Blog
AI AgentsJuly 28, 202613 min read

How to Use Claude for Lead Generation (2026)

How to use Claude for lead generation: give it a real API tool, a worked prompt-to-result example, and how to qualify leads and hand off to outreach.

Claude calling a lead-data API tool and turning the structured result into a qualified list ready for outreach.

Yes, you can use Claude for lead generation, but not by asking it to browse Google Maps in a chat window - Claude reasons, writes, and calls tools, and lead generation needs a tool that returns real business records. Give Claude a lead-data API to call and it can plan a search, qualify what comes back, and hand qualified contacts to an outreach step, all from a single prompt.

What Claude Can and Cannot Do Here

Be honest about the split, because most of the how-to content ranking for "claude lead generation" right now glosses over it. Claude can reason about a request, decide what to search for, call a tool with the right arguments, read structured data back, and write something useful with it - a qualified shortlist, a scored ranking, a personalized outreach draft. Claude cannot open a browser and scroll Google Maps for you, and it does not ship with a business database it can query from memory. Ask Claude "find me 20 plumbers in Leeds with an email" with no tool attached and you get a plausible-sounding answer built from training data, not a real, current list of plumbers in Leeds.

That gap is exactly why tool use exists. Claude supports tool use / function calling: you describe a tool's name, its parameters, and when to call it, and the model decides, mid-conversation, to invoke it with concrete arguments instead of guessing. For lead generation the tool is a business data API - something that actually queries Google Places, visits each business's website, and returns emails, ratings, and contact details as structured JSON. Wire that tool in and the "Claude does lead generation" claim becomes literally true instead of aspirational: Claude plans, the tool fetches, Claude reads the result and keeps working.

This is also why "how to use Claude for lead generation" is a build question, not a settings question. There is no toggle inside Claude for "connect to my leads." You expose an endpoint, describe it once, and the model handles the rest of the conversation - deciding when to call it, what arguments to pass, and what to do with what comes back.

Give Claude a Lead-Data Tool

A minimal, honest tool definition for this job needs five parameters. Here is the shape, using biz collect's POST /api/v1/search as the concrete backing call:

{
  "name": "find_leads",
  "description": "Search for local businesses by location and keyword. Returns names, ratings, websites, and (optionally) verified contact emails as structured JSON.",
  "input_schema": {
    "type": "object",
    "required": ["location", "keywords"],
    "properties": {
      "location": {
        "type": "string",
        "description": "City, region, or place name, e.g. 'Leeds, UK'."
      },
      "keywords": {
        "type": "array",
        "items": { "type": "string" },
        "description": "Business types to search for, e.g. ['plumber', 'emergency plumber']."
      },
      "radius_km": {
        "type": "number",
        "description": "Search radius in kilometers from the resolved location, 1-50."
      },
      "scrape_emails": {
        "type": "boolean",
        "description": "Whether to visit each business's website and extract verified emails and contacts."
      },
      "wait": {
        "type": "boolean",
        "description": "Block the call until the search finishes instead of returning a job to poll."
      }
    }
  }
}

location and keywords are the only required fields on the underlying POST /api/v1/search request; radius_km, scrape_emails, and wait are the ones worth exposing to the model because they change what comes back and how the conversation flows. radius_km accepts 1-50 and defaults to 10. scrape_emails defaults to true and tells the API to fetch each business's website and pull emails, social links, and outgoing links, not just the name-and-address record Google Places returns on its own.

wait: true is the parameter that matters most for an agent loop specifically. Without it, the search is async: the call returns a job_id and a poll_url, and something in your stack has to poll GET /api/v1/jobs/{job_id} until status flips to completed. That is a perfectly normal pattern for a backend job queue, but it is an awkward one for a tool-calling model, which would either need a second tool for polling or a wrapper that hides the loop from it. Set wait: true and the same request blocks server-side (tunable with wait_timeout_seconds, 10-540 seconds, default 300) and returns the finished job - full businesses array included - in that single response. One tool call, one tool result, and Claude keeps reasoning in the same turn instead of managing a poll loop itself. If the timeout elapses before the job finishes, the API falls back to the normal 202 accepted response with wait_timed_out: true, and the agent (or your wrapper) can poll poll_url from there.

A Worked End-to-End Example

Here is what an actual turn looks like once the tool above is wired in.

Prompt:

Find independent coffee shops within 8 km of Bristol, UK. I want ones with a website and a real contact email, not just a phone number.

Claude's tool call:

{
  "location": "Bristol, UK",
  "keywords": ["independent coffee shop", "specialty coffee"],
  "radius_km": 8,
  "scrape_emails": true,
  "wait": true
}

What the tool returns (trimmed to one business):

{
  "job_id": "job_9f3c...",
  "status": "completed",
  "results_count": 34,
  "businesses": [
    {
      "id": "biz_1a2b",
      "name": "Redcliffe Coffee Roasters",
      "address": "12 Redcliffe Hill, Bristol",
      "website": "https://redcliffecoffee.example",
      "website_is_directory": false,
      "emails": ["hello@redcliffecoffee.example"],
      "email_details": [
        {
          "email": "hello@redcliffecoffee.example",
          "confidence": "high",
          "has_mx": true,
          "is_role_account": true,
          "contact": null
        }
      ],
      "rating": 4.8,
      "user_rating_count": 212,
      "primary_type": "coffee_shop",
      "social_links": [{ "platform": "instagram", "url": "https://instagram.com/redcliffecoffee" }]
    }
  ]
}

Claude reads that JSON the same way it reads anything else in context. Given the prompt's filter ("a website and a real contact email"), it drops the businesses in the 34-record result with no website or an empty emails array, keeps the rest, and can summarize: "28 of 34 have a scraped email; Redcliffe Coffee Roasters is a role inbox (hello@) rather than a named contact, rated 4.8 from 212 reviews." Nothing above is invented after the tool call returns - it is the model reading fields that were already in the response and describing them in plain language, which is the whole value of pairing a reasoning model with a structured data source instead of asking either one to do the other's job.

Qualify and Score With the Returned Fields

This is where a tool-using Claude setup earns its keep over a plain scrape: the response carries fields built for exactly this filtering step, and Claude can apply a rubric to them in the same turn it received them.

  • rating and user_rating_count - a 4.8 rating from 3 reviews and a 4.8 rating from 400 reviews are not the same signal. Ask Claude to weight both together rather than rating alone.
  • review_summary - a generated summary of what reviewers actually say, useful for a one-line qualification note without re-reading every review.
  • primary_type - the specific Google place type (e.g. coffee_shop, travel_agency), better for filtering a mixed-keyword search than the raw keyword list you sent in.
  • website_is_directory - true means the website field points at a directory or aggregator listing (a local.ch, a Yelp page) rather than the business's own site. biz collect does not scrape those for emails, since it would just return the directory's contact data, not the business's - treat the URL as a listing, not a homepage, and expect no scraped email in that case.
  • is_role_account vs a resolved contact - every email comes back tagged is_role_account: true or false. A role account (info@, kontakt@, office@) gets contact: null unless a named person is printed right next to that exact address on the site; a personal or named address resolves to a contact object with a first/last name and, where the site is in German, a salutation_de. Ask Claude to greet a resolved contact by name and fall back to the business name - not a guessed name - for role accounts.

A reasonable scoring prompt to give Claude alongside the tool result: "Rank these by rating weighted by review count, prefer a resolved named contact over a role account, and exclude anything where website_is_directory is true." That is a rubric over fields that already exist in the response, not a request to infer facts the API never returned.

From Leads to Outreach

A qualified list is only half the job. The natural next step is drafting outreach, and that is a second tool call to a sibling API rather than something Claude does unassisted - Claude can write a good email, but actually sending one, and tracking whether it sent, is again something that needs a real endpoint.

AutoEmail is built for exactly this handoff: POST /outreach/batch takes the resolved contacts from the search above and drafts (or sends) up to 100 emails per call, either from a fixed template (mode: "final", substituting {{name}}/{{email}}) or generated per recipient from a brief (mode: "generate").

The part worth calling out explicitly, because it is the honest answer to "will the agent send email on its own": AutoEmail keys carry a mode fixed at key creation, and it is enforced by the API, not a suggestion in a prompt. A human_in_the_loop key - the secure default - always returns 201 {"status": "pending_approval"} from a batch call, landing the draft in a review queue instead of sending it. POST /emails/{id}/approve, the endpoint that actually sends, returns 403 mode_not_allowed for a human_in_the_loop key. Only a full_autonomous key can call /approve, and every successful call there consumes one quota unit. So the agent that found the leads can also draft the outreach in the same session, but a person still has to approve the send unless you have deliberately opted a key into full_autonomous mode. That is exactly the split covered in more depth in the AI outreach agent guardrails guide, and the full find-then-draft chain, field by field, lives in the AI agent lead generation pipeline guide.

Cost and Guardrails

Set these before you let Claude run the search loop unattended, because none of them are on by default in the direction you'd want for a first run:

  • max_credits bounds spend on an exhaustive-coverage search (the mode that grids a wide radius into tiles to escape Google's 60-result-per-query cap). If the full tile grid would cost more than max_credits, the tile list is truncated to fit, keeping the most central tiles, and the job is flagged coverage_truncated: true so you know coverage was partial. The minimum is 20 credits, the cost of one search tile.
  • render_fallback: false guarantees zero render charges. Left at its default (true), a site whose plain-HTML scrape finds nothing and looks JavaScript-built gets re-fetched through a headless renderer at +1 credit each, reported in rendered_sites_count and render_credits_charged.
  • On the outreach side, GET /usage reports AutoEmail's current-period quota, so an agent (or you) can check remaining quota before a batch call rather than finding out via a 402 quota_exceeded response on the write itself.

Ask Claude to check GET /usage before drafting a large batch, and to pass max_credits on any exhaustive search it plans, and the cost side of the loop is bounded by real numbers instead of trust.

What to Watch Out For

A few honest caveats worth keeping in the system prompt, so Claude doesn't overstate what a result means:

  • MX verification is not a mailbox probe. Every scraped email gets a confidence tag (high, medium, low, unknown) from syntax validation plus an MX lookup over DNS-over-HTTPS. There is deliberately no SMTP RCPT TO handshake - it is unreliable from a serverless environment and damages sender reputation at scale. confidence: "high" means the domain accepts mail and the address looks like a real, monitored inbox, not that a message to it is guaranteed to land.
  • Some businesses have no website at all, in which case emails and email_details come back empty - there is nothing to scrape.
  • website_is_directory: true means the same, functionally: no email scrape happens against a directory listing, by design.
  • A role-account-only business (only an info@ or kontakt@ address, no named person on the site) still gets contact: null. Have Claude greet the business by name rather than inventing a contact name that was never in the data.
  • robots_skipped_count on the job tells you how many sites were skipped entirely because their robots.txt disallowed the scraper (the default scrape_mode: "respectful" honors it per RFC 9309). A nonzero count is not a bug - it is the scraper behaving as documented.

The Google Places API itself, underneath any of this, does not return an email field at all - every email in a result set came from visiting that business's own website, which is also why some businesses simply have none.

Frequently Asked Questions

Frequently asked questions

Can Claude do lead generation?
Yes, but only with a tool attached. Claude has no business database and cannot browse Google Maps on its own - it reasons, plans, and calls tools. Give it a business data API tool (location, keywords, radius, and an email-scraping flag) and it can plan a search, read the structured result, and qualify or hand off the leads.
How do I use Claude to find business leads?
Define a tool with input parameters like location, keywords, radius_km, scrape_emails, and wait, backed by an API such as biz collect's POST /api/v1/search. Claude decides when to call it and with what arguments based on the user's request, then reads the returned JSON - names, ratings, emails, contacts - to answer follow-up questions or qualify the list.
Does Claude have a business database it can search?
No. Claude's training data is not a live, queryable business directory, and it has no built-in way to browse Google Maps or a business website for you. Every real business record in a Claude-driven workflow comes from a tool call to an actual API, not from the model's own knowledge.
How do I use Claude for lead generation without manually polling a job?
Set wait: true on the search request. Instead of getting back a job_id you have to poll, the call blocks server-side (up to wait_timeout_seconds, default 300, max 540) and returns the completed job - full business list included - in the same response, so Claude gets a usable result in one tool call instead of needing a second polling tool.
How do I create an AI agent for lead generation with Claude?
Wire two tools: a search tool (find_leads, backed by a business data API) and an outreach tool (backed by an email-drafting API like AutoEmail). Claude calls the first to get qualified businesses, then the second to draft outreach - with a human-in-the-loop approval gate before anything actually sends, since neither Claude nor a well-designed outreach API should send email unattended by default.
Can Claude send the outreach emails itself once it finds leads?
Not by default. AutoEmail's human_in_the_loop mode - the secure default - makes every draft land as a pending approval (201 pending_approval); the send endpoint, POST /emails/{id}/approve, returns 403 mode_not_allowed for that key. Only a full_autonomous key can approve and send, and that mode has to be deliberately chosen.
Is a high-confidence email from a Claude lead search guaranteed to be a real inbox?
No. Confidence is based on syntax validation and an MX lookup over DNS-over-HTTPS, not an SMTP mailbox probe - that check is deliberately not performed, since it is unreliable from a serverless environment and can damage sender reputation. A high confidence tag means the domain accepts mail and the address looks like a monitored inbox, not a guaranteed live mailbox.

Turn the article into an API call.

Use biz collect free: 200 signup credits, no credit card, and a clean JSON contract your agent or workflow can call today.

No credit card required200 signup credits20 daily login credits