Arcadium Data Scrapers
Home / Integrations / n8n / Weekly Google Maps local business leads to Google Sheets

Weekly Google Maps local business leads to Google Sheets

Businesses of one type in an area with phone, website, rating and review count; every Monday only the places not in the sheet yet. Uses Google Maps Places Scraper.

Every Monday this workflow runs Google Maps Places Scraper (arcadium/google-maps-places) for a business type in an area, for example dentists in Austin, TX, and appends the places that are not in your Google Sheet yet: name, category, address, phone, website, rating, review count, Google Maps link and the date the place was first seen. Over time the sheet becomes a lead list that grows only by new businesses.

Schedule (Mon 07:00) → Apify: Run actor and get dataset → Google Sheets: Get rows → Code: new places only → Google Sheets: Append row

File: workflow.json (n8n workflow export format, with a sticky note that repeats the setup steps).

What you need

CredentialWherePlaceholder in the file
Apify API tokenApify Console → Settings → API & IntegrationsREPLACE_WITH_YOUR_APIFY_CREDENTIAL_ID (credential type Apify API)
Google Sheetsn8n's Google Sheets OAuth2 credentialREPLACE_WITH_YOUR_GOOGLE_SHEETS_CREDENTIAL_ID (two nodes)
A spreadsheetYour Google DriveREPLACE_WITH_YOUR_SPREADSHEET_ID in the sheet URL (two nodes)

The Apify node is Apify's official n8n node, package @apify/n8n-nodes-apify (node version 2, operation Run actor and get dataset). On n8n Cloud search for "Apify" in the nodes panel. On self-hosted n8n: Settings → Community nodes → Install → @apify/n8n-nodes-apify.

Import

  1. Create a Google Sheet with a tab named Places and this header row (the nodes read and write columns by name):

placeId | cid | name | category | address | phone | website | rating | reviewCount | googleMapsUrl | searchTerm | firstSeen

  1. n8n → Workflows → Import from File → workflow.json.
  2. Search Google Maps: pick your Apify credential and edit the JSON input:
  3. searchTerms: what you would type into Google Maps, one business type per entry (dentist, plumber, coffee shop).
  4. location: a city, district, region or postcode (Austin, TX, Schwabing, Munich). The area is searched map cell by map cell, so a city search is not limited to one result list.
  5. maxPlacesPerSearch: places per search term and run (100 in the template, 0 = every place found in the area).
  6. website: any in the template; with keeps only places that list a website, without only places without one (a common lead filter for web agencies).
  7. skipClosed: true leaves out places Google marks as closed.
  8. Optional filters: minRating (such as 4), categoryFilter (such as ["dentist"]), language and country.
  9. Read places in sheet and Append new places: pick your credential and paste your sheet URL in both.
  10. Execute once (the first run fills the sheet), check it, then Activate.

How "only new places" works

New places only compares each place with the rows already in the sheet on placeId, Google's stable id of a place, and on cid as a fallback. Places already in the sheet are dropped; new ones get today's date in firstSeen. The same place found by two search terms is written once.

Why a sheet lookup and not n8n's Remove Duplicates node with "Remove items processed in previous executions": that node keeps its history inside n8n. The history is lost when you import or duplicate the workflow, a place counts as seen even when the Sheets append afterwards fails, and it does not notice rows you delete or add by hand. With the lookup the sheet is the only memory: delete a row and the place comes back next week as new, add a place by hand and it is never added twice. Reading one sheet once a week is fast for tens of thousands of rows. If you prefer the Remove Duplicates node anyway, replace Read places in sheet with it (operation "Remove Items Processed in Previous Executions", value to dedupe on {{ $json.placeId }}) and leave the lookup part of New places only with an empty sheet list.

The append node writes values as they are (cellFormat: RAW), so the 19-digit cid stays exact and phone numbers are not turned into numbers.

Cost per run

Pay per event. Prices are the actor's Store pricing at the time of writing (Free plan; paid Apify plans pay less). The live price is on the Store page.

EventPriceIn this template
Place$0.002 ($2.00 per 1,000)2 search terms × 100 places = $0.40 per week
Coverage and error rowsfree

Plus Apify's small start event per run. The node caps a run at $0.50 (maxTotalChargeUsd). Every place the search returns is charged each week, also the ones already in your sheet: the dedupe keeps the sheet free of repeats, it does not lower the run cost. To spend less, lower maxPlacesPerSearch, run every two or four weeks, or narrow the search with minRating, website or categoryFilter.

What to expect