Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save KonstantinosSykas/dfe4c5e392e299ab9341d6e16299454f to your computer and use it in GitHub Desktop.
Save KonstantinosSykas/dfe4c5e392e299ab9341d6e16299454f to your computer and use it in GitHub Desktop.
Download all workouts from sports-tracker
// based entirely on this blog post:
// http://druss.co/2016/04/export-all-workouts-from-sports-tracker/
// unfortunately the original script no longer works, moslty because jQuery is
// no longer available on sports-tracker pages.
//
// I've compiled the changes proposed in the comments in the script below.
// to use the script, login to your sports-tracker account
// change URL to http://www.sports-tracker.com/diary/workout-list
// open browser console (Cmd-Shift-I)
// paste the script, hit enter - it'll run and print something like this to the cosole:
// curl -o SportsTracker-<..id..>.gpx "http://www.sports-tracker.com/apiserver....."
// right-click on the colsole and save the contents to a file, call it download-all-workouts.sh
// open terminal, change to the directory where you saved the contents of the console
// edit the file - remove the javascript at the beginning of the file leaving only curl commands
// fix permissions:
// $>chmod +x download-all-workouts.sh
// run the script:
// $>./download-all-workouts.sh
// KonstantinosSykas 2020-04-21:
// (1) Server name for exports has changed from 'www.sports-tracker.com' to
// 'api.sports-tracker.com'.
// (2) Updated code to include activity type and date in the filename.
// (3) To export in .fit format, in the URL path replace the 'exportGpx' with
// 'exportFit' (without quotes) and replace the filename suffix '.gpx'
// with '.fit' accordingly.
// (4) All of the above tested successfully on Win10/PowerShell with Chrome.
var key = "sessionkey=";
var valueStartIndex = document.cookie.indexOf(key) + key.length;
const token_len = 32;
var token = document.cookie.substr(valueStartIndex, token_len);
function downloadOne(item) {
// Get activity type
var activities = ["Walking", "Running", "Cycling", "CrossCountrySkiing", "Other1", "Other2", "Other3", "Other4", "Other5", "Other6", "MountainBiking", "Hiking", "RollerSkating", "AlpineSkiing", "Paddling", "Rowing", "Golf", "Indoor", "Parkour", "BallGames", "OutdoorGym", "PoolSwimming", "TrailRunning", "Gym", "NordicWalking", "HorsebackRiding", "Motorsports", "Skateboarding", "WaterSports", "Climbing", "Snowboarding", "SkiTouring", "FitnessClass", "Soccer", "Tennis", "Basketball", "Badminton", "Baseball", "Volleyball", "AmericanFootball", "TableTennis", "RacquetBall", "Squash", "Floorball", "Handball", "Softball", "Bowling", "Cricket", "Rugby", "IceSkating", "IceHockey", "Yoga", "IndoorCycling", "Treadmill", "Crossfit", "Crosstrainer", "RollerSkiing", "IndoorRowing", "Stretching", "TrackAndField", "Orienteering", "StandupPaddling", "MartialArts", "Kettlebell", "Dancing", "SnowShoeing", "Frisbee", "Futsal", "Multisport", "Aerobics", "Trekking", "Sailing", "Kayaking", "CircuitTraining", "Triathlon", "Undefined1", "Cheerleading", "Boxing", "ScubaDiving", "FreeDiving", "AdventureRacing", "Gymnastics", "Canoeing", "Mountaineering", "TelemarkSkiing", "OpenwaterSwimming", "Windsurfing", "KitesurfingKiting", "Paragliding", "Undefined2", "Snorkeling", "Surfing", "Swimrun", "Duathlon", "Aquathlon", "ObstacleRacing", "Fishing", "Hunting"];
var activity_type_id = item.children[0].attributes[1].value;
var activity_type = activities[activity_type_id];
// Get activity date and convert it to YYYYMMDD format
var activity_summary = item.innerText.substr(item.innerText.indexOf('\n') + 1);
var activity_date= activity_summary.substr(0, activity_summary.indexOf('\n'));
var activity_year = activity_date.substr(activity_date.lastIndexOf(',') + 2, 4);
var activity_month = '00';
switch(activity_date.substr(0, 3)) {
case 'Jan':
activity_month = '01';
break;
case 'Feb':
activity_month = '02';
break;
case 'Mar':
activity_month = '03';
break;
case 'Apr':
activity_month = '04';
break;
case 'May':
activity_month = '05';
break;
case 'Jun':
activity_month = '06';
break;
case 'Jul':
activity_month = '07';
break;
case 'Aug':
activity_month = '08';
break;
case 'Sep':
activity_month = '09';
break;
case 'Oct':
activity_month = '10';
break;
case 'Nov':
activity_month = '11';
break;
case 'Dec':
activity_month = '12';
break;
}
var activity_day = activity_date.substr(4, 2);
var twodigits = activity_day.lastIndexOf(',') - 1;
if (!twodigits) {
activity_day = '0' + activity_day[0];
}
activity_date = activity_year + activity_month + activity_day;
var href = item.href;
var id = href.substr(href.lastIndexOf('/') + 1, 24);
var url = 'http://api.sports-tracker.com/apiserver/v1/workout/exportGpx/' + id + '?token=' + token;
var filename = 'SportsTracker-' + activity_type + '-' + activity_date + '-' + id + '.gpx';
console.log('curl -o ' + filename + ' "' + url + '";sleep 2');
}
function loopThroughItems(items)
{
var i = 0;
for (i = 0; i < items.length; i++) {
downloadOne(items[i]);
}
}
var items = document.querySelectorAll("ul.diary-list__workouts li a");
document.body.innerHtml = '';
loopThroughItems(items);
@KonstantinosSykas
Copy link
Author

In case you still have issues, various workarounds can be found in the comments posted at @devalls code.

@xpat3000
Copy link

xpat3000 commented Jun 1, 2020

Hi @KonstantinosSykas , I'm able to generate the list of my workouts, but when trying to run it in PS on W10, I'm getting this error:
image Any idea what to do? Thanks.

@KonstantinosSykas
Copy link
Author

Hi @xpat3000, I have updated code line 35 and I have checked that it has been fixed.
It seems that something changed in the page source code and it could not get the sessionkey.
Try with the updated code and you should be fine getting your training exports.

@xpat3000
Copy link

Thanks a lot for help @KonstantinosSykas, I have worked it out in parallel. With valid sessionkey everything works. All exported/imported ;)

@henzels
Copy link

henzels commented Jun 12, 2020

Fault must be on my part if it worked yesterday, maybe anybody can help: all files are being made but 1KB and only containing:

<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.10.2</center>
</body>
</html>

Can it be a permission error from the script? @KonstantinosSykas

@KonstantinosSykas
Copy link
Author

It seems they are making some updates and their load-balancer has two versions of the page. I have made some changes trying to overcome this.
However, @henzels, I have not received the error you get. What is your platform (O/S and browser versions)? Try the updated version and let me know.

@henzels
Copy link

henzels commented Jun 12, 2020

@KonstantinosSykas (great fast response :)). I think the fault was mine. Tried it with updated version, but still got the same output via script. However, I just tried pasting all curl lines into powershell and that did the trick! No script needed (168 workouts exported successfull, maybe there is a powershell limit for lines to paste though if you have more). Thank you, I suppose it is a permission issue for the script. Win10, Edge-chromium and chrome.

@GoNzCiD
Copy link

GoNzCiD commented Sep 25, 2020

Hi @KonstantinosSykas, it fails for me using curl right now. Using wget instead curl it downloads correctly.

@djcb
Copy link

djcb commented Apr 9, 2021

--- sports-tracker-download.js.orig	2021-04-09 09:12:49.591026316 +0300
+++ sports-tracker-download.js	2021-04-09 09:12:08.033536281 +0300
@@ -93,7 +93,7 @@
 
     var href = item.href;
     var id = href.substr(href.lastIndexOf('/') + 1, 24);
-    var url = 'http://api.sports-tracker.com/apiserver/v1/workout/exportGpx/' + id + '?token=' + token;
+    var url = 'https://api.sports-tracker.com/apiserver/v1/workout/exportGpx/' + id + '?token=' + token;
 	var filename = 'SportsTracker-' + activity_type + '-' + activity_date + '-' + id + '.gpx';
     console.log('curl -o ' + filename + ' "' + url + '";sleep 2');
 }

@KonstantinosSykas
Copy link
Author

@GoNzCiD @djcb
I tried the code again on Win10 with Chrome Version 89.0.4389.114 (Official Build) (64-bit) and it still works as it is. The only issue I encountered was with Firefox 87.0 (64-bit) where the output curl line did not give the full url path but it was shortened using <...> making it unusable.

@witekbobrowski
Copy link

witekbobrowski commented Apr 14, 2021

Hi! So the script worked fine but I keep getting the 301 Moved Permanently error when calling the url with curl. It works fine when pasted into the browser tho. Do I need to set some headers or something like that?

<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>Microsoft-Azure-Application-Gateway/v2</center>
</body>
</html>

Im on macOS BigSur. Thanks!

@djcb
Copy link

djcb commented Apr 14, 2021

Apply that patch, or manual alternatively, search-replace the http: with https:. Without it, I saw the 301 error, but with it, it works.

@witekbobrowski
Copy link

I have tried that, nothing changes :<

@KonstantinosSykas
Copy link
Author

KonstantinosSykas commented Apr 16, 2021

@witekbobrowski please do me a favor and paste here one of the curl lines you get. Since this is a public thread, obscure your sports-tracker username and perhaps a part of the sessionid or any other personal info.

@witekbobrowski
Copy link

witekbobrowski commented Apr 16, 2021

Here it is:

...
curl -o SportsTracker-Walking-<id>.gpx "http://api.sports-tracker.com/apiserver/v1/workout/exportGpx/<id>?token=<token>";sleep 2
...

I get all 459 of these, matching my workout number on the website

Tried it both with http:// and https://

@sz03436
Copy link

sz03436 commented Apr 16, 2021

replacing http with https does the trick for me

@yorwosP
Copy link

yorwosP commented May 12, 2021

I have replaced curl -o ... with curl -L -o ... (-L option used to follow redirects)
It seems to work for me

@witekbobrowski
Copy link

I have replaced curl -o ... with curl -L -o ... (-L option used to follow redirects)
It seems to work for me

Thanks! I tried it with curl -L -o and it worked!

@bobika99
Copy link

Has anyone tried running the script lately? I'm getting a 403 error.

@KonstantinosSykas
Copy link
Author

KonstantinosSykas commented Aug 30, 2022

Hi @bobika99 , I just tried it successfully on a Win10 Pro (21H1) using Chrome Version 104.0.5112.102 (Official Build) (64-bit).

EDIT: I succesfully executed the curl command in Windows PowerShell and visually checked the .gpx at GPS Visualizer online service.

@KonstantinosSykas
Copy link
Author

KonstantinosSykas commented Aug 31, 2022

Hi @bobika99,

I thought a bit more on that 403 error and a scenario came up where your case could have something to do with exceeded quota while hitting the sports-tracker api server or service.

What you could do, if that's the case, is to avoid exporting all your workouts at once. Split them in smaller groups and execute them one group at a time (or execute each group during different hours in a day, or even next day; I don't know how the quota could be configured by the sports-tracker web admin).

I tried to simulate the case exporting a larger group of workouts. There was no problem exporting 364 of them (sorry, I don't have more to test). I wonder how many workouts you are trying to export or if you have fiddled a bit with the sleep command of the script.

Drop a note to share the outcome of your attempts.

@bobika99
Copy link

I'm sorry, but it was my fault. I used the command line instead of powershell.

@KonstantinosSykas
Copy link
Author

@bobika99 excellent news! Have a great day! 🥳

@DeR-RoN
Copy link

DeR-RoN commented Mar 1, 2023

Worked like a charm with Chrome under Win11 Pro 22H2! Thank you very much! Now that Sports Tracker has gone Premium on all of their usefull features its time finally export all my workouts and move on. 😄

EDIT: With 450+ workouts, I copy-pasted 100 lines directly into the powershell prompt, executed them, and repeated the process until all workouts were downloaded.

@KonstantinosSykas
Copy link
Author

@DeR-RoN it's good that this still works. 💪

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment