Code Monkey home page Code Monkey logo

garmin-connect-export's Introduction

garmin-connect-export

Download a copy of your Garmin Connect data, including stats and GPX tracks.

Description

This script will backup your personal Garmin Connect data. All downloaded data will go into a directory called YYYY-MM-DD_garmin_connect_export/ in the current working directory. Activity records and details will go into a CSV file called activities.csv. GPX files (or whatever format you specify) containing track data, activity title, and activity descriptions are saved as well, using the Activity ID.

If there is no GPS track data (e.g., due to an indoor treadmill workout), a data file is still saved. If the GPX format is used, activity title and description data are saved. If the original format is used, Garmin may not provide a file at all and an empty file will be created. For activities where a GPX file was uploaded, Garmin may not have a TCX file available for download, so an empty file will be created. Since GPX is the only format Garmin should have for every activity, it is the default and preferred download format.

If you have many activities, you may find that this script crashes with an "Operation timed out" message. Just run the script again and it will pick up where it left off.

Usage

You will need a little experience running things from the command line to use this script. That said, here are the usage details from the --help flag:

usage: gcexport.py [-h] [--version] [--username [USERNAME]]
                   [--password [PASSWORD]] [-c [COUNT]]
                   [-f [{gpx,tcx,original}]] [-d [DIRECTORY]] [-u]

optional arguments:
  -h, --help            show this help message and exit
  --version             print version and exit
  --username [USERNAME]
                        your Garmin Connect username (otherwise, you will be
                        prompted)
  --password [PASSWORD]
                        your Garmin Connect password (otherwise, you will be
                        prompted)
  -c [COUNT], --count [COUNT]
                        number of recent activities to download, or 'all'
                        (default: 1)
  -f [{gpx,tcx,original}], --format [{gpx,tcx,original}]
                        export format; can be 'gpx', 'tcx', or 'original'
                        (default: 'gpx')
  -d [DIRECTORY], --directory [DIRECTORY]
                        the directory to export to (default: './YYYY-MM-
                        DD_garmin_connect_export')
  -u, --unzip           if downloading ZIP files (format: 'original'), unzip
                        the file and removes the ZIP file

Examples: python gcexport.py --count all will download all of your data to a dated directory.

python gcexport.py -d ~/MyActivities -c 3 -f original -u --username bobbyjoe --password bestpasswordever1 will download your three most recent activities in the FIT file format (or whatever they were uploaded as) into the ~/MyActivities directory (unless they already exist). Using the --username and --password flags are not recommended because your password will be stored in your command line history. Instead, omit them to be prompted (and note that nothing will be displayed when you type your password).

Alternatively, you may run it with ./gcexport.py if you set the file as executable (i.e., chmod u+x gcexport.py).

Of course, you must have Python installed to run this. Most Mac and Linux users should already have it. Also, as stated above, you should have some basic command line experience.

Data

This tool is not guaranteed to get all of your data, or even download it correctly. I have only tested it out on my account and it works fine, but different account settings or different data types could potentially cause problems. Also, because this is not an official feature of Garmin Connect, Garmin may very well make changes that break this utility (and they certainly have since I created this project).

If you want to see all of the raw data that Garmin hands to this script, just print out the contents of the json_results variable. I believe most everything that is useful has been included in the CSV file. You will notice some columns have been duplicated: one column geared towards display, and another column fit for number crunching (labeled with "Raw"). I hope this is most useful. Some information is missing, such as "Favorite" or "Avg Strokes." This is available from the web interface, but is not included in data given to this script.

Also, be careful with speed data, because sometimes it is measured as a pace (minutes per mile) and sometimes it is measured as a speed (miles per hour).

Garmin Connect API

This script is for personal use only. It simulates a standard user session (i.e., in the browser), logging in using cookies and an authorization ticket. This makes the script pretty brittle. If you're looking for a more reliable option, particularly if you wish to use this for some production service, Garmin does offer a paid API service.

History

The original project was written in PHP (now in the old directory), based on "Garmin Connect export to Dailymile" code at http://www.ciscomonkey.net/gc-to-dm-export/ (link has been down for a while). It no longer works due to the way Garmin handles logins. It could be updated, but I decided to rewrite everything in Python for the latest version.

Contributions

Contributions are welcome, particularly if this script stops working with Garmin Connect. You may consider opening a GitHub Issue first. New features, however simple, are encouraged.

License

MIT © 2015 Kyle Krafka

Thank You

Thanks for using this script and I hope you find it as useful as I do! 😄

garmin-connect-export's People

Contributors

jowiho avatar kjkjava avatar sclub avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

garmin-connect-export's Issues

Errors starting the py-script

New to Python I installed python 3.7.0, thought it should be easy to get output by the gcexport.py-script.

Unfortunately Python demands a lot of parantheses that seem to be missing after the print-commands of gcexport.py.
After introducing "( )" I got the next error (just trying the "-h"):
"ImportError: cannot import name 'urlencode' from 'urllib' (C:\Users\Gerald\AppData\Local\Programs\Python\Python37\lib\urllib_init_.py)"

This init-file is empty.
Is there something else necessary that the py-script runs?

Best regards
beta-L-user

Unable to download GPX or TCX

Works using the -f original flag but GPX or TCX files throw error:

Welcome to Garmin Connect Exporter!
Garmin Connect activity: [2495363004] Treadmill Running
	Tue, Feb 13, 2018 4:59 AM, 00:30:02, 3.40 Miles
	Downloading file...
Traceback (most recent call last):
  File "gcexport.py", line 231, in <module>
    raise Exception('Failed. Got an unexpected HTTP error (' + str(e.code) + ').')
Exception: Failed. Got an unexpected HTTP error (410).

post-auth url

hello, it's not an issue per say

But after I failed for hours to implements login to garmin connect through python requests for a little upload .fit files cli I'm currently writing (https://github.com/euri10/gols), I found your code.

And I still can't explain why that url_gc_post_auth = 'https://connect.garmin.com/post-auth/login?' works wonderfully.

Now it bugs me, because when browsing with chrome dev tools, or looking at the way it connects in Burp, or even trying to debug the redirects in requests, I never ever saw that url...never ever!!

So it works, it's cool, but out of curiosity, how did you manage to find it ? is it from the old site ?
well sorry for the non-issue here, but that bugs me, I'd like to understand

Garmin new UI statistics

The URL containing all activities (statistics) returns 0 results.

File "/usr/src/app/garmin_connect_export/gcexport.py", line 1218, in main
total_to_download = int(userstats_json['userMetrics'][0]['totalActivities'])
KeyError: 'userMetrics'

login to garmin successds though. Does anyone experience the same issue

HTTP Error 404

I've used this occasionally, but it seems to be broken now. Here's the traceback:

Traceback (most recent call last):
File "./gcexport1.py", line 120, in
http_req(url_gc_post_auth + 'ticket=' + login_ticket)
File "./gcexport1.py", line 71, in http_req
response = opener.open(request, data=post) # This line may throw a urllib2.HTTPError.
File "/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 435, in open
response = meth(req, response)
File "/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 548, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 473, in error
return self._call_chain(*args)
File "/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 407, in _call_chain
result = func(*args)
File "/usr/local/Cellar/python/2.7.13_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 556, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 404: Not Found

Payment required

Ever since February 23, I'm getting a message from the Garmin api while using this that a payment is required and it doesn't complete.

Requesting Login ticket... Done. Ticket=ST-0234665-GucJ5WoJWl7eA30ye9Fr-cas
Authenticating... Done.
[ERROR] Failed to reach url https://connect.garmin.com/modern/proxy/activitylist-service/activities/search/activities?start=0&limit=20, error: HTTP Error 402: Payment Required
Querying list of activities 1..20...Traceback (most recent call last):
File "C:\admintools\garmin-connect-export-3.0.2\gcexport.py", line 1061, in
main(sys.argv)
File "C:\admintools\garmin-connect-export-3.0.2\gcexport.py", line 941, in main
result = http_req_as_string(URL_GC_LIST + urlencode(search_params))
File "C:\admintools\garmin-connect-export-3.0.2\gcexport.py", line 271, in http_req_as_string
return http_req(url, post, headers).decode()
File "C:\admintools\garmin-connect-export-3.0.2\gcexport.py", line 247, in http_req
response = OPENER.open(request, data=post)
File "C:\Users\mediaserver\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 523, in open
response = meth(req, response)
File "C:\Users\mediaserver\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 632, in http_response
response = self.parent.error(
File "C:\Users\mediaserver\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 561, in error
return self._call_chain(*args)
File "C:\Users\mediaserver\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 494, in _call_chain
result = func(*args)
File "C:\Users\mediaserver\AppData\Local\Programs\Python\Python39\lib\urllib\request.py", line 641, in http_error_default
raise HTTPError(req.full_url, code, msg, hdrs, fp)
urllib.error.HTTPError: HTTP Error 402: Payment Required

How to download past 100th most recent activity?

I see that the script only pulls GPX data up to the 100th most recent activity. I also understand that Garmin only allows up to 100 downloads at one time. How do I edit the script, or can you post an edited script that allows me to enter a range of indices (e.g. 300 - 400 [for the 300th to 400th most recent activities]) so that I can download all of my activities. Thanks

Error 403 forbidden

Hey,

first of all thanks for the nice tool! I've been using it for some months now. Unfortunately, since yesterday(?) I get the following error regardless of the parameters I use. The password and username are correct. I verified it via Garmin Connect web interface:

Welcome to Garmin Connect Exporter!
Warning: Output directory already exists. Will skip already-downloaded files and append to the CSV file.
Traceback (most recent call last):
File "gcexport.py", line 155, in
result = http_req(url_gc_search + urlencode(search_params))
File "gcexport.py", line 70, in http_req
response = opener.open(request, data=post) # This line may throw a urllib2.HTTPError.
File "/usr/lib/python2.7/urllib2.py", line 410, in open
response = meth(req, response)
File "/usr/lib/python2.7/urllib2.py", line 523, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python2.7/urllib2.py", line 442, in error
result = self._call_chain(_args)
File "/usr/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(_args)
File "/usr/lib/python2.7/urllib2.py", line 629, in http_error_302
return self.parent.open(new, timeout=req.timeout)
File "/usr/lib/python2.7/urllib2.py", line 410, in open
response = meth(req, response)
File "/usr/lib/python2.7/urllib2.py", line 523, in http_response
'http', request, response, code, msg, hdrs)
File "/usr/lib/python2.7/urllib2.py", line 448, in error
return self._call_chain(_args)
File "/usr/lib/python2.7/urllib2.py", line 382, in _call_chain
result = func(_args)
File "/usr/lib/python2.7/urllib2.py", line 531, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 403: Forbidden

Any changes on Garmin side? Can you reproduce the problem or do I have canged something here that I am not aware of atm?

possible to export daily sleep data?

Garmin makes sleep data (part of the "daily summary") available for export as a zipped fit file.

Would it be possible to make this script also backup that data?

The url garmin connect fetches from is

https://connect.garmin.com/modern/proxy/download-service/files/wellness/2016-08-28

I guess I could make a second copy of the script, edit the variable url_gc_original_activity and change /activity/ to /wellness/ and it might work

Update URL paths

Thank you for making this. As Garmin Connect has been updated, can you update the HTTP path's to extract data?

UnicodeEncodeError for ø

When downloading activities, the script crashes on activities with "ø" in the name.
Error message:

File`"gcexport.py", line 186, in
print a['activity']['activityName']['value']
File "C:\Anaconda2\lib\encodings\cp437.py", line 12, in encode
return codecs.charmap_encode(input,errors,encoding_map)
UnicodeEncodeError: 'charmap' codec can't encode character u'\xf8' in position 1: character maps
to <undefined>

Tracked it to the
json_results = json.loads(result) on line 169 (or in that area if I have changed the script slightly). Basically writing or printing the result variable shows the ø properly in files or on screen, but the "json_results"-dict shows a unicode stringfor the acitivityName as this

{u'value': u'H\xf8vik Cycling'}

Tested with
print a['activity']['activityName']['value'].encode('utf-8') (also other encodings without luck) but it produces a weird character.

Anyone know how to fix it?

Downloading TCX Files

Hi,

I tried downloading a tcx file using this script.

When doing so, I get a very different TCX file than the one I get when downloading the tcx file manually (from the activity itself).

Has anyone tried this and knows how to get the same file as the one you download in the activity?

Thanks.

Exception: Failed. Got an unexpected HTTP error (410)

When I try to download my Garmin Workouts, the last activity ist listed, then the Download of the file is tried and the I receive the following exception:

Traceback (most recent call last):
  File "./gcexport.py", line 231, in <module>
    raise Exception('Failed. Got an unexpected HTTP error (' + str(e.code) + ').')
Exception: Failed. Got an unexpected HTTP error (410).

Unexpected HTTP error (503)

Hi,

I'm using latest version of script.
I get
raise Exception('Failed. Got an unexpected HTTP error (' + str(e.code) + ').') Exception: Failed. Got an unexpected HTTP error (503).
when trying to run script. Last week everything was working.

I tried putting url (url_gc_gpx_activity + a['activity']['activityId'] + '?full=true) and I get
The requested endpoint is retired

URL for downloading through browser is https://connect.garmin.com/modern/proxy/download-service/export/gpx/activity/12691xxxxxx

Can't import .fit files

Hi, I'm a little new to your program and I received this error message when trying to import .fit files from my Garmin account.

I'm not sure how to fix it unfortunately. Any help would be greatly appreciated. Thanks a lot!
Matt

Traceback (most recent call last):
File "./gcexport.py", line 155, in
result = http_req(url_gc_search + urlencode(search_params))
File "./gcexport.py", line 70, in http_req
response = opener.open(request, data=post) # This line may throw a urllib2.HTTPError.
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 437, in open
response = meth(req, response)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 550, in http_response
'http', request, response, code, msg, hdrs)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 469, in error
result = self._call_chain(*args)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 656, in http_error_302
return self.parent.open(new, timeout=req.timeout)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 437, in open
response = meth(req, response)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 550, in http_response
'http', request, response, code, msg, hdrs)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 475, in error
return self._call_chain(*args)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib2.py", line 558, in http_error_default
raise HTTPError(req.get_full_url(), code, msg, hdrs, fp)
urllib2.HTTPError: HTTP Error 500: Internal Server Error

SSL Certificate Failure

The script fails for me with the following error message:
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:581)>

I'm using Debian Squeeze with an up-to-date ca-certificates package and have no trouble accessing connect.garmin.com via my browser with working SSL.

Any thoughts? I'm thinking I'd need to add the certificate for the Garmin API... Thanks for creating and sharing the script - it's a neat idea!

Error when exporting manually created files that are incomplete

I get an an error when extracting the downloaded zip file of a manually created event, where I (for example) forgot to add the event type. The downloaded zip file is then empty and unzipping it will not work. A simple workaround that does the trick for me (i.e. it ignores these cases) would be to add
if os.stat(data_filename).st_size > 0:
in line 300, before unzipping the file. Of course, it then completely ignores the file, but it will continue the bulk export.

Script crashes on non-gpx workouts when not using -f argument

Garmin Connect activity: [1892029351] Other
Wed, 2 Aug 2017 18:12, 00:33:18, 0.00 Miles
https://connect.garmin.com/modern/proxy/download-service/export/gpx/activity/1892029351?full=true
Downloading file...
Traceback (most recent call last):
File "gcexport.py", line 357, in
data = http_req(download_url)
File "gcexport.py", line 86, in http_req
raise Exception('Bad return code (' + str(response.getcode()) + ') for: ' + url)
Exception: Bad return code (204) for: https://connect.garmin.com/modern/proxy/download-service/export/gpx/activity/1892029351?full=true

Problem with german Umlauts when running as cron-job

Hi,
i have a lot of activities that contain the character "ö".
When running gcexport.py in a cron job i get the followin error:

Garmin Connect activity: [1127628337] Traceback (most recent call last):
File "./gcexport.py", line 174, in
print a['activity']['activityName']['value']
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf6' in position 1: ordinal not in range(128)

Is there anything i can do?

Regards,
Jörg

Error 410 and solution

Posting in case helpful. For a recent activity of mine, which I added to Connect manually, no GPX is available (see screenshot). Therefore with command-line defaults,

Traceback (most recent call last):
  File "./gcexport.py", line 231, in <module>
    raise Exception('Failed. Got an unexpected HTTP error (' + str(e.code) + ').')
Exception: Failed. Got an unexpected HTTP error (410).

When adding --format 'original', however, the export is successful.

Screenshot:

screenshot from 2017-02-08 14-07-10

Crashes with 404 error

Can only get through a couple workout files without seeing the following error. Restarting script will get me past the one file, but it crashed again a couple files later

(using https://github.com/moderation/garmin-connect-export/blob/master/gcexport.py)

Garmin Connect activity: [1953986132] Schenectady Running
Thu, Aug 31, 2017 7:57 AM, 00:17:43, 1.95 Miles
verboseprint
https://connect.garmin.com/modern/proxy/download-service/export/gpx/activity/1953986132?full=true
Downloading file... http exception
404
Traceback (most recent call last):
File "gcexport.py", line 394, in
raise Exception('Failed. Got an unexpected HTTP error (' + str(e.code) + ').')
Exception: Failed. Got an unexpected HTTP error (404).

Ticket Cookie

I'm wondering if Garmin has updated their privacy settings. I used your code back in February 2021 with no errors but when I tried running today, I get the following error:

Traceback (most recent call last):
File "gcexport.py", line 114, in
raise Exception('Did not get a ticket cookie. Cannot log in. Did you enter the correct username and password?')
Exception: Did not get a ticket cookie. Cannot log in. Did you enter the correct username and password?

Any thoughts on this? Thanks!

TypeError: cannot concatenate 'str' and 'int' objects

When downloading Workouts, the program reports an Exception:

        Downloading file...
Traceback (most recent call last):
  File "garmin-connect-export_moderation/gcexport.py", line 357, in <module>
    data = http_req(download_url)
  File "garmin-connect-export_moderation/gcexport.py", line 86, in http_req
    raise Exception('Bad return code (' + response.getcode() + ') for: ' + url)
TypeError: cannot concatenate 'str' and 'int' objects

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.