Export all HubSpot contacts to Google Sheets with pagination

I’m working on transferring contact data from HubSpot to Google Sheets but running into a pagination issue. My current script only pulls 100 contacts at a time, but I need to get over 7000 contacts total.

function fetchContactsFromHub() {
  var apiToken = "YOUR_API_TOKEN"; // Add your actual API token here
  var endpoint = "https://api.hubapi.com/crm/v3/objects/contacts?limit=100&archived=false&hapikey=" + apiToken;
  var result = UrlFetchApp.fetch(endpoint);
  var jsonData = JSON.parse(result.getContentText());
  var contactList = jsonData['results'];
  var worksheet = SpreadsheetApp.getActiveSheet();
  var columns = ["Email Address", "Given Name", "Family Name", "Contact ID"];
  var dataRows = [columns];
  contactList.forEach(function (contact) {
    dataRows.push([contact['properties'].email, contact['properties'].firstname, contact['properties'].lastname, contact['id']]);
  });
  worksheet.getRange(5,1,dataRows.length,dataRows[0].length).setValues(dataRows);
  contactList.forEach(function (contact) {
    console.log(contact['properties']);
  });
}

When I try to increase the limit parameter beyond 100, I get an error. How can I modify this to handle pagination and fetch all contacts from HubSpot? I need a way to loop through all pages of results.

You need a recursive function to handle pagination properly. Don’t try increasing the limit - instead, have your function call itself using the ‘after’ parameter from HubSpot’s response. I hit the same memory issues with large contact exports. Google Apps Script will kill your script if you try processing everything at once due to execution time limits. Break it into smaller chunks and use PropertiesService to save your progress between runs. One heads up - the API response structure changed in v3. Make sure you’re checking jsonData.paging.next.after instead of the old pagination methods. When I pulled our 5000+ contacts, it took 3 separate script runs to avoid timeouts.

yeah, 100 per request is the std limit. use a while loop with the pagination cursor - chk if jsonData.paging?.next?.after exists, then add &after= + that token to your next call. keep looping until there’s no more pages. also, switch to bearer token auth instead of hapikey - way more reliable.

Had this exact issue migrating our client database last year. Use the ‘after’ parameter HubSpot sends back in their API response - you’re not handling the pagination token right. After your first API call, check if jsonData has a ‘paging’ property with a ‘next’ object. If it’s there, grab that ‘after’ token for your next request. Keep looping with this token until there’s no more paging info. Don’t dump all 7000+ contacts to the sheet at once - learned this the hard way. Google Sheets will timeout on you. Process in batches of 500-1000 and write incrementally. Add error handling too because HubSpot’s API flakes out on large datasets sometimes. Took 15-20 minutes for our 8000 contacts but ran perfectly once I fixed the pagination.