Dataset to Google Sheets — No OAuth avatar

Dataset to Google Sheets — No OAuth

Pricing

from $5.00 / 1,000 sheet updateds

Go to Apify Store
Dataset to Google Sheets — No OAuth

Dataset to Google Sheets — No OAuth

Append or replace rows in your Google Sheet from any Apify dataset. Share the sheet once with the Actor's e-mail; no Google login, no tokens that expire.

Pricing

from $5.00 / 1,000 sheet updateds

Rating

0.0

(0)

Developer

Duffy Radmilović

Duffy Radmilović

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

16 hours ago

Last modified

Share

Send any Apify dataset into your Google Sheet: append new rows, skip duplicates, or replace the tab. There's no Google login and no OAuth token. Share your sheet once with the Actor's e-mail and it keeps working. No token to expire, no invalid_grant, no reconnecting accounts.

Why this exists

The usual way to get scraped data into Google Sheets is to connect your Google account with OAuth. Those tokens expire, get revoked, or get tied to the wrong account, and scheduled runs start failing.

This Actor uses a Google service account instead. You give it access the same way you'd give a colleague access: Share → add an e-mail → Editor. It can only touch spreadsheets you shared with it.

Setup (one minute, once per spreadsheet)

  1. Create or open a Google Sheet.

  2. Click Share and add this e-mail as Editor:

    sheets-bot@helena-sheets.iam.gserviceaccount.com

    If Google says the address has no Google account, share anyway. That's normal for service accounts.

  3. Copy the sheet link into the Google Sheet link field and pick a dataset.

If you forget step 2, the run tells you exactly that, with the e-mail to add. It charges nothing beyond Apify's minimal start fee.

Use it after another Actor (the main use case)

Run a scraper on a schedule and have every run land in the same sheet automatically:

  1. Open the scraper (or its task) in Apify Console → Integrations → connect an Actor → choose Dataset to Google Sheets — No OAuth.

  2. In the integration input set:

    {
    "spreadsheetUrl": "https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/edit",
    "sheetName": "Results",
    "mode": "append",
    "dedupeBy": "url",
    "datasetId": "{{resource.defaultDatasetId}}"
    }
  3. Done. Each successful scraper run appends only rows whose url isn't in the tab yet.

Important: the dataset has to arrive through the datasetId field. Apify only grants this Actor read access to datasets passed that way.

Tested end to end: a scraper run followed by this Actor wrote 57 rows. The next identical run wrote 0 and skipped 57 duplicates.

Input

fielddefaultmeaning
spreadsheetUrl(required)Link of the Google Sheet, or its ID.
sheetNameSheet1Tab to write into. Created if missing.
datasetId—Dataset to copy. In integrations use {{resource.defaultDatasetId}}.
rows—Alternative to a dataset: a JSON array of objects.
modeappendappend adds rows below existing ones. replace clears the tab first.
dedupeBy—Field name. In append mode, rows whose value is already in that column are skipped.
columnsallWhich fields to write, in this order. Nested fields use dots: price.amount.
maxRows0Safety brake. 0 = no limit.

How data is laid out

  • Nested objects are flattened: {"price": {"amount": 7}} → column price.amount.
  • Lists of simple values become one cell: ["a","b"] → a, b. Lists of objects become a JSON string.
  • The header row only ever grows. Existing columns keep their position; new fields get new columns on the right. Your formulas and formatting to the left stay where they are.
  • Values are written as they are (RAW). Numbers stay numbers and text stays text. A product code like 00123 isn't turned into 123, and a date-like string isn't reinterpreted.

Output

One row per run in the default dataset:

{
"status": "OK",
"spreadsheetId": "17gw...nxU",
"sheetName": "Shopify",
"mode": "append",
"rowsIn": 57,
"rowsWritten": 0,
"rowsSkippedDuplicate": 57,
"columns": ["shopDomain", "productId", "variantId", "title", "price"],
"sheetUrl": "https://docs.google.com/spreadsheets/d/17gw...nxU/edit#gid=...",
"message": "Wrote 0 rows to \"Shopify\", skipped 57 duplicates.",
"finishedAt": "2026-09-24T19:16:10.000Z"
}

Problems come back as a row with a clear status, not just a log line:

statusmeaning
NOT_SHAREDThe sheet isn't shared with the Actor's e-mail. The message says which e-mail to add.
SPREADSHEET_NOT_FOUNDThe link doesn't point to an existing sheet.
DATASET_NOT_FOUNDThe dataset doesn't exist.
DATASET_NOT_ACCESSIBLEThe dataset wasn't passed through the datasetId field (see above).
EMPTY_DATASETNothing to write. Nothing charged.
BAD_INPUTMissing or invalid input. The message says which field.
TOO_LARGEWriting would pass Google's 10 million cells per spreadsheet. Checked before writing.
RATE_LIMITEDGoogle kept refusing after several retries with back-off.
CHARGE_LIMIT_REACHEDYour maximum cost per run is too low to write anything.

Pricing

Pay per event:

eventprice
Sheet updated (once per successful run)$0.005
Rows written, per started 1,000 rows$0.02
  • 500 new rows a day → $0.025 a day, about $0.75 a month.
  • One-off export of 12,000 rows → 12 × $0.02 + $0.005 = $0.245.
  • A scheduled run with no new rows (all duplicates) still costs $0.005, because the sheet was checked.
  • Failed runs (not shared, bad input, empty dataset) are not charged.

If you set a maximum cost per run, the Actor writes only as many rows as that limit covers, then says so in the result.

Limitations — please read

  • It can't create spreadsheets. Service accounts have no Drive storage of their own, so the Actor only writes into a sheet you created and shared.
  • Google's limit is 10 million cells per spreadsheet, counting every tab. For very large exports use a new spreadsheet or pick fewer columns.
  • One cell holds at most 50,000 characters. Longer values are cut off with ….
  • Google allows about 60 write requests per minute for this service account. The Actor writes up to 5,000 rows per request and retries with back-off, so normal use never gets close. Very heavy parallel use may be slowed down.
  • dedupeBy checks one column. It compares values as text.
  • replace clears values, not formatting.

Privacy

  • The Actor can open only spreadsheets you explicitly shared with its e-mail. Share a sheet made for this purpose, not your whole Drive.
  • It reads the spreadsheet's tab names and sizes, plus the header row and the dedupeBy column of the tab it writes to. It reads no other cell contents.
  • Remove access at any time: Share → remove the e-mail.
  • The Actor stores no copy of your data outside your Apify run.

FAQ

Why not just use Apify's Google Drive integration? That uploads a file (CSV/JSON) into a Drive folder. This Actor writes rows into a live Google Sheet, appends, and skips duplicates.

Can I write several scrapers into one spreadsheet? Yes, use a different sheetName for each.

Does it work with shared drives / Google Workspace? Yes, if your organisation allows sharing with outside e-mails. Some companies block it. Then the run returns NOT_SHARED.

What if Google is down or slow? Requests are retried with exponential back-off. Rows already written stay written and are reported in the result.