n8n lead generation: the five stages of a prospecting pipeline that runs itself
Most “AI lead generation” templates break in the same three places: the price of the maps API, the memory of the deduplication node, and the model returning something that is not JSON. This is the architecture that survives all three, with the numbers we measured on a real run.
What the pipeline actually has to do
Strip the marketing away and manual B2B prospecting is five steps, repeated by a person: find candidate businesses, decide which ones have a visible problem, write down why they are worth contacting, write the first message, and put the result somewhere a CRM can read. Every one of those steps is a node.
The pipeline below is a scheduleTrigger flow with 13 executable nodes. It runs at 08:00,
produces a sheet and a CSV, and sends nothing to anybody — by design, the sending stays manual and yours.
Stage 1 — Find candidates without overpaying for the map
Use Places API (New) with the places:searchText endpoint. The legacy API has been
closed to new customers since 2025, so half of the tutorials you will find point at an endpoint that
returns 403 on a fresh Google Cloud project.
The important, under-documented detail is that the field mask sets the price. Google bills the
highest SKU present in the response. Ask for displayName and formattedAddress
and you are in Essentials. Add rating and you are in Pro. Add
nationalPhoneNumber or websiteUri and you are in Enterprise, at
USD 35 per 1,000 requests instead of free.
X-Goog-FieldMask: places.id,places.displayName,places.formattedAddress,
places.primaryTypeDisplayName,places.rating,places.userRatingCount,
places.businessStatus,places.nationalPhoneNumber,places.websiteUri
That is deliberate. A list of names without a phone and a website is not a lead list; it is a phone book. The two fields that make a prospect contactable are exactly the two that move you into Enterprise — so budget for it instead of being surprised by it:
| Leads wanted | Requests | Places cost | AI cost | Total |
|---|---|---|---|---|
| 60 (one daily run) | 3 | 0.105 | 0.003 | 0.11 |
| 1,000 | 50 | 1.75 | 0.056 | 1.81 |
| 10,000 | 500 | 0 (free tier) | 0.56 | 0.56 |
| 20,000 | 1,000 | 0 (free tier) | 1.12 | 1.12 |
| 100,000 | 5,000 | 140.00 | 5.60 | 145.60 |
USD, measured 16 Oct 2026: Google Text Search Enterprise tier (first 1,000 requests per month free, which
covers roughly 20,000 leads) and deepseek-flash with 660 input / ~120 output tokens per lead.
Provider prices change — re-check before a large month.
Pagination is where the second surprise lives. Google wants a couple of seconds between pages before
nextPageToken is valid; paginate at full speed and the API answers 400.
n8n's HTTP Request node has native pagination, so set Max Requests to 3 and a
requestInterval of 2000 ms. Three pages × 20 results = 60 businesses per run, and the loop
stops by itself when the response stops carrying a token.
Stage 2 — Normalise into one row per business
Never let the shape of an API response leak into the rest of the flow. One Code node flattens every
place into a fixed row: placeId, name, address, category, rating, review count, phone,
website, and a small digital-gap heuristic computed from those fields — no website, mobile-only
site, few reviews, permanently closed. That heuristic is not the final score; it is a cheap prior that
keeps the expensive model honest.
Stage 3 — Deduplicate (and know that this node remembers)
The removeDuplicates node with operation Remove Items Seen in Previous Executions
stores the keys it has seen, per workflow, in the instance database — not in the execution. That is the
feature you want: a daily run should not send yesterday's leads to your CRM again.
It is also the most common reason a template “works once and then returns nothing”. Second run, same data, 0 items, chain stops. If you are debugging exactly that, the full explanation and the one-click remedy are in the dedupe post mortem.
Stage 4 — Score and write with an LLM, batched
One HTTP Request node to the model, in batches of 4 items with a 1.2 s interval. Two settings matter more than the prompt:
response_format: { type: "json_object" }— kills most parse failures before they happen.- Reasoning disabled — measured on our own account: 117–121 output tokens per lead with reasoning off, versus 351–800 with it on, plus intermittent empty responses when the model burned its budget thinking. Five times the cost for a worse answer.
The prompt must return the id it was given, and the next Code node must rebuild the
placeId → business map instead of trusting item order. Batched requests come back
reordered, partially, or not at all; pairing by identifier makes the flow deterministic anyway.
{
"places": [
{ "id": "ChIJ...", "score": 78, "senales": ["sin web propia", "3 resenas"],
"dolor": "no aparece al buscar su servicio",
"pitch": "Hola, vi que ..." }
]
}
And wrap the parse in try/catch. Losing one lead from a batch is a small cost; losing the
whole 60-lead run because model output #41 had a trailing comma is not.
Stage 5 — Branch to outputs, filter with a threshold
An if node compares the model score to a minScore you configure once. Above:
Google Sheets, then CSV, then (optionally) a webhook to your CRM. Below: a no-op so you can count the
discards and see whether your rubric is calibrated. Outputs hang off the same branch in parallel, so you
can disable Sheets without breaking the CSV.
Start at minScore 60 and raise it to 70 once you have seen a week of output. Raising it
costs nothing and saves AI tokens; lowering it is how you end up with 200 rows nobody calls.
What to verify before you trust any template (including ours)
- Import it into a clean instance and count the resolved node types. A type that does not exist in your version fails at import, silently or loudly depending on the version.
- Run the logic with mocked third parties, so the only variable is your own data.
- Check the
typeVersionceiling. A flow built on a newer package may still run on an older instance — n8n falls back to the newest version it has — but that is a reason to prefer a current instance, not a guarantee. - Read the failure list before you need it. Every workflow has a small set of failures it will reproduce on a new machine.
That is the checklist we ran on our own kit: both flows imported and executed on clean
n8n 2.43.6 and n8n 1.60.0 instances, 28/28 node types resolved, 13/13 and 8/8 nodes in
success, and a real 1,065-byte CSV produced by the run.
If you would rather not build it from scratch
The Starter kit is this exact pipeline plus the meeting-notes-to-CRM flow, the 8-field configuration node, a validator, a self-test script and six documents in ES/EN — USD 49, one time, runs on the n8n you already have.
See what's inside Next: the scoring rubricRelated: a lead-scoring rubric that holds up on real data · why your workflow returns 0 items the second time · all articles