Python library for the Strava API v3
Project description
strava
A modern, fully-typed Python SDK for the Strava API v3.
Features
- Sync and async clients built on httpx
- Full type annotations and
py.typedsupport - 34 API endpoints across 9 resource groups
- 50+ dataclass models with automatic serialization
- OAuth2 authentication with automatic token refresh
- Lazy pagination iterators
- Custom exception hierarchy with rate limit details
Installation
pip install strava
Quick Start
from strava import Strava
with Strava(access_token="your_token") as client:
# Get authenticated athlete
athlete = client.athletes.retrieve_authenticated()
print(f"{athlete.firstname} {athlete.lastname}")
# List recent activities
for activity in client.activities.list(per_page=10):
print(f"{activity.name} - {activity.distance}m")
Async
from strava import AsyncStrava
async with AsyncStrava(access_token="your_token") as client:
athlete = await client.athletes.retrieve_authenticated()
activities = await client.activities.list(per_page=10).collect()
OAuth2 Authentication
Get an authorization URL
from strava import build_authorization_url
url = build_authorization_url(
client_id="your_client_id",
redirect_uri="http://localhost:8000/callback",
scopes=["read", "activity:read_all"],
)
# Redirect the user to `url`
Exchange the code for tokens
from strava import exchange_token
tokens = exchange_token(
client_id="your_client_id",
client_secret="your_secret",
code="code_from_callback",
)
print(tokens.access_token, tokens.refresh_token, tokens.expires_at)
Refresh a token manually
from strava import refresh_access_token
tokens = refresh_access_token(
client_id="your_client_id",
client_secret="your_secret",
refresh_token="current_refresh_token",
)
print(tokens.access_token, tokens.refresh_token, tokens.expires_at)
Automatic token refresh
from strava import Strava
def save_tokens(access_token, refresh_token, expires_at):
# Persist the new tokens to your database
...
client = Strava(
access_token="...",
client_id="your_client_id",
client_secret="your_secret",
refresh_token="...",
expires_at=1700000000,
on_token_refresh=save_tokens,
)
Revoke tokens
from strava import revoke_token
revoke_token(
client_id="your_client_id",
client_secret="your_secret",
token="access_or_refresh_token",
token_type_hint="access_token",
)
deauthorize(access_token=...) remains available for compatibility, but it is deprecated because Strava will retire oauth/deauthorize on June 1, 2027. Prefer revoke_token() for new code.
API Coverage
| Resource | Methods |
|---|---|
| Activities | create, retrieve, update, list, list_comments, list_kudoers, list_laps, list_zones |
| Athletes | retrieve_authenticated, update_authenticated, retrieve_zones, retrieve_stats |
| Clubs | retrieve, list_activities, list_admins, list_members, list_authenticated |
| Gear | retrieve |
| Routes | retrieve, export_gpx, export_tcx, list_by_athlete |
| Segments | retrieve, explore, list_starred, star |
| Segment Efforts | retrieve, list |
| Streams | get_activity_streams, get_route_streams, get_segment_effort_streams, get_segment_streams |
| Uploads | create, retrieve |
Strava API Changes
The default API host is https://www.api-v3.strava.com, matching Strava's June 1, 2027 migration from https://www.strava.com/api/v3.
Some methods remain in the SDK for compatibility but are affected by Strava's 2026 Developer Program changes:
clubs.list_activities(),clubs.list_admins(), andclubs.list_members()are deprecated by Strava effective September 1, 2026.segments.explore()is restricted to approved Extended Access applications effective September 1, 2026.deauthorize()is deprecated; userevoke_token()with your client credentials instead.
Pagination
List endpoints return lazy paginators:
# Iterate one item at a time (fetches pages on demand)
for activity in client.activities.list():
print(activity.name)
# Collect all results eagerly
all_activities = client.activities.list().collect()
# Limit results
first_50 = client.activities.list().collect(max_items=50)
# Iterate page by page
for page in client.activities.list(per_page=50).pages():
print(f"Got {len(page)} activities")
Error Handling
from strava import (
StravaError,
AuthenticationError,
AuthorizationError,
NotFoundError,
RateLimitError,
TokenExpiredError,
ValidationError,
ServerError,
)
try:
activity = client.activities.retrieve(123)
except TokenExpiredError:
print("Access token has expired — refresh it")
except AuthenticationError:
print("Invalid or missing access token")
except AuthorizationError:
print("Insufficient permissions")
except NotFoundError:
print("Activity not found")
except ValidationError as e:
print(f"Bad request: {e.message}")
except RateLimitError as e:
print(f"Rate limited. 15-min usage: {e.usage_15min}/{e.limit_15min}")
except ServerError:
print("Strava server error — try again later")
except StravaError as e:
print(f"API error {e.status_code}: {e.message}")
Development
# Install dependencies
uv sync
# Run tests
make test
# Run tests with coverage
make coverage
# Lint and format
make lint
make format
Python Version
Supports Python 3.11 through 3.14.
Contributing
Contributions are welcome! Please read the Contributing Guide before opening a pull request.
Found a bug? Open an issue. Have an idea? Request a feature.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file strava-0.5.0.tar.gz.
File metadata
- Download URL: strava-0.5.0.tar.gz
- Upload date:
- Size: 18.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7a64e23ad72d8dde450a4ce18f4faa4dc10b1a49caffd995643d5ced50701c6e
|
|
| MD5 |
47f1f35698426027d6333009a81b9566
|
|
| BLAKE2b-256 |
79c2efa43d3fac24884642f1fd2d5068861b8d192a1e54c56c401cfba9991eae
|
Provenance
The following attestation bundles were made for strava-0.5.0.tar.gz:
Publisher:
publish.yml on ragnarok22/strava-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strava-0.5.0.tar.gz -
Subject digest:
7a64e23ad72d8dde450a4ce18f4faa4dc10b1a49caffd995643d5ced50701c6e - Sigstore transparency entry: 1724315207
- Sigstore integration time:
-
Permalink:
ragnarok22/strava-python@866a8b4b12facadbd2c658515572de02593a0c0b -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/ragnarok22
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@866a8b4b12facadbd2c658515572de02593a0c0b -
Trigger Event:
push
-
Statement type:
File details
Details for the file strava-0.5.0-py3-none-any.whl.
File metadata
- Download URL: strava-0.5.0-py3-none-any.whl
- Upload date:
- Size: 31.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
168eccd377ad7da82f608f5285c6640708e85f42c6072dc8ed7858afefd5e007
|
|
| MD5 |
7c9b73e1e74ff6c484ff907f0df09ad0
|
|
| BLAKE2b-256 |
df916a654abfa1fdc92967d1fcad95cde22ae8682c88e2386ac31abd32cb3b11
|
Provenance
The following attestation bundles were made for strava-0.5.0-py3-none-any.whl:
Publisher:
publish.yml on ragnarok22/strava-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
strava-0.5.0-py3-none-any.whl -
Subject digest:
168eccd377ad7da82f608f5285c6640708e85f42c6072dc8ed7858afefd5e007 - Sigstore transparency entry: 1724315289
- Sigstore integration time:
-
Permalink:
ragnarok22/strava-python@866a8b4b12facadbd2c658515572de02593a0c0b -
Branch / Tag:
refs/tags/v0.5.0 - Owner: https://github.com/ragnarok22
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@866a8b4b12facadbd2c658515572de02593a0c0b -
Trigger Event:
push
-
Statement type: