How to connect the Strava API with Google Sheets and Data Studio

Editor’s Note: Strava updated their OAuth workflow (see here), which breaks the code shown below. I’ll post a fix as soon as I can.

This post looks at how to connect the Strava API with Google Sheets and create a visualization in Google Data Studio.

Strava api with google sheets and data studio

Strava is an insanely good app for athletes to track their workouts. I use it to track my running, biking and hiking, and look at the data over time.

This whole project was born out of a frustration with the Strava app.

Whilst it’s great for collecting data, it has some limitations in how it shows that data back to me. The training log shows all of my runs and bike rides, but nothing else. However, I do a lot of hiking too (especially when I’m nursing a running injury) and to me, it’s all one and the same. I want to see it all my activities on the same training log.

So that’s why I built this activity dashboard in Google Data Studio. It shows all of my activities, regardless of type, in a single view.

Connecting the Strava API with Google Sheets

To connect to the Strava API with Google Sheets, follow these steps:

Setup your Google Sheet

  1. Open a new Google Sheet (pro-tip: type into your browser window!)
  2. Type a header row in your Google Sheet: “ID”, “Name”, “Type”, “Distance (m)” into cells A1, B1, C1 and D1 respectively
  3. Open the Script Editor (Tools > Script editor)
  4. Give the script project a name e.g. Strava Sheets Integration
  5. Create a second script file (File > New > Script file) and call it
  6. Add the OAuth 2.0 Apps Script library to your project (Resources > Libraries...)
  7. Enter this ID code in the “Add a library” box: 1B7FSrk5Zi6L1rSxxTDgDEUsPzlukDsi4KGuTMorsTQHhGBzBkMun4iDF
  8. Select the most recent version of the library from the drop-down (version 34 currently — September 2019) and hit “Save”

Add the code

If you’re new to API and Apps Script, check out my API Tutorial For Beginners With Google Sheets & Apps Script.

In your file, add this code:

var CLIENT_ID = '';

// configure the service
function getStravaService() {
  return OAuth2.createService('Strava')

// handle the callback
function authCallback(request) {
  var stravaService = getStravaService();
  var isAuthorized = stravaService.handleCallback(request);
  if (isAuthorized) {
    return HtmlService.createHtmlOutput('Success! You can close this tab.');
  } else {
    return HtmlService.createHtmlOutput('Denied. You can close this tab');

Also available in this GitHub oauth.js repo.

In your file, add this code:

// custom menu
function onOpen() {
  var ui = SpreadsheetApp.getUi();

  ui.createMenu('Strava App')
    .addItem('Get data', 'getStravaActivityData')

// Get athlete activity data
function getStravaActivityData() {
  // get the sheet
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('Sheet1');

  // call the Strava API to retrieve data
  var data = callStravaAPI();
  // empty array to hold activity data
  var stravaData = [];
  // loop over activity data and add to stravaData array for Sheet
  data.forEach(function(activity) {
    var arr = [];
  // paste the values into the Sheet
  sheet.getRange(sheet.getLastRow() + 1, 1, stravaData.length, stravaData[0].length).setValues(stravaData);

// call the Strava API
function callStravaAPI() {
  // set up the service
  var service = getStravaService();
  if (service.hasAccess()) {
    Logger.log('App has access.');
    var endpoint = '';
    var params = '?after=1546300800&per_page=200';

    var headers = {
      Authorization: 'Bearer ' + service.getAccessToken()
    var options = {
      headers: headers,
      method : 'GET',
      muteHttpExceptions: true
    var response = JSON.parse(UrlFetchApp.fetch(endpoint + params, options));
    return response;  
  else {
    Logger.log("App has no access yet.");
    // open this url to gain authorization from github
    var authorizationUrl = service.getAuthorizationUrl();
    Logger.log("Open the following URL and re-run the script: %s",

Also available in this GitHub code.js repo.

Note about the params variable

Have a look at the params variable:

var params = '?after=1546300800&per_page=200'

The ‘after’ parameter means my code will only return Strava activities after the date I give. The format of the date is epoch time and the date I’ve used here is 1/1/2019 i.e. I’m only returning activities from this year.

(Here’s a handy calculator to convert human dates to epoch timestamps.)

The other part of the params variable is the ‘per_page’ variable, which I’ve set to 200. This is the maximum number of records the API will return in one batch.

To get more than 200, you need to add in the ‘page’ parameter and set it to 2,3,4 etc. to get the remaining activities, e.g.

var params = '?after=1546300800&per_page=200&page=2'

Eventually you’ll want to do that programmatically with a while loop (keep looping while the API returns data and stop when it comes back empty handed).

Note about parsing the data

The script above parses the response from the API and adds 4 values to the array that goes into the Google Sheet, namely: ID, Name, Type and Distance.

You can easily add more fields however.

Look at the Strava documentation to see what fields are returned and select the ones you want. For example, you add total elevation gain like this:


If you add extra fields to the array, don’t forget to change the size of the range you’re pasting the data into in your Google Sheet.

The array and range dimensions must match.

Setup your Strava API application

You need to create your app on the Strava platform, so that your Google Sheet can connect to it.

Login to Strava and go to Settings > My API Application or type in

This will take you to the API application settings page.

Give your application a name, and enter a website and description. You can put anything you want here, as it’s just for display.

The key to unlock the Strava API, which took me a lot of struggle to find, is to set the “Authorization Callback Domain” as

(Hat tip to this article from Elif T. Kuş, which was the only place I found this.)

Strava API application setup

Next, grab your client ID and paste it into the CLIENT_ID variable on line 1 of your Apps Script code in the file.

Similarly, grab your client secret and paste it into the CLIENT_SECRET variable on line 2 of your Apps Script code in the file.

Copy these two values:

Strava API application

And paste them into your code here:

Oauth client id and secret in Apps Script

Authorize your app

Run the onOpen function from the script editor and authorize the scopes the app needs (external service and spreadsheet app):

Apps Script authorization

If your process doesn’t look like this, and you see a Warning sign, then don’t worry. Click the Advanced option and authorize there instead (see how in this Google Apps Script: A Beginner’s Guide).

Return to your Google Sheet and you’ll see a new custom menu option “Strava App”.

Click on it and select the “Get data” drop-down.

Nothing will happen in your Google Sheet the first time it runs.

Return to the script editor and open the logs (View > Logs). You’ll see the authorization URL you need to copy and paste into a new tab of your browser.

This prompts you to authorize the Strava app:

Strava API with Google Sheets authorization workflow

Boom! Now you’ve authenticated your application.

For another OAuth example, have a look at the GitHub to Apps Script integration which shows these steps for another application.

Retrieve your Strava data!

Now, the pièce de résistance!

Run the “Get data” function again and this time, something beautiful will happen.

Rows and rows of Strava data will appear in your Google Sheet!

Connect Strava API with Google Sheets

The code connects to the athlete/activities endpoint to retrieve data about all your activities.

In its present setup, shown in the GIF above, the code parses the data returned by the API and pastes 4 values into your Google Sheet: ID, Name, Type and Distance.

(The distance is measure in meters.)

Of course, you can extract any or all of the fields returned by the API.

In the data studio dashboard I’ve used some of the time data to determine what day of the week and what week of the year the activity occurred on. I also looked at fields measuring how long the activity took.

Setting a trigger to call the API automatically

Once you’ve established the basic connection above, you’ll probably want to set up a trigger to call the API once a day to get fresh data.

You’ll want to filter out the old data to prevent ending up with duplicate entries. You can use a filter loop to compare the new data with the values you have in your spreadsheet and discard the ones you already have.

Building a dashboard in Google Data Studio

Google Data Studio is an amazing tool for creating visually stunning dashboards.

I was motivated to build my own training log that had all of my activities showing, regardless of type.

First, I created some calculated fields in Apps Script to work out the day of the week and the week number. I added these four fields to my file:

(new Date(activity.start_date_local)).getDay(), // sunday - saturday: 0 - 6
parseInt(Utilities.formatDate(new Date(activity.start_date_local), SpreadsheetApp.getActiveSpreadsheet().getSpreadsheetTimeZone(), "w")), // week number
(new Date(activity.start_date_local)).getMonth() + 1, // add 1 to make months 1 - 12
(new Date(activity.start_date_local)).getYear() // get year

And I converted the distance in metres into a distance in miles with this modification in my Apps Script file:

(activity.distance * 0.000621371).toFixed(2), // distance in miles

From there, you simply create a new dashboard in Data Studio and connect it to your Google Sheet.

The activity log chart is a bubble chart with day of the week on the x-axis and week number as the y-axis, both set to average (so each appears separately). The bubble size is the Distance and the dimension is set to Name.

Bubble chart in Data Studio

Next, I added a Year filter so that I can view each year separately (I’ve got data going back to 2014 in the dataset).

To complete the dashboard, I added a Strava logo and an orange theme.

Strava api with google sheets and data studio

(Note: There’s also an open source Strava API connector for Data Studio, so you could use that to create Strava visualizations and not have to write the code yourself.)

Next steps for the Strava API with Google Sheets

This whole project was conceived as a way to explore the Strava API with Google Sheets. I’m happy to get it working and share it here.

However, I’ll be the first to admit that this project is still a little rough around the edges.

But I am excited to have my Strava data in a Google Sheet now. There are TONS of other interesting stories / trends that I want to explore when I have the time.

There is definitely room for improvement with the Apps Script code. In addition to those mentioned above, and with a little more time, I would bake the OAuth connection into the UI of the Google Sheet front end (using a sidebar), instead of needing to grab the URL from the Logs in your script editor.

And the Data Studio dashboard was rather hastily thrown together to solve the issue of not seeing all my activity data in once place. Again, there’s a lot more work you could do here to improve it.

To be continued…

Time for a run first though!

31 thoughts on “How to connect the Strava API with Google Sheets and Data Studio”

  1. Aw man, this is FANTASTIC! Thanks so much for your work! Agreed–love Strava, but I am a data nerd and have it go to SmashRun automatically. Love the thought of getting my data to Google Data Studio.

    But…I got stuck at this step: Login to Strava and go to Settings > My API Application

    So I have no option for My API Application. I have My Apps, but nothing where I can add a custom API, I am guessing.

    1. Hi Chris,

      Hmm, it should be an option in the list of options on the left side , under “My profile”, “My Account”, …etc. and it’s the final choice. This is on desktop btw. It’s at the url:

      There you should find a “Create App” button…

      Hope this helps.


  2. Hi ben, tnx for the nice post.. tried but I had a “Cannot call method “getRange” of null” error on data acquisition..what could have happened?

  3. Hi Ben,

    Is this still working for you after the October 15 change at Strava?

    I only get the data into Google Sheets if I have the access code and pass it directly with the URL:
    var params = ‘?after=1546300800&per_page=200&access_token=2f9…

    The weird thing is that the OAuth from Google doesn’t seem to work for me, I am never confronted with the pop-up.

    So I bypass
    if (service.hasAccess()) {

    and use:
    if (scope == “activity:read_all”) {

    And then it works.

    So I do have clearly an authentication problem…
    Not sure if you have any idea…

    1. Hey Ralph – It’s possible! It’s still fetching all my data (picked up my last walk on Thursday last week) at the moment. I’ll revisit when I get a chance 🙂


  4. Thanks Ben, I went over all the oAuth stuff on the weekend. My problem can’t be that hard to fix. I will give it a new shot this week.


    1. Hey Ralph,

      Judging from your Twitter posts I think you got this working right? Feel free to share a link if you’ve posted working code anywhere like GitHub.

      I haven’t had time to revisit my code yet!


    2. Hello Ralph,

      I’m having the same issue after the October end. I can’t find where is the problem. I guess it is related with the refresh token and how the library handle it but, I’m stuck. Could you share the solution in the case you found it?

      Thanks in advance.

  5. I haven’t been able to get data since the migration period ended in Oct. I’m not a strong coder so I look forward to someone with actual coding skills to figure out how to adapt Elif’s code for me. I left her a note as well and will report back if she responds with a fix.

  6. Excited to try this out. I got as far as authenticating, but came back to Google Sheets and no “Stava App” menu option.

  7. Hi Ben

    Thanks for your script and it works and I am able to get all the data I need. However, is it possible to get the Strava authorization URL from log and pop up to the browser? (like the google authorization). Since I want to share the sheet to someone else.

  8. I am having an issue with the first lines of code:
    Exception: Cannot call SpreadsheetApp.getUi() from this context. (line 4, file “Code”).

    Does it have something to do with Google deprecating containers?

  9. Hi Ben

    Absolutely love this whole project and I’ve used it to connect to my Strava account which will hopefully help motivate me with my training!

    For some reason when I first used the ‘Get data’ option from the custom menu inside the Sheet before authentication, it gave an error message (TypeError: Cannot read property ‘forEach’ of undefined at getStravaActivityData(Code:24:8)) and when I checked the logs they were blank. Then I ran the callStravaAPI function manually from the Script File and it worked fine and I could get the authentication URL from the Logs. I’m not sure if this is just me (sometimes my logs take a while to load?) or something other people have found?

    Thanks so much for sharing this.

    P.S An online course on Data Studio would be great!

    1. Great procedure Ben, many thanks.
      I’ve followed the instructions, however I’m getting the same error
      “Cannot read property ‘forEach’ of undefined at getStravaActivityData.” and can proceed further.
      Any fix or section to validate please?

      1. I think this is the step where you need to copy the URL from the log and paste into another tab to authorize the App on Strava’s side. I just did this and I think that was the last error I had before I got it working.

      2. I had a similar error and managed to fix it as follows:
        – Open a browser tab and go to
        – Click on “My executions” on the left
        – Click on any of the executions that are listed as “failed” which should expand to show some log info
        – Copy the URL from there into a new browser window

        Hope this helps.. .I am a runner with zero experience with programming and APIs..

  10. Hi Ben,
    Thanks for this, it has totally changed how I track my Strava Activities. I was able to get this working the first time through, even though I have never coded or made a script before in my life. I used your instructions elsewhere on your blog to set up a trigger to automate this daily, but it imports (duplicates) the old data along with the new data, over and over again. You said:

    “You’ll want to filter out the old data to prevent ending up with duplicate entries. You can use a filter loop to compare the new data with the values you have in your spreadsheet and discard the ones you already have.”

    Can you describe how to go about doing this?


  11. Ben this is a great project and I have implemented it for my own activites.

    Question – is there a way that I can utilise multi-user authentication?

    Would like to pull in extra data from my running club, just a small user base so they would be happy to provide authorisation for me to access their data the issue is how I can handle that via this method? Thought is I can loop through list of userIDs to pull each atheletes data. Any tips much appreciated! I have used this method to interogate the clubs functionalilty of the API but the data it returns doesn’t have a timestamp which impedes my usage.

    1. Hi Robert,

      Were you able to get this going?

      I am in the same boat and need to extract every member in the clubs’ activities.

  12. This is awesome and I have it working now.

    If I wanted to do the same thing for a segment leaderboard would it be a simple change?

  13. Should this work for extracting Strava Club activities as well? I keep getting an error message saying that the service is not defined. I’m probably doing something stupid, this is all new to me!

  14. hello, i want to get retrive data start latlng and end latlng that have 2 value for each column . for start latlng the value is 3.0251736 and 115.43636273. i call it but it only retrieve the first value. how can i get both of the value ?

  15. I’m still getting this error when I run the script.

    TypeError: Cannot read property ‘getRange’ of null

    I’ve read through every post in this thread and followed all the tips but I haven’t been able to get it to work. Any help is appreciated…

  16. For Strava Club data, I have changed a line in the call Strava API to:
    var endpoint = ‘{id}/activities’;

    Where {id} is your 6 digit Club ID from the link to your club page on Strava.

    I can then populate the spreadsheet with activity.type, activity.distance, activity.moving_time, activity.elapsed_time, activity.athlete.firstname, activity.athlete.lastname.

    That is really helpful for me but lastname is only an initial and I can’t get activity dates. I’ve done this by trial and error – can anyone with more knowledge figure out how to extract additional club activity data?

Leave a Reply

Your email address will not be published. Required fields are marked *