Library / SDK
matin/garth avatar
matin/garth

Garth: a Garmin Connect client that stopped working when the login flow changed

[DEPRECATED] Garmin SSO auth + Connect Python client

820 stars74 forksPythonMIT

At a glance

What is it?
Garth was a Python library for the Garmin Connect API with OAuth authentication, and it is now deprecated, because Garmin changed their auth flow and broke the mobile authentication approach the library depended on. A saved OAuth1 token may keep working until it expires, roughly a year after it was issued, but no new login will succeed.
Who is it for?
Garth is worth reading as a reference implementation rather than as something to install, and it is worth reading precisely because it failed in a specific and instructive way. It is the wrong choice for any new project, since no new login will work and the maintainer has said they are not in a position to adapt to the change.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 138 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A library that stopped at the login screen

Garth was a Python library for Garmin Connect API access with OAuth authentication, and the repository now carries a deprecation notice at the top of the README.

The reason is stated in one sentence with no ambiguity: Garmin changed their auth flow, breaking the mobile auth approach that Garth depends on. The author adds that they are not in a position to dedicate the time to adapt to these changes, and points to an announcement discussion for the details. The README also says anyone is welcome to fork Garth as a starting point for a new library, which is the practical instruction for anyone who still needs this.

The failure mode is worth being precise about, because it is not the usual kind of library rot. Garth did not stop working because it was unmaintained, or because a dependency moved on, or because Garmin Connect's API endpoints changed shape. It stopped working because the authentication step itself was replaced, and the replacement was not compatible with the approach the library used.

The mobile auth approach, in essence, was a way of obtaining a session for a Garmin account through a flow designed for the phone apps, and the library wrapped that flow and then exchanged the result for OAuth tokens. When the flow changed, the wrapper no longer produced a valid token, and everything downstream of it failed with it.

What still works and for how long

The README has a short section titled For existing users, and it draws a boundary that is unusually useful to understand.

If you already have a saved session with a valid OAuth1 token, Garth may continue to work until that token expires, and the README puts the lifetime at about a year from when it was issued. New logins will not work.

So there are two distinct populations of users, and they are in very different positions. A user with a stored token has a working integration with an expiry date they can see, roughly a year from issuance. A user without one has nothing, because the only way to get a token is the login flow that no longer functions.

That distinction matters for planning. A team running Garth in production has a countdown rather than an outage, and the countdown is per token, so a fleet of accounts will expire at different times depending on when each was authenticated. The clock does not stop for anyone.

It is also a useful distinction for anyone evaluating the library for a new project. The library is not deprecated in the sense of being frozen while the world moves on. It is deprecated in the sense that one specific entry point has been closed and the other is on a timer.

The package shape and what the dependencies say

The pyproject.toml describes Garth as Garmin SSO auth + Connect client, authored by Matin Tamizi, and it is worth reading for what a client for this API actually consists of.

The runtime dependencies are requests, pinned to the 2.x series, pydantic and pydantic-settings in their 2.x series, requests-oauthlib at 1.3.1 or later, and logfire. The two OAuth related dependencies are the interesting ones. requests-oauthlib is the OAuth1 client that requests uses, and the OAuth1 mention in the README is not incidental, because OAuth1 is the older and more awkward of the two OAuth versions, and it is the one a client with a long-lived token would use.

pydantic and pydantic-settings mean the library models the Garmin API responses as validated types and takes its configuration from settings, which for an API client is a reasonable choice and explains why the package has a version where response shapes are typed.

logfire is the observability dependency, and its presence in a small client library is a sign of the era the library was written in.

The project requires Python 3.10 or newer and the classifiers list support for 3.10 through 3.14, on macOS, Windows, Linux and as OS independent. The development status classifier reads Development Status :: 7 - Inactive, which is the standard trove classifier for a project that has stopped.

The build system is hatchling with a dynamic version read from src/garth/version.py, and the release process uses release-it, with the changelog linked from the project URLs.

The project structure and the tooling

The repository layout is what a well-run Python project looks like, and it is worth noting even though the library itself is finished.

There is a src/ directory with the package, a tests/ directory, a docs/ directory, a colabs/ directory for Jupyter notebooks, an mkdocs.yml, and a pyproject.toml with a uv.lock, so the project used uv for dependency management. There is a .readthedocs.yaml, which is why the documentation is hosted on Read the Docs, and a .pre-commit-config.yaml, a .markdownlint.json, a .devcontainer/ directory, a .vscode/ directory, a .coderabbit.yaml and a CLAUDE.md.

The Makefile is adapted from the one in pydantic, which is a tell that the author followed a template rather than inventing one. It defines install, which installs the package in editable mode along with the dev, linting and testing dependency groups and sets up the pre-commit hooks, and sync, which reconciles the lockfile with uv sync. There are separate format and lint targets, both driven by ruff, and the lint target also runs ty, a type checker.

The test target runs pytest under coverage, and there are separate targets for an HTML coverage report and an XML report written to coverage/coverage.xml, which is the shape you need to feed a CI coverage service. The all target runs lint, codespell and testcov, which is the standard set of checks in CI.

The style configuration is strict in a way that suggests the author cared: ruff with a line length of 79, four space indent, target py310, and the lint rule set limited to E, F, I and UP, with no ignores. The pyproject also carries a tool.ty section that turns invalid-method-override into a warning rather than an error, which is a concession to a typing edge case.

Where Garth cannot be used

The first limitation is the simplest and the most important: new logins do not work, so the library cannot be used to start a new integration. Any evaluation that begins by writing a fresh login flow will fail, and it will fail in a way that looks like a bug in the library rather than a deliberate deprecation.

The second is the token expiry. A saved OAuth1 token is stated to last about a year from issue, and when it lapses the integration stops with no path to a new token. That makes Garth unsuited to any long-lived unattended service, since the service is guaranteed to break within a year and there is no way to renew it.

The third is that the maintenance is finished, not paused. The author says they are not in a position to dedicate the time to adapt, and the README calls v0.8.0 the final release. The repository is not archived, so the code and the documentation stay readable, but the library is not going to receive a fix when Garmin changes something else.

The fourth is that the ecosystem around it moved on. The README notes that Garth was translated into multiple programming languages, and each of those ports depended on the same mobile auth approach and therefore broke in the same way at the same time. A user of one of the ports rather than the Python original faces the same problem with a different library.

The fifth is the scope of what it did. Garth was a client for Garmin Connect, the consumer side of the Garmin ecosystem. It is not a substitute for the Garmin device SDK, and it does not cover activity data upload from devices, which the repository topics separate out under the garmin-sdk tag.

Garth compared with the official Garmin SDK and with a direct requests client

The official option is Garmin's own Connect Python SDK, and the difference in approach is who owns the auth flow. A vendor SDK is built by the company whose login flow changed, so when the flow changes the SDK is updated in step, and the client code does not have to know how the session is obtained. Garth was a third party reimplementation of that session acquisition, which is exactly the thing that broke.

The second comparison is writing the client directly against the API with requests. The Garmin Connect API is an ordinary HTTP API, and much of what Garth did was make the calls and parse the responses. A team that already has a session can plausibly write a thin client, and a team that does not has the harder problem, which is the login flow.

The third comparison is with the other community clients. The README says Garmin's change broke the mobile auth approach that Garth and other libraries depend on, which is the useful detail: the problem is not a Garth bug, and a different community library faces the same wall. That is why the announcement is the first thing to read, because it describes what actually changed and therefore what a replacement would have to do.

There is a fourth angle, which is what makes the deprecation instructive rather than merely sad. Garth was a successful library, with the README claiming 350k or more downloads per month and translations into multiple programming languages. Its failure was not neglect or a bad design, it was dependency on an undocumented interface that the vendor was free to change. That is the general lesson, and it is worth more to a reader than the code.

Licence, project state and what to do with the code

The licence is MIT, with the LICENSE file at the root of the repository. The pyproject declares the same, and the trove classifier names the MIT License explicitly. A permissive licence with no copyleft obligation is what makes the README's offer meaningful: anyone can fork Garth as a starting point for a new library and build on the code without asking.

The repository is not archived and the last push was on 2026-06-09, so the source and the documentation remain in place. The recent releases are v0.8.0 from 2026-03-28, described as the final release, along with 0.7.11 and 0.7.10 from 2026-03-19. The version scheme is a plain numeric one, and the 0.8.0 release exists to mark the end rather than to add a feature.

The documentation is still published at garth.readthedocs.io and the README says it remains available for reference, which is the point of keeping the readthedocs configuration in the repository. A reference implementation of how a Garmin Connect session was obtained and how the API responses were modelled is still worth reading, and that is a different kind of value from a working library.

Three things are worth doing with that. If you maintain an existing Garth integration, note the token expiry in your own documentation and plan the migration rather than discovering it in a monitoring alert. If you want to build a replacement, start from the announcement discussion to understand the new flow, then fork the code, and treat the old OAuth1 path as a reference for everything except the login. And if you are simply looking for a client, the deprecation notice is the signal to look elsewhere, because a library whose entry point is closed will not be there when you need it.

Editorial conclusion

Garth is worth reading as a reference implementation rather than as something to install, and it is worth reading precisely because it failed in a specific and instructive way. It is the wrong choice for any new project, since no new login will work and the maintainer has said they are not in a position to adapt to the change. If you have an existing integration, treat the saved OAuth1 token as a clock rather than a solution, because it stops working when it expires. Before starting anything new against Garmin Connect, look for a maintained client, and if you want to build one, start from this code and a current look at the new authentication flow rather than assuming the OAuth1 path still applies.

Frequently asked questions

Is Garth still maintained?

No. The README states that Garth is deprecated and no longer maintained, because Garmin changed their auth flow and broke the mobile auth approach Garth depends on, and the author says they are not in a position to dedicate the time to adapt. The v0.8.0 release is described as the final release.

Can I still use Garth if I have a saved session?

Possibly. The README says that if you already have a saved session with a valid OAuth1 token, Garth may continue to work until that token expires, which is about a year from when it was issued. New logins will not work.

What broke Garth?

Garmin changed their auth flow, which broke the mobile auth approach that Garth and other libraries depend on, as described in the linked issue. It was not a defect in Garth itself, and the announcement discussion has the details of what changed.

What are Garth's main dependencies?

requests, pydantic, pydantic-settings, requests-oauthlib and logfire, with Python 3.10 or newer required. The build uses hatchling, the version is read from src/garth/version.py, and the project is tested with pytest and linted with ruff and ty.

Can I fork Garth and keep using it?

The README says anyone is welcome to fork Garth as a starting point for a new library, and the MIT licence permits it. A fork would need to replace the login flow, since that is the part Garmin changed and the part new logins depend on.

Where is the Garth documentation?

It is still published at garth.readthedocs.io, and the README says the documentation remains available for reference. The documentation site is built from the docs/ directory with mkdocs.

Official sources

  1. Issues
  2. License: MIT
  3. matin/garth on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/matin-garth.svg)](https://hysenlabs.com/projects/matin-garth)

Was this useful?