Dataset to Google Sheets Export
Pricing
Pay per event
Dataset to Google Sheets Export
Send any Apify dataset to a Google Sheet. Append, replace, or append only new rows (dedupe by key). Runs after any scraper as an integration. Uses your own Google service account, so no shared quota, and every setup mistake gets a plain-English fix.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Joshua White
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
0
Monthly active users
20 hours ago
Last modified
Categories
Share
Send any Apify dataset to a Google Sheet: after a scraper finishes, on a schedule, or by hand. Rows are appended,
the tab is replaced, or only new rows are added (deduplicated by a key such as url), so a daily run never
writes the same item twice.
It signs in with your own Google service account. That means no "reconnect your Google account" prompts, no quota shared with every other user of a public Google app, and nothing that expires. When something is set up wrong, the run tells you which click fixes it.
What you get
- Three modes: append, replace the tab, or append only new rows (dedupe on one or more fields).
- Runs as an integration after any Actor. Pick this Actor under Integrations on your scraper; the finished run's dataset is exported automatically.
- Clean columns. Nested objects become
address/city-style columns, the same names Apify's CSV export uses. Lists become one readable cell (a, b, c), or one column per element, or JSON text. You choose. - Columns stay put. On later runs, data is matched to your header by name, even if you reordered columns in the sheet. New fields are added as new columns on the right.
- Field selection: export only the fields you name, in your order, or leave some out.
- Big exports, few requests. Rows are sent in batches of up to ~2 MB, so 60,000 rows take about a dozen requests. Rate limits (HTTP 429) and Google hiccups are retried with backoff for up to about two minutes.
- Safe with scraped text. Values are written as plain values, never as formulas, so a scraped
=IMPORTXML(...)stays text. Cells over Google's 50,000-character limit are cut short (and counted in the summary) instead of failing the run. - Checks before it writes. Access, sharing and the 10-million-cell limit are checked before anything is written. Replace mode clears the tab only once the dataset has been read, and an empty dataset leaves the tab as it is.
Setup (about 5 minutes, once)
You need a Google service account: a robot Google user that only gets access to the sheets you share with it. It's free, and Google asks for no billing details to use the Sheets API.
- Open console.cloud.google.com and sign in. In the project picker at the top,
choose New project, name it (for example
apify-sheets), and click Create. Make sure the new project is selected. - Open the Google Sheets API page and click Enable.
- Go to IAM & Admin > Service Accounts > Create service account. Give it a name, click Create and continue, skip the optional role step, and click Done.
- Click the new service account, open the Keys tab, then Add key > Create new key > JSON > Create. A
.jsonfile downloads. - Open that file in a text editor, copy all of it, and paste it into Google service account key (JSON) in this Actor's input. Apify stores it encrypted, and it never appears in logs.
- In the file, find
"client_email"(something likeapify-sheets@your-project.iam.gserviceaccount.com). Open your Google Sheet, click Share, paste that email, choose Editor, untick Notify people, and click Share.
Do steps 1–5 once. For each new spreadsheet, just share it with the same email (step 6).
Google Workspace (company) accounts: some organizations block service-account keys. If step 4 says key creation is disabled by policy, use a personal Google account for the project. Your sheet can still live anywhere, as long as it is shared with the service account's email.
Input
| Field | What it does |
|---|---|
| Google Sheet URL | The sheet's address from your browser. If it ends in #gid=…, that tab is used. |
| Google service account key | The whole JSON key file (see Setup). |
| Dataset | The dataset to export. As an integration: {{resource.defaultDatasetId}} (preset). |
| Mode | append (default), replace, or dedupe (append only new rows). |
| Deduplicate by fields | For dedupe: the field(s) that identify an item, e.g. url. |
| Tab name | Optional. Created if it doesn't exist (you can turn that off). |
| Fields to export / Fields to leave out | Optional column selection and order. A parent name (address) selects all its nested columns. |
| Lists / Nested objects | How arrays and objects become cells (see above). |
| Write header row | On by default; needed for dedupe and for matching columns by name. |
| Skip first items / Max items | Export only part of the dataset. |
Example input:
{"spreadsheet": "https://docs.google.com/spreadsheets/d/1AbC.../edit#gid=0","serviceAccountKey": "{ \"type\": \"service_account\", ... }","datasetId": "aBcDeFgHiJkLmNoP","mode": "dedupe","dedupeFields": ["url"],"fields": ["url", "title", "price"]}
Run it automatically after a scraper
- Open your scraper (or one of its saved Tasks) and go to the Integrations tab.
- Choose Connect Actor or Task, pick this Actor, and use the Run succeeded trigger.
- Fill in the sheet URL, the key and the mode. Dataset is preset to
{{resource.defaultDatasetId}}, which Apify replaces with the finished run's dataset. Keep it as is (if it's empty, type{{resource.defaultDatasetId}}).
This Actor runs with Apify's limited permissions: it can read only the dataset named in its input, nothing else in your account.
With mode dedupe on url (or another ID field), a daily scrape only ever adds what's new.
Use your sheets from an AI agent
For Claude, Cursor or another MCP client, use the separate Google Sheets MCP Server Actor. It shares this Actor's Google code and works with the same service account.
Output
Each run saves a summary to the key-value store (OUTPUT) and as one dataset item: the sheet link, rows written,
duplicates skipped, new columns, cells cut at 50k characters, and whether the run stopped early. The run's status
message says the same in one line.
When something is wrong
Each of these ends the run with a message that names the fix:
| Problem | What the message tells you |
|---|---|
| The sheet isn't shared with the service account | The exact email to share with, as Editor |
| Google Sheets API not enabled in the project | The link to the Enable button |
| Wrong or deleted spreadsheet | Where to copy the right URL from |
| An Excel file stored in Drive | Use File > Save as Google Sheets |
| You pasted an OAuth client file, an API key, or only the private key | What you pasted, and where to get the right file |
| The key was deleted or the service account removed | How to make a new key |
| A protected tab | Remove the protection or allow the service account |
| The export would pass Google's 10,000,000-cell limit | Checked before writing; use a new spreadsheet or fewer columns |
| A mistyped dataset ID | Where to find the ID (no empty dataset is created) |
| Google's quota stays exhausted after retries | Space out runs, or use one service account per workflow |
Limits worth knowing
- Google allows 10 million cells per spreadsheet, counting empty cells in every tab. Long-running append exports eventually need a new spreadsheet; replace mode trims unused rows.
- 50,000 characters per cell. Longer values are cut, and the summary counts them.
- Your service account gets Google's standard quota of 60 write requests per minute. One run uses a few requests per 10,000 rows, so this only matters if many runs write at the same moment.
- New rows go below the last row that has anything in it, anywhere in the tab. Keep notes and totals off the export tab (or above the table), or they end up in the middle of your data.
- Replace mode clears the tab before writing. If a run fails partway, the tab holds a partial export. Run it again.
Pricing
Pay per event: you pay per row written to your sheet. Header rows and rows skipped as duplicates are free, and a run that fails before writing anything costs only Apify's tiny start fee. Set a maximum charge on the run, and the export stops cleanly when it is reached.
FAQ
Is my key safe? The key field is a secret input: Apify encrypts it, and the Actor never logs it. The service account can only open sheets you explicitly share with it. You can delete the key in Google Cloud at any time.
Can it write formulas? No. Everything is written as plain values, on purpose.
Does it read my other files? No. It asks Google only for spreadsheet access, and it can see only sheets shared with it.