{"id":20033171,"url":"https://github.com/dbr/garminsyncier","last_synced_at":"2025-06-14T09:06:11.761Z","repository":{"id":10099719,"uuid":"12162072","full_name":"dbr/garminsyncier","owner":"dbr","description":"A simple-but-robust Garmin Connect to Strava tool","archived":false,"fork":false,"pushed_at":"2021-03-21T23:21:39.000Z","size":345,"stargazers_count":2,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-14T09:04:13.463Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dbr.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-08-16T15:47:05.000Z","updated_at":"2024-07-18T07:42:10.000Z","dependencies_parsed_at":"2022-09-14T16:40:27.412Z","dependency_job_id":null,"html_url":"https://github.com/dbr/garminsyncier","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dbr/garminsyncier","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbr%2Fgarminsyncier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbr%2Fgarminsyncier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbr%2Fgarminsyncier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbr%2Fgarminsyncier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dbr","download_url":"https://codeload.github.com/dbr/garminsyncier/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dbr%2Fgarminsyncier/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259790457,"owners_count":22911547,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-13T09:44:47.380Z","updated_at":"2025-06-14T09:06:11.743Z","avatar_url":"https://github.com/dbr.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Garmin Connect to Strava auto-uploader\n\nYou probably want to use [CopyMySports.com](http://www.CopyMySports.com/)\ninstead.\n\nThis Python-based tool uploads all rides from a Garmin Sync account to\nStrava, preserving all data except temperature (including speed,\nelevation, heartrate, cadence, power)\n\n## Setup\n\nFirst copy `config.py.sample` to `config.py` and fill out the values.\n\nThen run the following commands routinely:\n\n    python -m garminsyncier grab\n    python -m garminsyncier mail\n\nThe first `grab` command should be run maybe every 10 minutes or so,\nto avoid annoying the Garmin Connect API.\n\nThe second `mail` command can be run more often, maybe every 1\nminute. It checks a directory for no files, and exits if none are\nfound.\n\n## How it works\n\nThe `grab` command downloads any new rides from Garmin Connect as a\n`.tcx` file. These are placed in `config.download_dir`.\n\nA ride is considered \"new\" if there is no file named `${ride_id}.gpx`\nor `${ride_id}.tcx` in either the `download_dir` or `sent_dir`\n\nThe `mail` command takes any `.tcx` or `.gpx` file in `download_dir`,\nand mails them to `upload@strava.com` (or any other address, really)\n\nAs long as `config.your_email` matches your Strava account address,\nthe ride will appear like any other.\n\n\nI ran the grab command every 10 minutes (avoid annoying Garmin's API),\nand the mail command every 1 minute (it's very quick\n\n\nNote that Garmin Connect `tcx` export does not include the temperature\ndata (which Strava may support in a `\u003cgpxtpx:atemp\u003e` tag on each track\npoint). The GPX format does include this data, but excludes power. You\ncan change format trivially in `garminconnect.py` (should really be a\nconfig option)\n\n\n## Why?\n\nI was attempting to cycle from Adelaide to Perth, and wanted to upload\nthe rides each day onto Strava...\n\nLeaving things quite late, I tried the now-defunct GarminSync a few\ndays before I left, but didn't trust it (mostly I didn't know how long\nit takes to spot new rides, and there was no logging when it last\ntried and so on)\n\n..so I wrote my own, simple and robust version if it in an evening.\n\nI ran it on a Rackspace \"cloud server\" VM, with the code, the logs,\nthe `download_dir` and `sent_dir` all located in Dropbox.\n\nThe code worked perfectly - I could check if it had uploaded the ride\nusing the Dropbox iOS application, comment on the ride with the Strava\napplication, and share the ride with family and friends on\nFacebook. All in the middle of rural Australia. Hurray for technology.\n\n(Oh, I made it as far as Ceduna after 4-and-a-bit days, before\ndeciding to head back)\n\n## Does it still work?\n\nProbably.\n\nIt worked as of 2013-07-20, running on Python 2.6. It does **not**\nrequire the now-dead Strava API v1 or v2 (nor the private v3)\n\nThe code itself is quite simple. The only parts likely to break are:\n\n* Garmin Connect's API. They are barely documented, and many of the\n  endpoints have multiple versions, all of which have varying levels\n  of usefulness. The API's have been around for a while, and multiple\n  old versions still active and working.\n* The `upload@strava.com` functionality might get removed, while this\n  is unlikely, I would have said the same thing about removing any\n  public-access to their proper API,\n  [but oh](http://www.dcrainmaker.com/2013/07/cutting-removing-functionality.html)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbr%2Fgarminsyncier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdbr%2Fgarminsyncier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdbr%2Fgarminsyncier/lists"}