Google Sheets Import & Export – Read, Append & Dedupe Rows
Pricing
$0.05 / 1,000 row moveds
Google Sheets Import & Export – Read, Append & Dedupe Rows
Google Sheets import and export for Apify: read any sheet into a dataset, or append, replace and dedupe-append dataset or JSON rows into Google Sheets. Service-account key (no OAuth pop-ups) or keyless read of public sheets. Connect any Actor via datasetId.
Pricing
$0.05 / 1,000 row moveds
Rating
0.0
(0)
Developer
Enes Bulanık
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
Google Sheets import and export for Apify: read any Google Sheet into a dataset, or append, replace and dedupe-append rows from an Apify dataset or JSON into Google Sheets. It uses a Google service-account key instead of OAuth pop-ups, and public sheets can be read without any key.
Price: $0.05 per 1,000 rows read or written. Errors and skipped duplicates are free.
What does Google Sheets Import & Export do?
It moves rows between Google Sheets and Apify in four modes:
| Mode | What happens |
|---|---|
read | Sheet → dataset. Row 1 is the header and each following row becomes one dataset item. |
append | Dataset/JSON → sheet. Rows are added under the existing data. New fields become new columns at the right. |
replace | Clears the tab and writes the header and all rows from scratch. |
dedupe-append | Appends only rows whose key column (e.g. url or id) is not in the sheet yet. You can run it on a schedule and never get duplicates. |
- Service-account authentication. You paste a JSON key once. It is stored as an encrypted secret input and used only while the run is active. There is no OAuth consent screen and no refresh token that can expire.
- Keyless read of public sheets. If a sheet is shared as Anyone with the link can view, you only need the link.
- Works with any Actor. Pass
datasetId(for example{{resource.defaultDatasetId}}in an integration) and the results of a scraper go straight into your sheet. - Flattening. Nested objects become columns such as
author.name. Lists of simple values are joined with;and lists of objects are stored as JSON text. Cells are cut at Google's 50,000-character limit, so they never cause an error. - Tabs. Pick a tab by name or by the
#gid=in the link. A missing tab is created automatically in write modes. - No formula injection by default. Values are written
RAW, so text that starts with=is not run as a formula. Switch toUSER_ENTEREDif you want Google to parse dates, numbers and formulas.
Use cases
- Export scraper results to Google Sheets after every run: product prices, leads from public directories, news, jobs, reviews.
- Build a growing, de-duplicated list. Schedule a scraper with
dedupe-appendonurl, and only new items are added each day. - Use a sheet as input. Read a list of URLs, keywords or product IDs that your team keeps in Google Sheets, then feed the dataset to another Actor.
- Share dashboards.
replacemode keeps a tab in sync with the latest run for Looker Studio or for colleagues. - AI agents. Let an agent read a sheet or write its findings to one through the Apify MCP server.
How to set up a service account (needed only for writing or for private sheets)
- Open Google Cloud Console and create (or pick) a project.
- APIs & Services → Library → enable Google Sheets API.
- IAM & Admin → Service accounts → Create service account. No roles are needed.
- Open the service account, go to Keys → Add key → Create new key → JSON, and a
.jsonfile is downloaded. - Open your spreadsheet → Share → add the service account e-mail (
name@project.iam.gserviceaccount.com) as Editor. - Paste the whole content of the JSON file into Service account key in this Actor's input.
The service account can access only the spreadsheets you share with it, and nothing else in your Google account.
Input
| Field | Type | Description |
|---|---|---|
spreadsheetUrl | string | Sheet link or ID. A #gid= in the link selects the tab. Defaults to Google's public sample sheet. |
mode | enum | read (default), append, replace, dedupe-append. |
sheetName | string | Tab name. Optional. A missing tab is created in write modes. |
serviceAccountKey | secret string | Service-account JSON key. Needed for writing and for private sheets. |
datasetId | string | Apify dataset to write, e.g. another run's defaultDatasetId. |
jsonData | array | Rows to write, given as JSON objects. Can be used instead of a dataset or together with one. |
dedupeKey | string | Key column for dedupe-append. |
columns | array | Only these columns, in this order. Optional. |
range | string | A1 range for read mode, e.g. A1:F500. |
maxRows | integer | Row limit, 0 = all. |
flattenNested | boolean | Flatten nested objects into dotted columns (default true). |
valueInputOption | enum | RAW (default) or USER_ENTERED. |
failOnError | boolean | Mark the run as FAILED on problems instead of returning a free error item. |
Read a public sheet (this is the default input):
{"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit#gid=0","mode": "read"}
Append only new rows from another Actor's run:
{"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/<your-sheet-id>/edit","mode": "dedupe-append","sheetName": "Products","datasetId": "{{resource.defaultDatasetId}}","dedupeKey": "url","serviceAccountKey": "{ \"type\": \"service_account\", ... }"}
Output
Read mode: one dataset item per row. The keys are the sheet's header names. Empty headers become column_<n>, and repeated headers get _2, _3. Real output from the default input (Google's public sample sheet):
{"Student Name": "Alexandra","Gender": "Female","Class Level": "4. Senior","Home State": "CA","Major": "English","Extracurricular Activity": "Drama Club"}
Write modes: one free summary item:
{"type": "summary","mode": "dedupe-append","spreadsheetId": "1AbC...","spreadsheetTitle": "Price tracker","spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1AbC.../edit#gid=0","sheetTitle": "Products","rowsInSource": 120,"rowsWritten": 17,"duplicatesSkipped": 103,"rowsWithoutKey": 0,"columns": ["url", "title", "price", "currency"],"newColumns": [],"tabCreated": false,"chargeLimitReached": false}
Problems: one free error item, and the run still ends as Succeeded unless failOnError is on:
{"type": "error","errorCode": "PERMISSION_DENIED","error": "Permission denied. Share the spreadsheet with the service account e-mail bot@my-project.iam.gserviceaccount.com (Share → add as Editor for writing, Viewer for reading)."}
Error codes: INVALID_INPUT, NO_CREDENTIALS, INVALID_CREDENTIALS, PERMISSION_DENIED, API_DISABLED, NOT_PUBLIC, SPREADSHEET_NOT_FOUND, SHEET_NOT_FOUND, NO_SOURCE, NO_ROWS, DATASET_NOT_FOUND, NO_DEDUPE_KEY, DEDUPE_KEY_MISSING, BAD_REQUEST, GOOGLE_API_ERROR.
Pricing
Pay-per-event. You pay only for rows that are moved, and platform usage is included.
| Event | Price | When it is charged |
|---|---|---|
row | $0.00005 per row ($0.05 / 1,000) | Each row read from the sheet into the dataset, or written to the sheet |
| Errors, summary items, skipped duplicates | Free |
| Job | Cost |
|---|---|
| Read a 30-row sheet | $0.0015 |
| Append 1,000 scraped products | $0.05 |
| Daily dedupe-append of 5,000 items where 200 are new | $0.01 per day |
Set Max cost per run in the run options to cap spending. The Actor then writes only as many rows as your budget allows and reports chargeLimitReached: true.
Use with AI agents (MCP)
Add the Actor as a tool in the Apify MCP server (https://mcp.apify.com?tools=openharvest/google-sheets-import-export), or let agents find it with search-actors ("google sheets"). MCP clients such as Claude, ChatGPT and Cursor can then read and write Google Sheets. Example tool input that an agent can send:
{"spreadsheetUrl": "https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit#gid=0","mode": "read","columns": ["Student Name", "Major"],"maxRows": 10}
For write modes, the agent passes jsonData (an array of objects). Keep the service-account key in a saved task, so the agent never has to see it.
FAQ
Why a service account instead of "Sign in with Google"? OAuth tokens saved between runs expire or get revoked, and interactive sign-in does not work in scheduled runs or for AI agents. A service account key is passed as a secret input, works the same way every time, and can reach only the sheets you share with it.
Is my key stored? The key is a secret input, so Apify stores it encrypted with your run input. The Actor uses it only in memory during the run, never logs it and never writes it to a dataset or key-value store. You can revoke it at any time in Google Cloud Console.
Can I read a sheet without any key? Yes, if the sheet is shared as Anyone with the link can view. The Actor downloads Google's CSV export. Values come out as displayed text, exactly what CSV export gives you.
What does dedupe-append compare?
The text value of the key column, with spaces trimmed. Rows already in the sheet and repeated rows within the same input are both skipped. Rows that have no key value are appended.
How big can it go? Google Sheets allows 10 million cells per spreadsheet. The Actor writes in batches of 5,000 rows and retries Google's rate limits (HTTP 429) with backoff. Very large datasets (hundreds of thousands of rows) need more memory, so raise the run memory to 2–4 GB.
Can it create a new spreadsheet? No. Service accounts no longer get Drive storage of their own. Create the spreadsheet yourself, share it with the service account, and the Actor fills it. Missing tabs are created automatically.
Formulas?
With the default RAW, a value like =SUM(A1:A3) is stored as text. With USER_ENTERED it becomes a working formula. Use USER_ENTERED only with data you trust.
Privacy and terms
The Actor accesses only spreadsheets that you own or that are shared with your service account, plus sheets their owners made public. It uses Google's official Sheets API and Google's own CSV export. You are responsible for having the right to read and write the data you move, and for following Google's Terms of Service and data-protection laws (e.g. GDPR) when the data includes personal information. The default sample sheet is Google's public demo spreadsheet.
Related actors
Other actors by the same developer whose results are often sent to Google Sheets:
- Google News Scraper – Full Article Text & Real Publisher URLs
- Google Trends Scraper – Interest Over Time & Related Queries
- Keyword Suggestions – Google, YouTube & Amazon Autocomplete
- Website SEO Audit Crawler – Broken Links, Schema & llms.txt
- Shopify & WooCommerce Products Scraper – Any Store, Schema.org
Support & feedback
Something does not work with your sheet? Open an issue in the Issues tab with the error code from the error item. Never paste your key into an issue.