Strava
Load and analyze Strava activities, stats, and workouts using the Strava API
Bohdan Podvirnyi
@bohdanpodvirnyi
What This Skill Does
Command-line interface to the Strava API for loading and analyzing athlete activities, stats, and profile data. Supports filtering by date, pagination, and token refresh.
Replaces manual data export from Strava's web interface by providing programmatic access to activities, stats, and athlete profiles via curl commands.
When to Use It
- List recent Strava activities for a given athlete
- Filter activities by date range to analyze training periods
- Retrieve detailed metrics for a specific workout or race
- Get athlete profile and overall statistics for performance tracking
- Paginate through large activity histories for batch analysis
Install
$ openclaw skills install @bohdanpodvirnyi/stravaStrava Skill
Interact with Strava to load activities, analyze workouts, and track fitness data.
Setup
1. Create a Strava API Application
- Go to https://www.strava.com/settings/api
- Create an app (use
http://localhostas callback for testing) - Note your Client ID and Client Secret
2. Get Initial OAuth Tokens
Visit this URL in your browser (replace CLIENT_ID):
https://www.strava.com/oauth/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=http://localhost&approval_prompt=force&scope=activity:read_all
After authorizing, you'll be redirected to http://localhost/?code=AUTHORIZATION_CODE
Exchange the code for tokens:
curl -X POST https://www.strava.com/oauth/token \
-d client_id=YOUR_CLIENT_ID \
-d client_secret=YOUR_CLIENT_SECRET \
-d code=AUTHORIZATION_CODE \
-d grant_type=authorization_code
This returns access_token and refresh_token.
3. Configure Credentials
Add to ~/.clawdbot/clawdbot.json:
{
"skills": {
"entries": {
"strava": {
"enabled": true,
"env": {
"STRAVA_ACCESS_TOKEN": "your-access-token",
"STRAVA_REFRESH_TOKEN": "your-refresh-token",
"STRAVA_CLIENT_ID": "your-client-id",
"STRAVA_CLIENT_SECRET": "your-client-secret"
}
}
}
}
}
Or use environment variables:
export STRAVA_ACCESS_TOKEN="your-access-token"
export STRAVA_REFRESH_TOKEN="your-refresh-token"
export STRAVA_CLIENT_ID="your-client-id"
export STRAVA_CLIENT_SECRET="your-client-secret"
Usage
List Recent Activities
Get the last 30 activities:
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete/activities?per_page=30"
Get the last 10 activities:
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete/activities?per_page=10"
Filter Activities by Date
Get activities after a specific date (Unix timestamp):
# Activities after Jan 1, 2024
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete/activities?after=1704067200"
Get activities in a date range:
# Activities between Jan 1 - Jan 31, 2024
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete/activities?after=1704067200&before=1706745600"
Get Activity Details
Get full details for a specific activity (replace ACTIVITY_ID):
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/activities/ACTIVITY_ID"
Get Athlete Profile
Get the authenticated athlete's profile:
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete"
Get Athlete Stats
Get athlete statistics (replace ATHLETE_ID):
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athletes/ATHLETE_ID/stats"
Pagination
Navigate through pages:
# Page 1 (default)
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete/activities?page=1&per_page=30"
# Page 2
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete/activities?page=2&per_page=30"
Token Refresh
Access tokens expire every 6 hours. Refresh using the helper script:
bash {baseDir}/scripts/refresh_token.sh
Or manually:
curl -s -X POST https://www.strava.com/oauth/token \
-d client_id="${STRAVA_CLIENT_ID}" \
-d client_secret="${STRAVA_CLIENT_SECRET}" \
-d grant_type=refresh_token \
-d refresh_token="${STRAVA_REFRESH_TOKEN}"
The response includes a new access_token and refresh_token. Update your configuration with both tokens.
Common Data Fields
Activity objects include:
name— Activity titledistance— Distance in metersmoving_time— Moving time in secondselapsed_time— Total time in secondstotal_elevation_gain— Elevation gain in meterstype— Activity type (Run, Ride, Swim, etc.)sport_type— Specific sport typestart_date— Start time (ISO 8601)average_speed— Average speed in m/smax_speed— Max speed in m/saverage_heartrate— Average heart rate (if available)max_heartrate— Max heart rate (if available)kudos_count— Number of kudos received
Rate Limits
- 200 requests per 15 minutes
- 2,000 requests per day
If you hit rate limits, responses will include X-RateLimit-* headers.
Tips
- Convert Unix timestamps:
date -d @TIMESTAMP(Linux) ordate -r TIMESTAMP(macOS) - Convert meters to km: divide by 1000
- Convert meters to miles: divide by 1609.34
- Convert m/s to km/h: multiply by 3.6
- Convert m/s to mph: multiply by 2.237
- Convert seconds to hours: divide by 3600
- Parse JSON with
jqif available, or usegrep/sedfor basic extraction
Examples
Get running activities from last week with distances:
LAST_WEEK=$(date -d '7 days ago' +%s 2>/dev/null || date -v-7d +%s)
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete/activities?after=${LAST_WEEK}&per_page=50" \
| grep -E '"name"|"distance"|"type"'
Get total distance from recent activities:
curl -s -H "Authorization: Bearer ${STRAVA_ACCESS_TOKEN}" \
"https://www.strava.com/api/v3/athlete/activities?per_page=10" \
| grep -o '"distance":[0-9.]*' | cut -d: -f2 | awk '{sum+=$1} END {print sum/1000 " km"}'
Error Handling
If you get a 401 Unauthorized error, your access token has expired. Run the token refresh command.
If you get rate limit errors, wait until the limit window resets (check X-RateLimit-Usage header).
Top skills in this category
npm Registry
@hith3shSearch npm packages, inspect metadata and versions, review download stats, and check security advisories. Use this skill when users want to explore npm regis...
Google Merchant Center
@byungkyuGoogle Merchant Center API integration with managed OAuth. This is a write-capable integration — it can read, create, update, and delete products, inventories, data sources, promotions, account settings, and conversions in Google Shopping. Use this skill when users want to interact with their Merchant Center data. All write operations (creating/updating/deleting products, inventories, promotions, data sources, or account settings) require explicit user approval with specific resource identifiers before execution. For other third party apps, use the api-gateway skill (https://clawhub.ai/byungkyu/api-gateway). Requires network access and valid Maton API key. Calls run through the `maton` CLI with OAuth login, or over raw HTTP with a Maton API key where the CLI cannot be installed. The endpoints documented here are the intended surface, not a technical limit — the `maton api` passthrough can reach others the connection permits. Default to read and list calls, and confirm every write or new connection with the user.
AgentGuard
@0xbeekeeperGoPlus AgentGuard — AI agent security guard. Run /agentguard checkup for a full security health check, scans all installed skills, checks credentials, permis...
Location Awareness
@hegghammerLocation awareness via privacy-friendly GPS tracking (Home Assistant, OwnTracks, GPS Logger). Set location-based reminders and ask about movement history, travel time, and nearby POIs.
Journal
@ivangdavilaRuns a personal journaling practice: capturing entries, prompts for a blank page, weekly and yearly reviews, and patterns across years of writing. Use when the user wants to write, vent, dictate, or get something out of their head; when they ask for a prompt or say they are stuck; for morning pages, bullet journal, five-minute, interstitial, dream, travel, decision, or work journaling; for a weekly, monthly, or annual review; when they ask what they have been writing about, whether a mood or theme keeps recurring, or what they wrote a year ago; when the practice lapsed and they want to restart; when entries need naming, tagging, searching, encrypting, backing up, or migrating out of Day One, Notion, or an Obsidian vault; when writing through grief, anger, shame, or a decision that will not settle; or when a work journal must become performance-review evidence. Not for retrieval-oriented notes (`notes`), gratitude logging alone (`gratitude`), or live emotional support (`psychologist`).