Getting More Details Activity From Strava API
We are back for another article in our series in working with the Strava API. So far, we have worked on our authentication with Strava, storing and updating our access tokens and athlete information. We have started downloading basic athlete activity information and started using a Google Sheet to store the information we have been collecting.
In this article we are going to use a different set of Strava API's that will give us more detailed information on athlete activities. As you may remember from our previous articles, Strava assigns an activity ID to each activity added into Strava. Using this activity ID, we can then use the following API's to get more detailed information on the activity.
If you need to catch up on our previous articles, you can do so, by going to the following link:
https://hive.blog/hive-163521/@strava2hive/getting-started-using-the-strava-api
https://stemgeeks.net/hive-163521/@strava2hive/getting-activity-data-from-the-strava-api
https://stemgeeks.net/hive-163521/@strava2hive/storing-strava-activity-data-in-google-sheets
As you can see from the image above, my "Morning Run Home" also has the URL of https://www.strava.com/activities/9851035324 with the 9851035324 value being the activity ID for this run. Of course to get this activity information for an athlete, you need to use the access token we have been using to get our original details from the Strava API.
Even though we get a large amount of information from the basic activity details, when you start working with the API, you will start to want to get some extra details, and this is what we will be looking at in this article. If you want to checkout the developer information, the following link is available, but at the same time, it is not always up to date:
https://developers.strava.com/docs/reference/
In the following, we are going to look at setting up a set of functions to get the following activity information:
- Detailed activity information like activity description
- Comments posted to the activity
- Activity photos uploaded by the athlete
- Kudos given to the activity
- Laps performed in the activity
- Heart rate and power zones achieved in the activity
1. Detailed Activity Information
This is the first step in getting a whole lot more information is using the api/v3/activities/{id} end point in the Strava API. The function we have put together below uses two parameters, the activity ID and the users access token. You will not be able to get any of this extra information for activities connected to any other athlete.
import requests
def detailed_activity(activity_id, access_token):
bearer_header = "Bearer " + str(access_token)
strava_activity_url = "https://www.strava.com/api/v3/activities/" + str(activity_id)
headers = {'Content-Type': 'application/json', 'Authorization': bearer_header}
response = requests.get(strava_activity_url, headers=headers, )
more_activity_data = response.json()
print("Activity name: ", more_activity_data['name'])
print("Activity description: ", more_activity_data['description'])
In the function, we have performed the following:
- Imported the requests module
- added our currect access token to the Bearer
- added the url as https://www.strava.com/api/v3/activities and added the activity ID
- sent the request to Strava and recorded the response in a variable
- gathered the response in a variable, and we have printed our two values, the activity name and activity description
If everything goes as planned, we would hopefully get an output similar to the one below:
Activity name: Morning Run Home
Activity description: Another good run home after a tough swim squad. Still using some good pics for the weekend and good that after a long week of work and being on call I am still running well.
As you can see from the Strava documentation, the API will return a large amount of information, similar to the truncated output we have added below:
{
"id" : 12345678987654321,
"resource_state" : 3,
"external_id" : "garmin_push_12345678987654321",
"upload_id" : 98765432123456789,
"athlete" : {
"id" : 134815,
"resource_state" : 1
},
"name" : "Happy Friday",
"distance" : 28099,
"moving_time" : 4207,
"elapsed_time" : 4410,
"total_elevation_gain" : 516,
"type" : "Ride",
2. Comments Posted To Activity
You can see all of the comments provided by users to an activity, by using the following URL: /activities/{id}/comments
Our function below simply provides back all the information from the API.
def comments_from_activity(activity_id, access_token):
bearer_header = "Bearer " + str(access_token)
strava_activity_url = "https://www.strava.com/api/v3/activities/" + str(activity_id) + "/comments"
headers = {'Content-Type': 'application/json', 'Authorization': bearer_header}
response = requests.get(strava_activity_url, headers=headers, )
more_activity_data = response.json()
print(more_activity_data)
As you can see, a user has also posted emoji's in the comments and these are provided back from the API.
[{'id': 1623035828, 'activity_id': 9798378812, 'post_id': None, 'resource_state': 2, 'text': '😲 Those Quads! 😅', 'mentions_metadata': None, 'created_at': '2023-09-07T01:06:22Z', 'cursor': None, 'athlete': {'resource_state': 2, 'firstname': 'Dan', 'lastname': 'R.'}, 'reaction_count': 1, 'has_reacted': True}]
3. Activity Photos Uploaded
Photos uploaded to an activity has been a bit of a mystery and one of those things not really well documented by Strava. I found the following details in the developer forums where someone explained it and is not just a matter of providing the URL, you also need to include the "?size=5000" option at the end. This allows Strava to give you all the details back when the request is made.
So the full URL you need to provide in your request is: /api/v3/activities/{id}/photos?size=5000
def photos_from_activity(activity_id, access_token):
bearer_header = "Bearer " + str(access_token)
strava_activity_url = "https://www.strava.com/api/v3/activities/" + str(activity_id) + "/photos?size=5000"
headers = {'Content-Type': 'application/json', 'Authorization': bearer_header}
response = requests.get(strava_activity_url, headers=headers, )
more_activity_data = response.json()
for i in more_activity_data:
print(i)
The following is provided from the API, and there is a lot of data, but the main piece of information you will see is the ".jpg" file, which is the actual image and the file location for you to possibly download if you need to.
{'unique_id': '27221e2c-a033-4979-b73c-2e998cf3ca2b', 'athlete_id': 1778778, 'activity_id': 9798378812, 'activity_name': 'Morning Run Home', 'post_id': None, 'resource_state': 2, 'caption': '', 'type': 1, 'source': 1, 'status': 3, 'uploaded_at': '2023-09-06T22:49:49Z', 'created_at': '2023-09-06T22:49:47Z', 'created_at_local': '2023-09-07T10:49:47Z', 'urls': {'5000': 'https://dgtzuqphqg23d.cloudfront.net/foVBLjs3r0jsVYW0aN9XSxjkHMsiwChdoB9SMDvLbdw-2048x2048.jpg'}, 'sizes': {'5000': [2048, 2048]}, 'default_photo': False}
{'unique_id': '5c9c7d6d-b164-4489-b526-7e4deef94307', 'athlete_id': 1778778, 'activity_id': 9798378812, 'activity_name': 'Morning Run Home', 'post_id': None, 'resource_state': 2, 'caption': '', 'type': 1, 'source': 1, 'status': 3, 'uploaded_at': '2023-09-06T22:49:55Z', 'created_at': '2023-09-06T22:49:54Z', 'created_at_local': '2023-09-07T10:49:54Z', 'urls': {'5000': 'https://dgtzuqphqg23d.cloudfront.net/_nz2y8mpOmivpxldspq93Jr0Mnep81cqhRHskFfH3HY-2048x2048.jpg'}, 'sizes': {'5000': [2048, 2048]}, 'default_photo': False}
4. Kudos Given
Kudos are given by friends and followers for your activity and we can get a list of all the Strava users who have given an athlete kudos by using the following URL: /activities/{id}/kudos
def kudos_from_activity(activity_id, access_token):
bearer_header = "Bearer " + str(access_token)
strava_activity_url = "https://www.strava.com/api/v3/activities/" + str(activity_id) + "/kudos"
headers = {'Content-Type': 'application/json', 'Authorization': bearer_header}
response = requests.get(strava_activity_url, headers=headers, )
more_activity_data = response.json()
print(more_activity_data)
We get a list of all the users who have given a specific activity kudos with the first and last name of the user provided.
[{'resource_state': 2, 'firstname': 'allister', 'lastname': 'K.'}, {'resource_state': 2, 'firstname': 'Clint', 'lastname': 'C.'}, {'resource_state': 2, 'firstname': 'Raewyn', 'lastname': 'S.'}, {'resource_state': 2, 'firstname': 'Allan', 'lastname': 'C.'}, {'resource_state': 2, 'firstname': 'Navid', 'lastname': 'J.'}, {'resource_state': 2, 'firstname': 'Doron', 'lastname': 'D.'}, {'resource_state': 2, 'firstname': 'SG_', 'lastname': 'T.'}]
5. Laps Of The Activity
Laps are provided by Strava using the following url: /activities/{id}/laps
We can assemble our function similar to the ones we have previously, as we have below:
def laps_from_activity(activity_id, access_token):
bearer_header = "Bearer " + str(access_token)
strava_activity_url = "https://www.strava.com/api/v3/activities/" + str(activity_id) + "/laps"
headers = {'Content-Type': 'application/json', 'Authorization': bearer_header}
response = requests.get(strava_activity_url, headers=headers, )
more_activity_data = response.json()
print(more_activity_data)
Laps are set up by the user, and for my activity below, I have only had one lap, but all the details are still provided back from the API when you make the call:
[{'id': 33616709415, 'resource_state': 2, 'name': 'Lap 1', 'activity': {'id': 9819681974, 'visibility': 'everyone', 'resource_state': 1}, 'athlete': {'id': 1778778, 'resource_state': 1}, 'elapsed_time': 2711, 'moving_time': 2711, 'start_date': '2023-09-10T04:36:19Z', 'start_date_local': '2023-09-10T16:36:19Z', 'distance': 0.0, 'start_index': 0, 'end_index': 2677, 'total_elevation_gain': 0, 'average_speed': 0.0, 'max_speed': 0.0, 'device_watts': False, 'average_heartrate': 127.3, 'max_heartrate': 149.0, 'lap_index': 1, 'split': 1}]
6. Heart Rate And Power Zones
Finally we can get the power and heart rate zones the athlete has been working in. There are a few different things this relies on, first that the user has heart rate and power data uploaded to Strava, and secondly the user must have a paid Strava account. You can still make the call to the API, but will get a 'Payment Required' error provided.
In this instance, we simply use the /activities/{id}/zones URL, and we can set up our function like the one below:
def zones_from_activity(activity_id, access_token):
bearer_header = "Bearer " + str(access_token)
strava_activity_url = "https://www.strava.com/api/v3/activities/" + str(activity_id) + "/zones"
headers = {'Content-Type': 'application/json', 'Authorization': bearer_header}
response = requests.get(strava_activity_url, headers=headers, )
more_activity_data = response.json()
print(more_activity_data)
Unfortunately, my account is not a paid account, so all I get back from the Strava API is the message below:
{'message': 'Payment Required', 'errors': []}
We have flown through a lot of data again and hopefully it has been made a little bit clearer for you. Of course, let me know if you need me to clarify anything in the comments.
Posted with STEMGeeks