• Update: I quit using Endomondo some time ago and no longer maintain this script. If it still works, great! If it doesn’t and you can make it work for you, great! If you want to take it and maintain it, feel free to do so.

    Update 2: Stephen Casey has modified this script so it should work again. Please check out his website for a description and a link to the updated script.

    As many people around the world I like to do some exercise now and then, and when that exercise is running I save all my workouts to Endomondo. I have been doing this for over two years now, and have accumulated more than 300 workouts. Recently Endomondo decided to limit the amount of features available for free, and move them to a subscription part of the website. While I have no problems with paying for what I use, I consider it a bad move to start charging for features that used to be free. It doesn’t really affect me that much though, since I never used those features anyway. However, it got me thinking that should Endomondo decide to do something similar in the future, I won’t have the option to switch platform since they hold all my workout data. There is a possibility to export one workout at a time, but Endomondo clearly stated that a mass export function will not be available. I was not satisfied by this so I wrote a script to export all my workouts from Endomondo, and I am posting it here in case some of you want to get all your data back from Endomondo too. After all it’s YOUR data. The script is written in PHP and runs from the command line. For Windows I have put everything needed into a single file. For Linux  and OSX you need to install PHP yourself. Also, in order for the script to work you need to login in one of the following ways:

    1. Put your username and password in a file called secret.txt where the first line is the username and the second line is the password. This does not work with Facebook logins and also requires OpenSSL support in your PHP installation.
    2. Get the cookie used to authenticate you and put the cookie  (everything after “Cookie: ” or the entire line, it doesn’t matter) in a file called cookie.txt. You can get the cookie in several ways: With Wireshark, using Chrome: (F12, reload page in Endomondo, Network, click on one of the resources under headers) or with some extension like TamperData for Firefox.

    If both files exist, username and password authentication takes priority. The script will first download a list of all your workouts, then download the actual workouts. It will remember the the latest workout that was downloaded, so if you run it again at a later point in time, you will only get new workouts. You can modify the function generateFileName to change the filenames of the saved workouts. Disclaimer: This script worked for me. Endomondo can easily change something on their website so this script does not work anymore, so I offer no guarantee that it will work for you. Use this script at your own risk. You can download the script for Linux and OSX or you can download everything needed to run it under Windows. If you’re using Windows you should extract the Endomondo directory from the ZIP file and execute the file run.cmd. For any other OS you should just execute php getworkouts.php.

    Posted by Michael @ 09:07

64 kommentarer til Download all workouts from Endomondo

  • bart siger:

    Would i be correct in saying that this needs to run on a webserver? and cannot be performed from a general internet user’s PC?

  • Michael siger:

    No, it can run on any PC with PHP CLI installed. It has only been tested on Linux though, but should work fine under Windows as well.

  • bart siger:

    Should the $cookie value have just the __utma= value contained in the cookie header? or the whole header? seems to be rejecting my cookie over and over…

  • Michael siger:

    You should set $cookie to the contents of the Cookie header, meaning everything after “Cookie: ” (EDIT: This is no longer true).

    There might be other reasons for getting the “cookie might be invalid” message than an invalid cookie. Maybe Endomondo has changed something on their site, or maybe the layout is a bit different if you are a paying member or from a different country than me.

    I’ll look into some of these things another time.

  • Michael siger:

    Just checked and the script still works fine for me. I have updated it to only download new workouts since last time it was run successfully.

  • Karol siger:

    Michael, thanks a lot for your script.
    I was able to run it after some changes in the code and wanted to share to help others.
    Initially I had the same problem as bart: the script suggested that my cookie is invalid, but the problem really was in the socket implementation between Windows and Linux. I was running the code on Windows 7 (XAMMP, PHP 5.3.1.) and it turns out that the command socket_recv does not necessarily waits for the whole content. In most cases I was receiving only a header and had to use a loop to get the whole thing. I used an example from the official manual (part of the getUrl function):

    $read ='';
    while((socket_recv($socket, $buf, 1024,0))>0){
    $asc = ord(substr($buf, -1));
    if ($asc == 0) {
    $read .= substr($buf,0,-1);
    break;
    } else {
    $read.=$buf;
    }
    }
    socket_close($socket);
    return $read;

    After this problem was solved and I managed to get a list of workouts all the tcx and/or gpx files were downloaded empty (0 bytes). The problem was caused by illegal file names for windows which in turn was caused by incorrect date parsing. It was passed without a change as your comment in the code stated but commas are not accepted in file names on Windows… What worked for me (US settings) was:

    function formatDateTime($input) {
    $date = date_create_from_format("M j, Y g:i A", $input);
    return $date->format("Y-m-d H.i");
    }

    Hope that helps.
    Karol

  • Michael siger:

    Thanks Karol! Thanks for testing under Windows and I am happy that you got it to work.

    I have modified the script to use streams instead of accessing sockets directly. Hopefully this solved the different ways of handling sockets under Linux and Windows (Windows seemed to ignore the MSG_WAITALL flag). However, I haven’t tested this, but at least it still works under Linux 😉

    I also changed the filename to simply the workout ID. The other parameters are still provided so it’s easy to modify the function if one wants different filenames.

  • Luca siger:

    Thanks Michael for your script.
    I’ve just tried it on windows xp and php 5.2 and it worked (I only had to add the function http_chunked_decode that was not defined).
    A very good job!!

  • Michael siger:

    Great that it worked for you too, Luca!

    I have updated the script to get rid of the dependency on http_chunked_decode, since that was the hardest dependency to satisfy (it was included in pecl_http which was not standard on some distributions and had to be installed from source).

    To the best of my knowledge, the script no longer needs any special dependencies to run.

  • Bogdi Goie siger:

    Testes today 28/12/2012. Exported all my files on Mac OSX using terminal 😀 Awwessome! Cheers.

    It would be good to keep this script updated if anything happens in the futures if you want/have time but nevertheless, thanks a lot!

  • Michael siger:

    @Bogdi Goie: Cool! I can now add Mac OSX to the list 🙂 Currently I’m trying to keep the script up to date, and it has in fact been updated several times since I made this post.

  • Carl siger:

    Hi,
    In order to help out as many people as possible, I also created a script that runs directly in the browser. It requires the Greasemonkey extension (or Tampermonkey in Chrome). You can get it here: http://userscripts.org/scripts/show/128743

  • Dzidas siger:

    Thanks, it did the job on Linux. Now I have my data!

  • Karthick siger:

    Hi Michael,

    Thanks for the script! To see the cookie info, I did F12 and entered “alert(document.cookie);” in the Javascript console (Chrome).

    There is one issue however. http://www.endomondo.com/workouts/list now lists workouts in multiple pages (15 workouts per page), and I could download workouts for only the first page.

    Anyone else has this problem?

  • Michael siger:

    @Karthick Great and easy way of getting the cookie!

    I just tried and have the same issue. After a bit of debugging it turns out that Endomondo has changed their URLs in some places. Currently the workout URL change to a different format after the first 15 workouts.

    I have updated the script to take this behavior into account, while still keeping backwards compatibility should Endomondo decide to fix their website to return consistent URLs.

  • Karthick siger:

    Michael,

    Thanks a ton -- worked with the updated script!

    I know a bit of php (very little), planning to dig around your script. If the cookie part can be automated, then I can set up a cron job to run this script every two days or so.. Assuming Endomondo doesn’t keep changing the url encoding 🙂 Will post updates here.

  • Michael siger:

    Karthick,

    Great that it works now! I have cleaned up the code to handle the URLs and added a method to use username and password to login 🙂

  • fred1987 siger:

    Hi all
    First, thanks for your job Michael.. great job !!

    I have an issue with your sript : I use tampermonkey/chrome / windows XP
    The script seems running correctly : i can put the started date and the finish date, the selection of workout is ok.
    I see the “Export script running” just at the right top of the page, but I have no export files in my Downloads directory …

    do you have an idea ?

    Thanks
    Fred

  • Michael siger:

    @fred1987 My script does not have an option for start and finish date, neither does it show “Export script running”. I think you are trying to run something else than the export script I have created.

  • Salatiel siger:

    Hi, i am getting lots of:
    Attempting to download workout 94730665… Workout “Running” is not exportable.

    Some

  • Michael siger:

    @Salatiel It means just what it says: That workout is not exportable. Can you export that workout manually from Endomondo?

  • Salatiel siger:

    No, i just found out the export option is grey. I just can’t understand why. Basically happens for every training i do with gps disabled. Since i run on a treadmill i really dont care about gps location, but i’d like to export my heartrate data.

  • Michael siger:

    @Salatiel A few months ago Endomondo disabled exports of workouts without GPS data. Before that you could still download the workout with e.g. heart rate data.

  • Salatiel siger:

    Hi Michael, thanks !
    I’m really starting to hate Endomondo !
    Let me ask you a thing , would it be possible to two function to your script ?
    1) Delete all workouts
    2) Upload a TCX as a workout

  • Salatiel siger:

    @Michael: Fixing the sentence above: ‘would it be possible implement two new functions to your script ?’

  • Michael siger:

    @Salatiel Anything is possible 😉 However, this is not something I am going to implement as it does not really fit the purpose of the script.

    I do have a python script for uploading workouts to Endomondo. Throw me an e-mail if you’re interested in that.

  • Alejandro siger:

    Thanks!!!!! It works

  • Michael siger:

    Great Job! Works on Mac OSX!

    I just changed date to display files in right order!

    function generateFileName($workout, $sport, $datetime, $title, $desc, $type) {

    $search = ‘/(\d\d).(\d\d).(\d\d\d\d) (\d\d:\d\d)/’;
    $replace = ‘${3}.${2}.${1} ${4}’;

    $my_date = preg_replace($search, $replace, $datetime);

    $filename = $my_date.’.’.$sport.’.’.$title.’.gpx’;
    return $filename;
    }

  • Michel siger:

    Thanks for sharing this script. Have it working with xampp 2.5 on win 7.

  • rob siger:

    the script worked great! Thank you very much!

  • theis siger:

    Can’t get it to work it says: Attempting to get ID of workout 1… could not find workout ID.
    Got an empty workdout ID. This should not happen so we’re bailing out. Exiting

  • Ben siger:

    Hi Michel,

    Im having trouble with the script.
    On both windows and OSX i cannot get it to work.

    If im using the login method I get “login failed Exiting” I defiantly know my UN and PW are correct and can log into endomondo with the same details

    If using the cookie method, I get invalid cookie..

    Any help appreciated…

  • Michael siger:

    @theis @Ben Works for me so there is no way for me to debug those issues. At the very least I need a complete dump of the HTTP conversation with the server.

  • Ben siger:

    Ok, how do I do that?

    I originally thought it may be due to a heavily filtered internet connection at work but I’m at home now and its still not working 🙁

    This is a normal login by the way not a facebook one

  • Mike siger:

    Tried this, and works good, except it only identifies 15 workouts…

  • Mike siger:

    Nevermind, worked in IE.. not in Chrome

  • Michael siger:

    @Mike You are commenting on the wrong script. My script does not run in a browser.

  • Adrian siger:

    Thanks for the script all working now. It fails downloading the workout files if there is not a workouts directory in the current directory but it is not obvious what the name of the directory to create is from the error message, unless you look through the code.
    Adrian.

  • Owen siger:

    Hey mate,

    Thank-you SO MUCH for this!

    The PHP version works fantastically!

  • Janek siger:

    Hi
    Sadly this seems not to work for me. Symptoms are:

    ...
    Attempting to get ID of workout 565... Got 3117906
    Attempting to get ID of workout 566... Got 3057950
    Attempting to download workout 3057950... Invalid or missing workout data for workout "Running". This is normal for some workouts with no track information.
    Attempting to download workout 3117906... Invalid or missing workout data for workout "Running". This is normal for some workouts with no track information.
    ...

    And zero files are downloaded. Directory ‘Workouts’ is made.

    Additional info:
    * If not all, then almost all workouts should have GPS locations. I can download these one by one from the web.
    * I’m using Windows version of the script you are providing
    * I’m using cookie-based login.
    * I’m not a subscriber
    * I’m using english version of the site.

    Any ideas what is wrong?

  • Luciano A. Ferrer siger:

    Same issue that Janek reported 🙁
    Maybe endomondo has changed the pages information, and that is because do not find the files?

    Using the secret.txt did not work (and openssl extension was on), no idea why… 🙁

  • wes siger:

    same as Janek and Luciano. I had this working in august, but now it’s not. new version?

  • Janek siger:

    I read the code and have some more comments. Excuse me if i’m wrong somewhere -- i’m not a developer:

    1. When i change from tcx to gpx in there, i get it running fine.
    downloadAllWorkouts($workouts, “gpx”, “Workouts”, false);

    2. When I insert some unknown export format, for example:

    function downloadAllWorkouts($workouts, $type = ‘ZZZ’, $directory = “”, $exit_if_file_exists = false) {

    I do not get an error, because in reality i should change it here:
    downloadAllWorkouts($workouts, “ZZZ”, “Workouts”, false);

    “$type = ‘ZZZ'” sould maybe be simply “$type” -- it’s somewhat confusing when it does not change anything.

    3. added some debug code to find out what is wrong with tcx export. Maybe this helps:
    -----------------------
    DEBUG $downloadstatus:
    enabled

    DEBUG $exportlink:
    ?wicket:interface=:842:pageContainer:lowerSection:lowerMain:lowerMainContent:workout:details:actions:ownActions:exportButton::IBehaviorListener:0:1

    DEBUG $downloadlink:
    ?wicket:interface=:842:pageContainer:lightboxContainer:lightboxContent:exportPanel:exportTcxLink:1:IResourceListener::

    Invalid or missing workout data for workout “Cycling, transport”. This is normal for some workouts with no track information.
    -----------------------

    4. Changed file name format. I hope there is more elegant way to do this.. Example: “2013-10-06 Running 9613900.gpx”

    function generateFileName($workout, $sport, $datetime, $title, $desc, $type) {
    $search = ‘/(\w+) (\d+), (\d\d\d\d) (\w+)/’;
    $replace = ‘${1}-${2}-${3} ${4}’;
    $my_date = preg_replace($search, $replace, $datetime); // “Oct 6, 2013 2:12 PM” -> “Oct-6-2013 2:12 PM”
    $my_date = substr($my_date, 0, strpos($my_date, ” “)); // “Oct-6-2013 2:12 PM” -> “Oct-6-2013”
    date_default_timezone_set(‘UTC’);
    $my_date = date(“Y-m-d”, strtotime($my_date)); // “Oct-6-2013” -> “2013-10-06”
    $filename = $my_date.’ ‘.$sport.’ ‘.$workout.’.’.$type; // “2013-10-06 Running 9613900.gpx”
    return $filename;
    }

  • Janek siger:

    4. A bit less buggy and absurd:

    function generateFileName($workout, $sport, $datetime, $title, $desc, $type) {
    date_default_timezone_set(‘GMT’);
    $date = DateTime::createFromFormat(‘M j, Y g:i A’, $datetime)->format(‘Y-m-d’);
    $filename = $date.’ [‘.$workout.’] ‘.$sport.’.’.$type;
    return $filename;
    }

    Produces filenames like: “2013-09-19 [247715200] Running.gpx”

  • Paul siger:

    Thanks Michael,

    I had to make a couple of changes to the script to have it do what I wanted.

    Logon with the cookie worked, but secret.txt did not.

    To fix the following error message
    Invalid or missing workout data for workout “Running”. This is normal for some workouts with no track information.
    I changes the following code

    $workouts = getAllWorkoutIds();
    downloadAllWorkouts($workouts, “gpx”, “Workouts”, false);

    Also to ensure the download worked properly, it is important to update the cookie.txt file immediately before running the script, otherwise an error is given.

    Also I tried copying and pasting Janeks code into the script using notepad. This proved impossible for reasons I could not figure out until I looked at the script in ‘Notepad ++’. As the copy and paste interpreted one of the inverted commas as a ‘special character’ changing the string.
    Once I debugged this error in notepad ++ It worked perfectly 🙂

  • Michael siger:

    @Janek

    1. Yeah, Endomondo seems to have changed something so exporting tcx files doesn’t work anymore. Since they messed up the tcx files anyway, I just disabled the use of tcx.

    2. You tried to change the default value if the parameter was not specified, and then you called the function with a value for that parameter. Of course that didn’t do anything.

    3. No that doesn’t help.

    4. …

  • Lars siger:

    works perfect for me -- windows, firefox, tamper, cookie login

  • Henrik Kirk siger:

    Still works -- thx

  • Brynn siger:

    Hi there,

    I’m trying to get it to work, but I’m afraid I’m running into problems from the get go. I’ve tried giving it my username and password, and the cookie.txt file. The secret.txt file is rejected because I don’t have OpenSSL running, which I can’t seem to get to work (I tried installing XAMPP to no avail).

    The cookie issue is that when I try to export it, I can’t seem to get it in a format the script wants. I can export a bunch of text that has things like utma and utmb and so on, but it doesn’t want that. Do you have an extension, for either firefox or chrome, and instructions on how to properly extract and format the cookie for the script to parse?

  • loic siger:

    Hi,

    It seems I have the same problem that Brynn. I completly unable to correctly connect to endomondo.
    For every try, the connection is fine but the answer from the server has a ‘login’ location instead of ‘home’ so the script can not go further.
    This is an example of cookie I use:
    __utma=162144232.712511631.1365970551.1395340169.1395347875.6; __utmz=162144232.1395167935.2.1.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); __gads=ID=1358daa29b0a22b2:T=1395167934:S=ALNI_MYS3ovqeN0Pd5_xdqfOTKgrVldieQ; workout-map_map_pos={\”center\”:{\”lat\”:46.44517918554257,\”lng\”:2.3762494999999717},\”zoom\”:5}; JSESSIONID=6C51CB8743E32544187741A8B9122D81; AWSELB=87FBB1DF06CB5333011593EA47F6302B44EB6F00A1D3E8AB951D2C5BDD683F85012B46BD5868B846976C1C64BF49543231BBA7A87AFA89C994C59DF5361884590554AEA794696CDD28E99D1F974FC597097FC44DE9; __utmc=162144232; __utmb=162144232.18.10.1395347875; EndomondoApplication_USER=XXXXXX%40gmail.com; EndomondoApplication_AUTH=s-2wO3*Ym5Gmxuq0Xpd3d2dsEn4

    Is there something wrong in it?

    Thanks,

    Loïc

  • Kristian siger:

    Hi,If you happen to have an iPhone this App can help you get to your data: https://rungap.zendesk.com/entries/45048583-Using-Endomondo-with-RunGap

  • Riadh siger:

    Doest this script still works?

  • RVB siger:

    Which cookie to use, please specify? Username & password in secret.txt doesn’t work.

  • […] someone’s (Michael Østergaard Pedersen) come to the rescue and has written a script that sets my data free.  Sadly, it it didn’t quite work.  Rather than giving up and finding […]

  • Stephen Casey siger:

    Hi -- I just found and tried to run your script but it looks like Endomondo have noticed you (and/or maybe some others) and added some further rules to prevent us from getting our run data out of their site.

    There were a couple of problems:

    1/ The Cookie validity detection wasn’t quite right -- I’ve changed it to check if Endomondo try to set a cookie -- a good indicator that they’ve not received one they feel is valid.

    2/ They’ve introduced some rate limiting -- I’ve recursed the get and postUrl functions so they pause for 10 seconds every time they hit the limit.

    All should work well again now -- feel free (obviously) to take the script from my site and update it here.

    Find it attached to the following post

  • Michael siger:

    @Stephen Casey: Thanks for updating the script. I have added a link to your website from the original post. Hope it is OK.

  • Sebastian siger:

    I could login after I modified line 34 to:

    $buf = getLocationHeader(“/home”);

  • Ross siger:

    Thanks for the work.
    The updated/modified script from Stephen Casey worked perfectly.

    Thanks to both of you for the work.

  • dalla siger:

    the script downloads 417 of my 699 workouts. got alot of errors like “Workout Running is not exportable”.. Most of it seems to be Weight traning, but it also happend to yoga, running, fotball soccer, swimming etc etc… Its not all of each workout. I’ve exportet some of the weight traning workouts…. wierd stuff.. I’ve checked the script and found this:
    if ($downloadstatus == ‘disabled’) {
    echo “Workout \””.$sport.”\” is not exportable.\n”;

    dunno what downloadstatus==disable means… anyone?

  • dalla siger:

    Sorry for being lazy and not read all the comments.. I’ve just saw your answer about no position data and I am not able to export manually. Is this possible to fix? by adding position data etc. guess not… 🙁

  • Kirmonkey siger:

    This worked for me:

    https://support.endomondo.com/hc/en-us/articles/201861443-File-Import-Export?flash_digest=fe0f50ebc200cd8eeb716e7b7ade8cc091e63abb

  • 1 siger:

    Hi,

    looks like endomondo has REST API.

    You may list your workouts like this:

    $ curl https://www.endomondo.com/rest/v1/users//workouts?before=2016-03-11T20%3A59%3A59.999Z&after=2013-01-22T21%3A00%3A00.000Z | json_pp | grep id | awk ' { print $NF; } ' | tr -d ','

    And then export like this:

    for id in $(curl | json_pp | grep id | awk ' { print $NF; } ' | tr -d ','; do
    curl -o $id.gpx 'https://www.endomondo.com/rest/v1/users//workouts/${id}/export?format=GPX';
    done

    Your USER_ID and headers can be simply found in firebug, just press "copy as CURL" button on any request.

  • Konrad siger:

    What are you using now?
    Before the last update I used to love Nike Run. Tho, ever since the last update it hasn't been working properly :/
    Can't befriend Endomondo. I've tried multiple times, but I still can't get myself to like it :/

  • Michael siger:

    Currently I'm using Garmin Connect. I need a way to track my workouts and don't need all the social media features. Previously I tried Runkeeper and that seemed to work for me as well too.