Google Sheets Import & Export: Sync, Upsert, Dedupe
Pricing
from $0.01 / 1,000 row written or reads
Google Sheets Import & Export: Sync, Upsert, Dedupe
Export any Apify dataset to Google Sheets after every scraper run: append, replace or upsert rows by key, skip duplicates, and add new fields as columns. Or import a sheet into a dataset. Uses your own Google service account, so there's no login to expire. $0.01 per 1,000 rows.
Pricing
from $0.01 / 1,000 row written or reads
Rating
0.0
(0)
Developer
Charles Markette
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Google Sheets Sync exports any Apify dataset to Google Sheets, or imports a sheet back into a dataset. Run it on its own, or connect it as the last step after any scraper so every run appends, replaces or upserts rows in your spreadsheet automatically. It's for anyone who keeps scraped leads, prices, listings or monitoring results in a Google Sheet: marketers, sales teams, analysts and no-code builders, as well as developers who want a reliable Sheets export from the Apify API.
- Append: add rows to the end. Optionally skip rows whose key, for example
urlorid, is already in the sheet (dedupe on append). - Replace: rewrite the tab with the new data. The grid is sized exactly, and old rows and columns are removed.
- Upsert: update rows that have the same key, add the new ones, and leave every other row alone. This is ideal for price trackers, lead lists and daily monitors.
- Read (import): load a tab into an Apify dataset. The first row is the header.
Why use Google Sheets Sync?
- Your own Google service account. There's no Google login to expire or re-connect, and changes to Actor permissions don't break your schedules. The key is a secret input, stored encrypted.
- Safe big writes. Rows go out in large batches with automatic backoff on Google's per-minute quota. Google's 10M-cell limit (all tabs, whole grid) is checked before anything is written. Appends use retry-safe writes below your last used row, so a retried request can't add the same rows twice.
- Your sheet stays intact. In upsert mode, rows you didn't send keep their formulas, dates and exact text (
00123stays00123), and columns with blank or repeated headers keep their data. Very large IDs are written as text so they never get rounded, and in the default RAW mode, scraped text that starts with=stays text instead of becoming a formula (also when an upsert rewrites it later). - New fields become new columns automatically, and existing columns keep their place. Nested data is flattened into columns like
address/cityandimages/0. - Limited permissions. The Actor can only read the dataset you pick and its own storage.
- Low, predictable price. $0.01 per 1,000 rows; duplicates you skip are free.
Use cases
- Scraper to spreadsheet: send Google Maps, Amazon, LinkedIn or any other scraper's results to a sheet after every run.
- Price and stock trackers: upsert by product URL or SKU so each product stays on one row and its price updates daily.
- Lead lists: append new leads and skip the ones already in the sheet, so your sales team never works a lead twice.
- Monitoring dashboards: keep a sheet that Looker Studio or a pivot table reads from up to date.
- Import a sheet into Apify: read a tab of URLs or keywords into a dataset that another Actor uses as input.
How to use Google Sheets Sync
Setup (about 3 minutes, one time)
- Go to Google Cloud Console and create a project, or pick an existing one.
- Enable the Google Sheets API: APIs & Services → Library → Google Sheets API → Enable.
- Go to IAM & Admin → Service Accounts → Create service account. Give it any name, and skip the roles.
- Open the service account, then Keys → Add key → Create new key → JSON. A
.jsonfile downloads. - Open your spreadsheet and click Share. Add the service account's
client_emailfrom the JSON file (it looks likename@project.iam.gserviceaccount.com) as an Editor. - Paste the whole JSON file content into Google service account key, and paste the spreadsheet URL.
Export a dataset to Google Sheets
- Pick the Dataset to export (for example the output of a scraper run).
- Choose the Mode (
append,replaceorupsert) and, for upsert or dedupe, the Key fields (likeurl). - Click Start. The run summary in the key-value store
OUTPUTtells you how many rows were written, updated, added and skipped, with a link to the spreadsheet.
Run it automatically after another Actor (integration)
- Open the scraper's Actor or saved task, go to the Integrations tab and click Add integration.
- Search for Google Sheets Sync, choose to start it when the run succeeded, and set the input. Apify fills in
{{resource.defaultDatasetId}}with that run's dataset:
{"spreadsheet": "https://docs.google.com/spreadsheets/d/…","sheetName": "Leads","mode": "upsert","keyFields": ["url"],"datasetId": "{{resource.defaultDatasetId}}","serviceAccountKey": "…"}
- Save, and use the integration's test menu to try it on a past run.
Only want the items that are new since the last run? Put Merge & Deduplicate Datasets in "only new" mode in between, or use upsert / append with Skip rows already in the sheet.
Input example
{"spreadsheet": "https://docs.google.com/spreadsheets/d/1AbC…/edit","sheetName": "Prices","mode": "append","datasetId": "aBcDeFgHiJkLmNoPq","keyFields": ["url"],"dedupeOnAppend": true,"columns": ["title", "price", "url"],"valueInputOption": "RAW","serviceAccountKey": "{ \"type\": \"service_account\", … }"}
| Field | Notes |
|---|---|
| Spreadsheet URL or ID | The sheet must be shared with the service account as Editor. Without a spreadsheet and key, the run only returns a setup reminder (nothing is written). |
| Sheet (tab) name | Created if it doesn't exist (write modes). Read mode fails if the tab is missing. Default Sheet1. |
| Mode | append, replace, upsert or read. |
| Dataset | The dataset to export. In integrations use {{resource.defaultDatasetId}}. |
| Raw data | Alternative to a dataset: objects, or arrays with a header row. |
| Key fields | Identify a row for upsert and for skipping duplicates. |
| Skip rows already in the sheet | Append only. |
| Columns | Optional field list and order. |
| How Google should interpret values | RAW (exact values) or USER_ENTERED (formulas, dates and locale parsing). |
| Nested field separator | Default /, as in address/city. |
| Max rows | Optional cap. |
Output example
Write modes save a run summary in the key-value store OUTPUT:
{"mode": "upsert","spreadsheetId": "1AbC…","sheet": "Prices","rowsWritten": 2140,"rowsRead": 0,"updated": 1985,"added": 15,"skippedDuplicates": 0,"columns": ["url", "title", "price", "currency", "inStock"],"apiRequests": 6,"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1AbC…"}
In upsert mode rowsWritten is the size of the whole tab after the merge, and updated + added are the rows you sent. Read mode outputs one dataset item per sheet row, with the header row as field names (blank headers become column_N, repeated ones name_N).
How much does it cost to export to Google Sheets?
Google Sheets Sync uses pay-per-event pricing: $0.00001 per row written or read ($0.01 per 1,000 rows), plus a $0.001 run start fee. Rows are charged as they're written. In upsert mode you pay for the rows you sent that were updated or added (each key once); rows already in the sheet that you didn't send are free. Rows skipped as duplicates are free.
Examples use the Free-plan rate. Where an example doesn't add it, each run also has its run-start charge, counted per GB of Actor memory (minimum one; one at the default memory); Apify Proxy (where used) is billed separately.
Worked example: a daily price tracker that upserts 2,000 products costs 2,000 × $0.00001 = $0.02, plus $0.001, so $0.021 per run, or about $0.63 per month with 30 daily runs.
If you set a maximum cost per run, the Actor writes only as many rows as that allows and tells you in the log.
FAQ
Do I need to connect my Google account?
No. You use a Google Cloud service account (a robot account) and share the spreadsheet with its email address. Nothing expires, so scheduled runs keep working.
"Google denied access (403)". What's wrong?
The spreadsheet isn't shared with the service account's client_email as an Editor, or the Google Sheets API isn't enabled in the service account's Cloud project. Fix either and run again.
"Spreadsheet not found (404)".
Check the URL or ID, and that the spreadsheet is shared with the service account.
"Service account key must be the full JSON key file content".
Paste the whole downloaded .json file, from the first { to the last }, without editing it. If Google says the key was rejected, it may have been deleted or disabled: create a new JSON key.
How does upsert decide which row to update?
By the Key fields. Key matching treats 1, 1.0 and "1" as the same key. Rows with an empty key are never matched (blank rows stay where they are), and input rows with an empty key are added as new rows.
My dates or numbers look different in the sheet.
In the default RAW mode values are stored exactly as given. Choose USER_ENTERED if you want Google to parse dates, numbers and = formulas in your data the way it does when you type them. Cells already in the sheet keep their formulas, dates and text either way.
The run says the sheet would go over 10 million cells.
Google counts every cell of every tab's grid. Use Columns to pick fewer fields, delete unused rows and columns in other tabs, or write to another spreadsheet. Nothing is written when this check fails.
Can I write to several tabs?
Yes, one tab per run. Save one task per tab, or connect several integrations.
Limitations
- Google allows 10 million cells per spreadsheet and 50,000 characters per cell. Longer values are cut off with "…".
- Upsert and replace rewrite the tab's values and size the grid to fit the data, so extra empty rows and columns are removed. Cell formatting is kept.
- Memory: at the default 1 GB, a run handles about 2 million cells (rows × columns). Give the run more memory for bigger sheets.
- If a run fails partway through a large write (for example Google is down for minutes), the rows written so far stay and are billed; re-run the same input in upsert mode, or append with "Skip rows already in the sheet", to finish without duplicates.
- Use one writer per tab: two runs appending or upserting into the same tab at the same moment can overwrite each other's rows. Give parallel scrapers their own tabs.
- Append mode reads the tab once to find the last used row (and existing keys when skipping duplicates).
- Not affiliated with Google.
Related Actors
Google Sheets Sync is part of a small suite of Actors that work together after any scraper:
| Actor | Use it to |
|---|---|
| CSV & Excel to Dataset | Read a shared Google Sheet or an Excel/CSV file back into a dataset. |
| Merge & Deduplicate Datasets | Merge runs and keep only items not seen before, then send just those to your sheet. |
| Send Email Report & Slack, Discord, Teams, Telegram Alerts | Get a Slack or email message with a preview whenever new rows arrive. |
| Dataset Delivery | Deliver the same data as a CSV or Excel file to SFTP, FTP, Dropbox or Google Drive. |
| SEC Funding Rounds Tracker | Feed a sheet of newly funded companies from SEC Form D, Form C and Reg A filings. |
| Vector DB Sync | Load any dataset into Pinecone or Qdrant for RAG. |
| Phone Number Validator & Formatter | Validate and format phone numbers (E.164) before they go into your sheet. |
| Dataset Filter & Transform | Pick, rename and flatten fields so they fit your sheet's columns. |
| RSS & Atom Feed Reader | Feed new blog, news or podcast items into a sheet on a schedule. |
| Bulk URL Status Checker | Check a sheet of URLs for broken links and SSL expiry on a schedule. |
| PDF & Image to Text | Pull tables and text out of PDFs and scans, then send the rows to your sheet. |
| Broken Link Checker | Crawl a website for broken links and keep the list in a Google Sheet. |
| Website Contact Info Scraper | Collect company contact details from their websites and send them to your sheet. |
| Website Tech Stack Detector | Keep a sheet of websites with their platform and marketing tools. |
| Career Page Jobs Scraper | Keep a sheet of open jobs at the companies you track. |