如何用 n8n 免費工作流程擷取 Google Maps 潛在客戶資料
How to scrape Google Maps leads with n8n (free workflow)
Scraper Finder 示範匯入免費六節點 n8n 工作流程,擷取 Google Maps 商家資料並整理成可供 Google Sheets 使用的資料列。在紐約餐廳的 20 個地點測試中,流程約 10 秒完成,13 個地點取得電郵,Apify 費用約 $0.45。工作流程以 placeId 去重;文章建議同步執行維持 20 至 50 個地點,數百個地點則改用非同步流程。
Last updated: 6 November 2026 (n8n 2.46)
Short answer: import a free six-node workflow into n8n, add your Apify API token as a Query Auth credential, type a search like "restaurants in New York, NY", and click Execute. You get one row per business (name, address, phone, website, email, rating, Google placeId), deduped and ready to append to Google Sheets. A 20-place test costs about $0.45 on Apify's free plan.
Disclosure: I maintain the free workflow repo used here. The scraping step runs a paid Apify Actor on your own Apify account (it has a free monthly credit), so the real costs have their own section. I wrote this with AI help for the wording; the steps, settings and numbers come from my own runs.
What does the workflow return?
One row per business with these fields: name, googleBusinessCategories, street, city, state, zip, phoneNumber, url (the business website), email, reviewScore, reviewsNumber and placeId. The clean-up node adds _source and _scrapedAt. Social profile links, googleMapsUrl and coordinates are in the full output when the Actor finds them.
In a 20-place test for "restaurants in New York, NY", the run took about 10 seconds and 13 of the 20 places came back with an email.
The six nodes:
Daily trigger → Configure input → Run Apify Actor → Normalize + dedupe → Rows ready → Google Sheets (optional)
How do I set it up? (5 steps)
1. Import the workflow
In n8n, open a new workflow, click ⋯ → Import from URL and paste the raw file link:
https://raw.githubusercontent.com/bolvein-firex/scraping-n8n-workflows/main/workflows/google-maps-business-lead-and-email-finder.json
The file has no tokens, credentials or sheet IDs in it, so nothing runs until you do steps 2 and 5.
2. Add your Apify token as a Query Auth credential
Run Apify Actor is a plain HTTP Request node, not a community node, so it works on n8n Cloud and self-hosted.
- In the Apify Console, copy your API token (Settings → API & Integrations).
- In n8n, open Run Apify Actor → Credential → create a Query Auth credential.
- Query parameter name:
token. Value: your Apify token. Name the credential anything, for example "Apify API Token".
Apify reads the token from the ?token= query parameter, which is what Query Auth adds. In a credential it never ends up in an exported workflow or a screenshot.
3. Edit the search in "Configure input"
Configure input is a Code node that returns the Actor's input:
-
searchQueries: one phrase per search, with the place in the phrase ("plumbers in Leeds", "coffee shops in Austin TX"). Several phrases per run are fine. -
max_results: 20 for the first run (why: see the timeout question below). -
extractEmails: true: reads each business's own website for contact emails. This fills theemailcolumn. -
onlySaveResults: "onlyWithContacts": drops places with no email or phone.
The starter input is validated against the Actor's input schema. When you add fields, copy the names from the Actor's Input tab: an unknown field is silently ignored, which is a confusing way to lose a filter.
4. Run it and check "Rows ready"
Click Execute workflow. Rows ready is a No Operation node that lets you look at the cleaned rows before anything is written.
5. Turn on Google Sheets
The Google Sheets (optional) node ships disabled, so a test can't write to a real sheet by accident.
- Enable it and add a Google Sheets OAuth2 credential.
- Replace
YOUR_GOOGLE_SHEET_IDwith the ID from your sheet's URL, and set the sheet name (the file usesRows). - It uses Append with Map Automatically, so the field names become the columns.
For a daily schedule, switch to Append or Update and match on placeId. That stops yesterday's places from being appended again. The Daily trigger fires at 08:00 in your instance's timezone.
Why does the workflow dedupe on placeId and not email?
Because chains share emails. My first version deduped on email and lost real rows: five branches of one franchise, with five addresses, phones and ratings, collapsed into one row because they shared info@. placeId is Google's own ID for a place and stays the same between runs.
| Dedupe key | Keeps every branch? | Stable between runs? | Use it for |
|---|---|---|---|
placeId |
Yes | Yes | The places sheet (this workflow) |
email |
No, chains collapse | Mostly | The send step, so one inbox gets one message |
phoneNumber |
No, call centres collapse | Mostly | Rarely useful |
Business name
|
No, "Starbucks" collapses | No | Don't |
If you're emailing these leads, dedupe on the lowercased email in the outreach step, right before sending. A reader on Reddit also pointed out that crawled info@ addresses bounce a lot, so put an email verifier right before the send step too. Not before the sheet: that way you only pay to verify the rows you actually contact.
Why does the run time out, and how big can a run be?
The node calls Apify's run-sync-get-dataset-items endpoint. It starts the Actor and returns the rows in the same HTTP response, so there's no polling loop. Apify ends a synchronous request after 300 seconds, so the node timeout is set to 300000 ms to wait exactly that long.
With extractEmails on, the Actor visits every business website, so large pulls take minutes. Keep sync runs at 20 to 50 places. For hundreds of places, switch to the async pattern: POST /v2/acts/{actor}/runs, wait for it to finish, then GET /v2/datasets/{datasetId}/items.
Also, Google returns a ranked window of roughly 150 to 220 businesses per search phrase, so asking one phrase for 1,000 results won't get you 1,000. Split by neighbourhood or category instead.
What happens when the Apify run fails?
Apify answers with an object like {"error": {"type": "...", "message": "..."}}. Depending on the failure and on the HTTP node's response settings, that object can reach the next node as an ordinary item, and you find one junk row in your sheet a week later. The clean-up node checks for it first and fails the execution with Apify's message:
const rows = $input.all().flatMap((item) => (Array.isArray(item.json) ? item.json : [item.json]));
const failed = rows.find((row) => row && row.error && typeof row.error === 'object' && Object.keys(row).length === 1);
if (failed) throw new Error(`Apify: ${failed.error.type || 'error'} ${failed.error.message || ''}`.trim());
After that, it trims strings, drops null fields and keeps one row per placeId.
How much does it cost to scrape Google Maps with n8n?
n8n is free self-hosted (n8n Cloud has its own plans). The scraping is billed by Apify, pay-per-event, to your account. On Apify's Free plan ($5 of credit a month):
| Item | Price |
|---|---|
| Run start | $0.10 per GB of run memory (4 GB default = $0.40 per run) |
| Each place returned | about $0.001 |
| Platform compute | a few cents |
| 20-place test | about $0.45 |
| Daily run, 30 days | about $13 a month on the Free plan, mostly start fees |
So the free credit covers about ten test runs. Paid Apify plans are cheaper per event. Check the Actor's Pricing tab before you schedule anything, and keep max_results small until you know what a run returns.
FAQ
Do I need to know JavaScript?
No. You only edit the JSON object in "Configure input". The two Code nodes work as shipped.
Does it work on n8n Cloud?
Yes. It uses only core nodes (Schedule Trigger, Code, HTTP Request, No Operation, Google Sheets).
Can I search outside the US?
Yes. Put the place in the phrase ("dentists in Lyon, France"), or set country and locationQuery in the input.
Is scraping Google Maps legal?
These are public business listings, but a business email can still be personal data (GDPR in the EU and UK, similar laws elsewhere). Check what you're allowed to do with it, where you and the recipients are, before you contact anyone.
Can I use it without Google Sheets?
Yes. Leave the Sheets node disabled and connect anything after Rows ready: Airtable, Postgres, a CRM node or a webhook.
Is there a version for Claude Code or other AI agents?
Yes. The same Actor is wrapped as an agent skill (a SKILL.md with the real input and output fields): google-maps-business-lead-and-email-finder skill.
More free workflows like this
The same six-node shape exists for other public data: Amazon and Shopify prices, Zillow listings, Indeed jobs, TikTok and Reddit search, Google Trends. Each workflow has a docs page with the Actor's real input and output fields: bolvein-firex/scraping-n8n-workflows. The next articles in this series take one source each. Short demos are on YouTube @ScraperFinder.
If something breaks on your n8n version, or you want a source that isn't there, leave a comment here or open an issue on the repo.
來源:DEV Community · dev.to

