Google Sheets Sync: Export Datasets & JSON to Sheets avatar

Google Sheets Sync: Export Datasets & JSON to Sheets

Pricing

from $0.07 / 1,000 row writtens

Go to Apify Store
Google Sheets Sync: Export Datasets & JSON to Sheets

Google Sheets Sync: Export Datasets & JSON to Sheets

Export any Apify dataset or JSON to Google Sheets reliably. Append, replace or dedupe/upsert rows by key, batch 100k+ rows, auto-retry Google errors, clear fixes in every error. Official Sheets API, your own service account.

Pricing

from $0.07 / 1,000 row writtens

Rating

0.0

(0)

Developer

Nicholas Powers

Nicholas Powers

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

5 hours ago

Last modified

Share

Google Sheets Sync: Export Apify Datasets & JSON to Google Sheets

Get scraper results into Google Sheets on every run, without losing rows or babysitting the export. Append new rows, replace a tab, or dedupe and upsert by a key such as url, id or email. Tested live with 100,000 rows in one run, retries Google errors on its own, and every error message tells you how to fix it.

  • ⚡ Quick start: paste a sheet URL, a dataset and a Google service account key, then run
  • 🔁 Append, replace, dedupe or upsert, with new fields added as new columns
  • 🧱 Large datasets: streamed in batches, rate-limited under Google's quota, checked against the 10M-cell limit before writing
  • 🛡️ Safe by default: never rewrites existing rows on append, never wipes a tab on an empty scrape, no formula injection
  • 🔌 Works as an integration: results go to Sheets each time your scraper finishes
  • 💸 $0.10 per 1,000 rows. Skipped duplicates are free, and there's no separate compute charge

Running with empty input (no sheet, credentials or data) exits successfully with a short demo message so Store health checks pass; provide a spreadsheet + credentials + datasetId for a real sync.

Why teams switch to Google Sheets Sync

Many dataset-to-Sheets exports download the whole sheet, merge it in memory, and write all of it back on every run. That gets slower as the sheet grows, hits cell limits, and lets two runs finishing at once overwrite each other. Google Sheets Sync is built differently:

Google Sheets Sync
AppendUses Google's append API. Existing rows, formatting and formulas are never rewritten
Parallel runsTwo runs writing to one tab at the same time keep all rows (tested live)
Dedupe / upsertReads only the key column(s) from the sheet, not the whole tab
Big datasetsStreams the dataset in pages; 100,000 rows in about 2 minutes (tested live)
LoginYour own service account key, so no shared app that Google can block and no expiring browser login
ErrorsPlain-English fixes, e.g. "Share the spreadsheet with sync@project.iam.gserviceaccount.com as an Editor"
RetriesExponential backoff on Google 429/5xx errors and network drops
PermissionsApify limited permissions: it can read only the dataset you give it, with no approval prompt

Quick start (about 5 minutes the first time)

  1. Create a Google service account key. See Setup: service account below.
  2. Share your Google Sheet with the service account email (…@….iam.gserviceaccount.com) as Editor.
  3. Fill in the input:
    • Google Sheet URL: paste the browser URL. #gid= picks a tab, or type a Tab name and it's created if missing.
    • Mode: append, replace or dedupe.
    • Apify dataset: pick the dataset from your scraper run.
    • Google service account key: paste the whole JSON file. It's stored encrypted as a secret.
  4. Run. The log ends with a link to your sheet.
{
"spreadsheet": "https://docs.google.com/spreadsheets/d/1AbC.../edit#gid=0",
"sheetName": "Leads",
"mode": "dedupe",
"dedupeOn": ["url"],
"updateExisting": true,
"datasetId": "aBcD1234efGH",
"serviceAccountJson": "{ \"type\": \"service_account\", ... }"
}

A service account is a robot Google account that never expires and never asks you to log in again.

  1. Open Google Cloud Console and create a project (any name, no billing needed).
  2. Enable the Google Sheets API: console.cloud.google.com/apis/library/sheets.googleapis.com.
  3. Go to IAM & Admin → Service accounts → Create service account. A name is enough; skip the roles.
  4. Open the account and go to Keys → Add key → Create new key → JSON. A .json file downloads.
  5. In Google Sheets, click Share and add the account's client_email as Editor.
  6. Paste the full contents of the JSON file into Google service account key.

Workspace admins: if key creation is blocked by the iam.disableServiceAccountKeyCreation policy, ask your admin for an exception or use OAuth below.

Setup: OAuth (alternative)

Use this if you can't create service account keys.

  1. In Google Cloud Console, create APIs & Services → Credentials → OAuth client ID (type Desktop app) and enable the Google Sheets API.
  2. Get a refresh token with the scope https://www.googleapis.com/auth/spreadsheets, for example with the OAuth 2.0 Playground using your own client ID and secret ("Use your own OAuth credentials").
  3. Fill in OAuth client ID, OAuth client secret and OAuth refresh token.

The sheet must belong to, or be shared with, the Google account that authorized the token.


Run it automatically after every scraper run (integration)

  1. Open your scraper or task in Apify Console and go to Integrations → Connect Actor or task → Google Sheets Sync.
  2. The Apify dataset field is prefilled with {{resource.defaultDatasetId}}, the dataset of the run that just finished. Keep it.
  3. Add your sheet URL, mode and key, then save.

Every time the scraper succeeds, its new results go into your sheet. Use dedupe mode with dedupeOn so that re-scraped items update or skip instead of piling up.

Custom webhooks: send {"datasetId": "{{resource.defaultDatasetId}}", ...} as the payload and turn on Interpolate variables in string fields. A dataset ID that appears only inside the raw webhook payload isn't shared with limited-permission Actors, so always map it into the dataset field.


Modes

ModeWhat it doesGood for
append (default)Adds rows at the bottom. New fields become new columns on the rightLogs, daily exports
replaceClears the tab and writes fresh data, keeping your header order. An empty source leaves the tab untouchedDashboards, "latest snapshot"
dedupeAppends only rows whose dedupeOn key isn't in the sheet yetLead lists, monitoring
dedupe + updateExistingUpsert: updates matching rows in place and appends new onesPrice trackers, CRM syncs, job boards

Other options:

  • data: a JSON array instead of a dataset
  • columns: which fields to write, and in what order
  • omitColumns
  • flatten: nested values become a.b and list/0 columns, like Apify's CSV export
  • limit / offset
  • maxRows: a cap on rows written per run
  • batchSize
  • requestsPerMinute
  • clearIfEmpty
  • parseValues: lets Google turn text into dates, numbers and formulas. It's off by default, so values are written as-is

Pricing

Pay only for rows actually written to your sheet. Skipped duplicates are free.

Rows writtenFree plan ($0.10 / 1K)Bronze ($0.09 / 1K)Silver ($0.08 / 1K)Gold+ ($0.07 / 1K)
1,000$0.10$0.09$0.08$0.07
10,000$1.00$0.90$0.80$0.70
100,000$10.00$9.00$8.00$7.00

Plus Apify's standard start fee of $0.00005 per run. Example: a daily scraper adding about 300 new rows in dedupe mode costs about $0.90 a month. Set Max cost per run in Apify and the Actor stops cleanly before going over it.


Output

Each run saves a summary to the default dataset and to the OUTPUT record in the key-value store:

{ "mode": "dedupe", "sheetTitle": "Leads", "itemsRead": 5000, "rowsAppended": 412, "rowsUpdated": 4588, "duplicatesSkipped": 0, "columns": 14, "url": "https://docs.google.com/spreadsheets/d/.../edit#gid=0" }

Troubleshooting

MessageFix
Permission denied. Share the spreadsheet with …Share the sheet with the service account email shown, as Editor
Google Sheets API has not been used in project … / is disabledEnable the Sheets API for the project your key belongs to
Google says this service account does not existThe key or account was deleted. Create a new JSON key
Your Google key could not be usedPaste the whole JSON file, including the -----BEGIN PRIVATE KEY----- block
Spreadsheet not foundCheck the URL, and that the sheet is shared with the service account
This run has no access to dataset …Pick the dataset in Apify dataset, or map {{resource.defaultDatasetId}} into it in the integration
…was not filled in ({{…}})Your webhook didn't interpolate variables. Turn on Interpolate variables in string fields
…over Google's 10,000,000-cell limitUse a new spreadsheet, delete unused tabs, restrict columns, or use replace
Google Sheets quota exceededLower requestsPerMinute, raise batchSize, or avoid many parallel runs on one key

FAQ

Does it work with Google Maps, Instagram, Amazon or any other Apify scraper? Yes. It reads any Apify dataset.

Will it overwrite my formatting or formulas? Not in append or dedupe mode. Rows are added below, and upserts change only the matched rows. replace clears cell values in the target tab.

Can several scrapers write to the same sheet? Yes. Use one tab per scraper, or the same tab. Parallel appends were tested without losing rows.

What about very large datasets? Rows are streamed and batched; 100,000 rows took about 2 minutes in testing. A Google spreadsheet holds at most 10 million cells, and the Actor checks that limit before writing.

Is my Google key safe? It's a secret input: Apify encrypts it, and it never appears in logs. The Actor runs with limited permissions and can't see the rest of your Apify account.

Can I import from Google Sheets into Apify? This Actor exports datasets and JSON to Sheets.

Keywords: export Apify dataset to Google Sheets, scraper to Google Sheets, JSON to Google Sheets, Google Sheets integration, append rows to Google Sheets, dedupe, upsert, Google Sheets API automation, sync data to spreadsheet.