All articles

How to build a Google Maps leads workflow in n8n (with verified emails)

Build a Google Maps leads workflow in n8n: your data source options, the 60 and 120 result caps, a node-by-node REST API and webhook build, then Sheets or Instantly.

The Leadraft teamLeadraft
Published
Read time
11 min
Category
Playbook

To build a Google Maps leads workflow in n8n, you need a data source first: n8n has no official Google Maps node, so workflows either call the Google Places API through the HTTP Request node, run a scraper through a community node, or call a lead tool's API. The core build is four nodes: start a search, wait and poll until it finishes, page through the leads, and write them to Google Sheets or a sending tool. If you want n8n to receive leads instead of fetching them, a Webhook node can catch them as they're exported. Below are the options, the result cap that breaks most templates, and a node-by-node build with exact endpoints.

What are my options for getting Google Maps data into n8n?#

There are three ways to get businesses from Google Maps into n8n, and they differ in how many businesses you get per search and whether emails come with them. We checked n8n's integrations directory in November 2026 and found no official Google Maps or Places node; the Google nodes listed are Sheets, Gmail, Drive, Calendar and Gemini.

Scroll horizontally if needed →

RouteHow it works in n8nResults per queryEmailsRuns on n8n Cloud
Google Places APIHTTP Request node to Text Search (New), with your API keyUp to 60 (20 per page, 3 pages)No: Google doesn't provide themYes
Community node or scraper actorA community node (for example one wrapping an Apify actor) or an HTTP call to the scraper's APIDepends on the actor and its settingsSome actors crawl websites for emails; checks varyVerified community nodes only
Lead tool REST APIHTTP Request nodes to the tool's API, or its webhook into an n8n Webhook nodeWhole area, dedupedDepends on the toolYes

Two n8n details matter here. First, unverified community nodes "aren't available on n8n cloud" and need a self-hosted instance; only verified ones install from the in-app nodes panel. Many Google Maps community nodes are small, early packages, so check their version history before you depend on one. Second, n8n counts an execution as "a single run of your entire workflow", regardless of how many steps it has. As of November 2026, n8n Cloud's Starter plan was listed at €20 a month (billed annually) for 2,500 executions, and the self-hosted Community edition is on GitHub.

On terms: Google's Maps terms restrict scraping Maps content, and the Places API has its own rules about storing data. Read is scraping Google Maps legal before you build a large pipeline, and get legal advice if you resell or store the data long term.

Why do n8n Google Maps templates stop at 60 or 120 results?#

Because one Google search is capped, and most templates run one search per city. Google's Text Search (New) reference says it "returns a maximum of 60 results across all pages", and the Maps interface itself stops at about 120 places per search. A template that runs "dentist in Phoenix" through either route gets the top of Google's ranking and silently misses everyone else.

One Google Maps search versus a tiled search of the same areaLeft: a single search returns results bunched around the middle of the area and stops. Right: the area split into a grid of tiles, each searched separately, finds businesses across the whole area, including the edges. In one measured run, a single search found 230 coffee shops in Portland and the tiled search found 457.One searchSame area, searched tile by tileResults stop, bunched in the middleEvery tile searched, edges included
One search stops after a few hundred results, mostly near the middle. Searching the area tile by tile reaches the edges. Measured once: Portland coffee shops, 230 from one search vs 457 tiled (measured on one city and one keyword.)

The fix is the same whatever tool you use: split the area into small tiles, search each tile, split any tile that still returns the full cap, try several names for the trade ("dentist", "dental clinic", "orthodontist"), and dedupe by Google place ID. Building that inside n8n is possible, but it means a grid generator, a recursive split, and a lot of API calls billed per request, not per business. Our 120 results limit guide walks through the method, and Places API vs scraping works through what the API calls cost.

The rest of this guide uses a lead tool's API as the source, so n8n only has to orchestrate. The example is Leadraft's REST API, because its endpoints are documented publicly; the same shape works with any tool that has a "start search, poll, read results" API.

How do I build the workflow node by node?#

The pull version of the workflow has six nodes and runs as one execution. Here it is end to end:

Schedule Trigger (or Manual Trigger)
  → HTTP Request: POST /searches          (start the search, keep "group")
  → Wait: 30 seconds
  → HTTP Request: GET /searches/{group}   (check status)
  → If: status is "completed"?
       false → back to Wait
       true  → HTTP Request: GET /leads   (paginated)
             → Google Sheets: Append or Update Row (match on place ID)

Step 1: Create a credential for the API key#

In Leadraft, create an API key under Settings → API keys. Keys look like lg_.... In n8n, create a Header Auth credential (one of the HTTP Request node's generic authentication methods) with the name Authorization and the value Bearer lg_your_key. Every HTTP Request node below uses it. The API allows 120 requests a minute per key, which a polling workflow never gets near.

Add an HTTP Request node:

Scroll horizontally if needed →

SettingValue
MethodPOST
URLhttps://app.leadraft.co/api/v1/searches
AuthenticationGeneric credential type → Header Auth
Send HeadersIdempotency-Key: a unique value, for example the execution ID
BodyJSON (below)
{
  "queries": ["dentist in Phoenix, AZ", "orthodontist in Phoenix, AZ"],
  "email_required": true,
  "scope": "in"
}

Each line is its own search, up to 500 lines and 25 locations per request. scope: "in" counts only businesses inside the city boundary; "near" adds a ring set by scope_km. The response returns 201 with a group (keep it) and a failed array listing any line that couldn't run and why. The Idempotency-Key header means a retried node returns the first answer instead of starting the searches twice. A 402 means the account is out of business credits.

Tip: you can paste the curl example from the API docs into the node with Import cURL. Imported values come in as strings, so switch the body to Using JSON if you need real booleans.

Step 3: Wait, then poll the status#

Add a Wait node set to After Time Interval, 30 seconds. Then an HTTP Request node:

  • Method: GET
  • URL: https://app.leadraft.co/api/v1/searches/{{ $('Start search').item.json.group }} (use your node's name)

The response has status, which is running, finishing (searching is done, emails are still being found and checked), paused or completed, plus businesses, with_email, searches_done and searches_total. The docs suggest polling every 10–30 seconds; businesses usually start arriving within minutes.

Add an If node: {{ $json.status }} equals completed. Connect the false branch back to the Wait node. n8n offloads waits of 65 seconds or more to its database, so if you'd rather poll every two minutes on a long search, that's fine too.

Don't treat finishing as done: at that stage the businesses are in, but emails are still being checked, and reading early gives you rows without them.

Step 4: Read the leads, page by page#

On the true branch, add an HTTP Request node:

Scroll horizontally if needed →

SettingValue
MethodGET
URLhttps://app.leadraft.co/api/v1/leads
Query parameterssearch_group = the group, grade = valid, limit = 500
PaginationUpdate a Parameter in Each Request: query cursor = {{ $response.body.next }}

/leads is keyset-paged: each page returns items and a next value, which you send back as cursor. Set the node to stop when next comes back null, which marks the last page. grade=valid returns only Verified emails; add a second grade parameter with catch_all if you want accept-all addresses too (keep them in a separate sheet or campaign). Invalid addresses are never returned.

Then add a Split Out node on items, so each lead becomes its own n8n item.

One billing detail: reading a Verified address you haven't been charged for uses one checked-email credit, once. If credits run out, the email comes back null with email_withheld: true, and it fills in on a later read.

Step 5: Write to Google Sheets without duplicates#

Add a Google Sheets node with the Append or Update Row operation, which updates a matching row or adds a new one at the end. Match on the place ID column so re-running the workflow updates businesses instead of duplicating them. Map the columns you'll use: name, email, email grade, phone, website, city, rating, review count.

If you only need a sheet, you can skip n8n entirely: Leadraft's live feeds give you a private CSV link that Google Sheets reads with =IMPORTDATA(...) and refreshes about once an hour.

How do I make n8n receive leads instead of polling?#

Use a Webhook node and let the lead tool push. This is the better pattern for monitors, which find new businesses on a schedule and send only the new ones.

  1. Add an n8n Webhook node, method POST. Turn on the Raw Body option, because the signature is computed over the exact bytes sent. Set Respond to Immediately.
  2. Activate the workflow and copy the production URL. The test URL only works while the editor is listening.
  3. In Leadraft, choose Webhook as the destination when you export a segment, or as a monitor's destination, and paste the URL. Optionally generate a signing secret under Settings → Integrations → Webhook.
  4. Verify the signature. Each request carries X-LeadGrid-Signature: sha256=<hex>, an HMAC-SHA256 of the raw body keyed with your secret. n8n's Crypto node has an Hmac action with SHA256 and HEX encoding; compute it over the raw body, prefix sha256=, and drop the request in an If node if it doesn't match.
  5. Split Out the leads array, then write each lead to Sheets, a database or a CRM.

What arrives:

{
  "source": "leadgrid",
  "export_id": 3141,
  "count": 200,
  "leads": [
    {
      "email": "hello@brightsmile.example",
      "email_grade": "valid",
      "business": "Bright Smile Dental",
      "category": "Dentist",
      "phone": "+15125550142",
      "website": "https://brightsmile.example/",
      "city": "Austin",
      "state": "Texas",
      "country": "US",
      "in_area": true,
      "place_id": 48213,
      "google_place_id": "ChIJ…"
    }
  ]
}

Rules worth building around:

  • Leads come in batches of 200, so one export of 1,000 leads is five requests and five n8n executions.
  • Answer with a 2xx within 30 seconds. Network errors and 5xx answers are retried (3 attempts in total); a 4xx stops the push. "Respond Immediately" keeps you inside the window.
  • A batch can arrive more than once, so upsert on place_id, never blind-append.
  • Webhooks carry lead batches, not events. There's no "search finished" event yet; to react when a search completes, use the polling loop above.
  • The URL must be public and final: redirects aren't followed and private networks are refused. Self-hosted n8n behind a firewall needs a public tunnel or reverse proxy.

The full payload and field list are in the webhooks docs.

How do I send the leads from n8n to Instantly or a CRM?#

Add one more HTTP Request node per lead. For Instantly, the API v2 call is POST https://api.instantly.ai/api/v2/leads with a bearer token, a campaign (the campaign's ID), the email, and extra fields in custom_variables:

{
  "campaign": "your-campaign-id",
  "email": "{{ $json.email }}",
  "company_name": "{{ $json.business }}",
  "website": "{{ $json.website }}",
  "custom_variables": { "city": "{{ $json.city }}", "category": "{{ $json.category }}" },
  "skip_if_in_workspace": true
}

Instantly's reference also lists skip flags (skip_if_in_workspace, skip_if_in_campaign) and a verify_leads_on_import flag. Leave verification off for addresses that are already Verified, and keep the skip flag on so the same business isn't emailed from two campaigns. Use the HTTP Request node's batching options (items per batch, batch interval) to stay under Instantly's rate limit.

That said, n8n in the middle only earns its place if you're doing something to the leads on the way: scoring them, writing a first line with an AI node, routing by city. If you just want leads in a campaign, a direct push is fewer moving parts. Our guide to importing Google Maps leads into Instantly covers the column mapping either way.

Which pattern should I use?#

Pick by what starts the work.

Scroll horizontally if needed →

You wantPatternn8n nodes
Run a search on a schedule and collect the resultsPull: start, poll, readSchedule Trigger, HTTP Request ×3, Wait, If, Google Sheets
Get new businesses in a market as they appearPush from a monitorWebhook, Crypto, If, Split Out, destination
Send an existing segment to a custom destinationPush from an exportWebhook, Split Out, destination
Just a sheet that stays currentNo n8n: live feedNone (IMPORTDATA in Sheets)

FAQ#

Does n8n have a Google Maps scraper node?#

Not an official one, as far as we could find in n8n's integrations directory in November 2026. Most n8n Google Maps workflows call the Google Places API with the HTTP Request node, run a third-party scraper (such as an Apify actor) through a community node or HTTP call, or call a lead tool's REST API.

Why does my n8n Google Maps workflow stop at 60 or 120 results?#

Because one Google search is capped. Google's Places API Text Search returns at most 60 results across all pages, and the Maps interface stops at about 120. To get every business in a city you have to split the area into smaller tiles, search each, and dedupe by place ID, or use a source that does that for you.

Can n8n receive leads from Leadraft automatically?#

Yes, through a webhook. Add an n8n Webhook node, copy its production URL, and choose Webhook as the destination when you export a segment or set up a monitor in Leadraft. Leadraft posts the leads as JSON in batches of 200, signed with HMAC-SHA256 if you set a signing secret. There is no native Leadraft node.

How many n8n executions does a Google Maps leads workflow use?#

n8n counts one execution per run of a whole workflow, however many nodes it has. A workflow that starts a search, waits, polls and writes rows is one execution per run. A webhook workflow is one execution per batch it receives.

Can I send the leads from n8n to Instantly?#

Yes. Call Instantly's API (POST /api/v2/leads with a campaign ID and the email) from an HTTP Request node, one lead per item. If you don't need n8n in the middle, Leadraft can also push to Instantly directly.

Sources#

  1. n8n Docs, HTTP Request node (generic Header Auth, pagination modes, $response, batching, Import cURL), seen November 3, 2026.
  2. n8n Docs, Webhook node (test vs production URL, Raw Body, Respond options, 16 MB payload), seen November 3, 2026.
  3. n8n Docs, Wait node (resume options; waits of 65 seconds or more offloaded), seen November 3, 2026.
  4. n8n Docs, Crypto node (Hmac with SHA256, HEX encoding).
  5. n8n Docs, Google Sheets: sheet operations (Append or Update Row).
  6. n8n Docs, Install community nodes (unverified nodes not available on n8n Cloud).
  7. n8n, Pricing (plans, executions, definition of an execution), seen November 3, 2026.
  8. Google for Developers, Text Search (New) ("returns a maximum of 60 results across all pages").
  9. Instantly, API v2: Lead (create lead, campaign, custom_variables, skip and verify flags).
  10. Leadraft docs: REST API, webhooks, live feeds.

Lead lists for the trades in this article