Accessing the Strava API

August 1, 2022    sports

See this documentation for OAuth2 authentication, but you need to generate an OAuth application once to obtain a client_id, client_secret, and refresh_token.

With these you can make a POST call to the Strava API which gives an Access Token that expires regularly. You can see these values all at https://www.strava.com/settings/api :

Python code to get your access token:

import requests
auth_url = "https://www.strava.com/oauth/token"

payload = {
    'client_id': string_myClientID,
    'client_secret': string_myClientSecretFromStrava,
    'refresh_token': string_myRefreshTokenFromStrava,
    'grant_type': "refresh_token",
    'f': 'json'
    }

res = requests.post(auth_url, data=payload, verify=False)
access_token = res.json()['access_token']

res.json() gives:

{'token_type': 'Bearer',
 'access_token': string_myAccessTokenFromAPI,
 'expires_at': 1659765556,
 'expires_in': 21600,
 'refresh_token': string_myRefreshTokenFromStrava}

With the access_token you can call everything you see in Strava’s API documentation. Here’s an example of how to get a summarized set of activities (also see here):

pages = 1
activities_url = "https://www.strava.com/api/v3/athlete/activities"
header = {'Authorization': 'Bearer ' + access_token}
strava_data = []

for i in range(pages):
    param = {'per_page': 200, 'page':i+1}
    strava_data += requests.get(activities_url, headers=header, params=param).json()

This call yields strava_data as a dictionary of each activity starting newest first. Each loop only calls the API once and 200 “per_page” was a decent mix of performance and speed.

Items in the dictionary have the following keys for runs with a heart rate monitor (YMMV for different activities):

dict_keys(['resource_state', 'athlete', 'name', 'distance', 'moving_time', 'elapsed_time', 'total_elevation_gain', 'type', 'sport_type', 'workout_type', 'id', 'start_date', 'start_date_local', 'timezone', 'utc_offset', 'location_city', 'location_state', 'location_country', 'achievement_count', 'kudos_count', 'comment_count', 'athlete_count', 'photo_count', 'map', 'trainer', 'commute', 'manual', 'private', 'visibility', 'flagged', 'gear_id', 'start_latlng', 'end_latlng', 'average_speed', 'max_speed', 'average_cadence', 'has_heartrate', 'average_heartrate', 'max_heartrate', 'heartrate_opt_out', 'display_hide_heartrate_option', 'elev_high', 'elev_low', 'upload_id', 'upload_id_str', 'external_id', 'from_accepted_tag', 'pr_count', 'total_photo_count', 'has_kudoed'])