Skip to main content

Python library for the Strava API v3

Project description

strava

CI codecov PyPI Python License

A modern, fully-typed Python SDK for the Strava API v3.

Features

  • Sync and async clients built on httpx
  • Full type annotations and py.typed support
  • 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(), and clubs.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; use revoke_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

strava-0.5.0.tar.gz (18.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

strava-0.5.0-py3-none-any.whl (31.1 kB view details)

Uploaded Python 3

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

Hashes for strava-0.5.0.tar.gz
Algorithm Hash digest
SHA256 7a64e23ad72d8dde450a4ce18f4faa4dc10b1a49caffd995643d5ced50701c6e
MD5 47f1f35698426027d6333009a81b9566
BLAKE2b-256 79c2efa43d3fac24884642f1fd2d5068861b8d192a1e54c56c401cfba9991eae

See more details on using hashes here.

Provenance

The following attestation bundles were made for strava-0.5.0.tar.gz:

Publisher: publish.yml on ragnarok22/strava-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for strava-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 168eccd377ad7da82f608f5285c6640708e85f42c6072dc8ed7858afefd5e007
MD5 7c9b73e1e74ff6c484ff907f0df09ad0
BLAKE2b-256 df916a654abfa1fdc92967d1fcad95cde22ae8682c88e2386ac31abd32cb3b11

See more details on using hashes here.

Provenance

The following attestation bundles were made for strava-0.5.0-py3-none-any.whl:

Publisher: publish.yml on ragnarok22/strava-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page