Google Sheets Sync: Append & Deduplicate
Pricing
from $0.10 / 1,000 row writtens
Google Sheets Sync: Append & Deduplicate
Append Apify dataset items to Google Sheets without rewriting the sheet. Stable columns, de-duplication by key, crash-safe batches and clear fix-it error messages.
Pricing
from $0.10 / 1,000 row writtens
Rating
0.0
(0)
Developer
Neatrow
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Features
Share
Send the results of any Apify Actor straight into a Google Sheet. New rows are added under your existing data. The sheet is never rewritten, so your formulas, notes and extra columns stay where they are.
Typical uses:
- Daily scraper → sheet. Add this Actor as an integration on your scraper. Every run appends only the new results.
- Price or job tracking. De-duplicate by
urlorid, so the same product or job never shows up twice, even across hundreds of runs. - Hand-off to non-technical teammates. They get a plain spreadsheet that keeps filling itself.
Why this instead of a full export
| This Actor | Typical full export | |
|---|---|---|
| Appending | Writes only the new rows | Often re-reads and rewrites the whole sheet |
| Re-runs and retries | De-duplicate by any field, so it's safe to run again | Duplicates or overwrites |
| Crashes and retries | Every write targets an exact range and is checked after a restart, so a crash or a retried request never duplicates rows or bills them twice | Can duplicate rows |
| New fields in your data | Added as new columns at the right end. Existing columns never move | Columns can shift |
| Errors | Tells you exactly what to fix (for example "share the sheet with bot@… as Editor") | Generic API error |
| Formula injection | Values are written as plain values, so a scraped =IMPORTXML(...) never runs | Depends |
Setup (about 3 minutes, one time)
- Open Google Cloud Console, then create a project, or pick an existing one.
- Go to APIs & Services → Library, search for Google Sheets API and click Enable.
- Go to IAM & Admin → Service accounts → Create service account. Any name works, and it needs no roles.
- Open the service account, then Keys → Add key → Create new key → JSON. A
.jsonfile downloads. - Open your spreadsheet, click Share, and add the service account's email (it looks like
name@project.iam.gserviceaccount.com) as an Editor. - Paste the whole content of the
.jsonfile into Google service account key in this Actor. Apify stores it encrypted.
Try it without setup
Run it with an empty input (or with only datasetId) to see a free preview of the rows exactly as they would be written: nested fields flattened, columns in order. Nothing is written and no rows are billed.
Input
| Field | What it does |
|---|---|
spreadsheet | Sheet URL or ID |
sheetName | Tab name. It's created if missing. Default Sheet1 |
serviceAccountKey | JSON key from the setup above (secret) |
datasetId | Dataset to sync. As an integration use {{resource.defaultDatasetId}} |
mode | append (default) or replace (clears values but keeps formatting, then writes) |
dedupeFields | For example ["url"]. Skips items already in the sheet |
columns | Optional. Write only these fields, in this order |
maxRows | Stop after this many rows (0 = no limit) |
Nested objects are flattened to parent.child columns. Arrays are written as JSON text.
Use it as an integration
On your scraper (Actor or task), open Integrations → Add → Apify Actor and pick this Actor. Fill in the spreadsheet and key, and set Dataset ID to {{resource.defaultDatasetId}}. Each finished run is then synced automatically. Add dedupeFields (for example ["url"]) so repeated results are skipped.
Example input
{"spreadsheet": "https://docs.google.com/spreadsheets/d/1AbC.../edit","sheetName": "Products","serviceAccountKey": "{ \"type\": \"service_account\", ... }","datasetId": "a1B2c3D4e5F6g7H8i","mode": "append","dedupeFields": ["url"]}
Output
The run's dataset and OUTPUT record hold a summary:
{"rowsWritten": 1240,"duplicatesSkipped": 85,"itemsRead": 1325,"columns": 14,"stopReason": "done","spreadsheetUrl": "https://docs.google.com/spreadsheets/d/.../edit#gid=0"}
Pricing
Pay per event: a small fee per run plus a fee per row actually written. Skipped duplicates are free. If a run reaches your maximum cost per run, it stops cleanly and tells you. In append mode with dedupeFields set, run it again to continue: rows already in the sheet are skipped.
Limits
- Google Sheets holds at most 10 million cells per spreadsheet. A cell holds at most 50,000 characters, so longer values are truncated and marked
…[truncated]. - Google rate limits are handled automatically with retries and backoff.
- Don't write to the same tab from two runs at once.
- A run that would push the spreadsheet past 10 million cells stops before writing and tells you.
FAQ
"Permission denied". The sheet isn't shared with the service account email. The error message shows the exact email to add as Editor.
Can I keep formulas next to the data? Yes. In append mode existing cells are never touched. Only empty rows in the data columns are written, so formula columns to the right of the data stay as they are.
Does replace delete my formatting? No. It clears values only. It only clears once the run has something to write, so an empty or failed input never empties your sheet.
I added my own columns (formulas, notes). Are they safe? Yes. The Actor only writes the columns of the fields it syncs. New fields are added to the right of everything already in use, never on top of your columns.
Found a bug or need a feature? Open an issue on the Issues tab. We answer quickly.