All articles

How to Get Enriched Google Maps Leads With an AI Agent

A practical resource for Claude Code, Codex, Cursor, Manus, and other agents that need local business leads with owners, emails, phones, websites, and outreach context.

B
Bennett Black|

The money in local lead generation is not in the scrape.

The scrape is the first step. It gives you business names, phone numbers, websites, categories, ratings, and addresses. That is useful, but it is not enough to sell web design, SEO, ads, reputation management, recruiting, software, or any other local service at scale.

The money comes from what happens next:

  • finding the businesses that match a real offer
  • knowing who owns or runs them
  • finding usable emails and phone numbers
  • understanding what is weak about their website or online presence
  • writing outreach that references something specific
  • exporting everything into a CRM or cold email workflow

That is where Claude Code becomes interesting. Claude can write scripts, filter data, build CSVs, generate personalization, and wire the output into your stack. But it still needs one thing before it can help: a reliable lead source with data an AI can actually reason about.

LocalProspects is that lead gen skill.

You give Claude a simple markdown skill file. After that, it can search for local businesses, wait for enrichment, inspect the fields, filter the best prospects, and save a CRM-ready export from a plain English request.

The lead gen workflow that actually matters

Most people think the workflow is:

  1. Scrape a city and niche.
  2. Export a spreadsheet.
  3. Send a generic email.

That works poorly because the list is too raw. A roofing company with 400 reviews, a claimed profile, a modern website, and no visible owner is not the same lead as a roofing company with 18 reviews, no analytics, a broken WordPress site, and an owner name on the About page.

The workflow you want Claude to run looks more like this:

  1. Search a niche and location.
  2. Enrich every business with contact, website, owner, tech, and service data.
  3. Score the businesses against the offer.
  4. Filter out bad targets.
  5. Generate outreach using real context.
  6. Export the results to Instantly, GoHighLevel, HubSpot, Airtable, Google Sheets, or a custom CRM.

That is the difference between "I scraped 1,000 leads" and "I have 125 businesses that match my offer, have reachable contacts, and have a reason to take the call."

What Claude needs to know

For Claude Code to do useful lead gen work, it needs more than a CSV download. It needs a clear map of the whole system:

  • Lead source: where the businesses come from
  • Search inputs: niche, city, region, location code, result limits
  • Authentication: how to call the API without exposing the key
  • Job lifecycle: whether results are immediate or async
  • Field schema: which fields exist and what they mean
  • Enrichment depth: whether the tool only returns listings or also reads websites
  • Contact quality: whether emails and phones are verified or just scraped
  • Personalization fields: services, tech stack, owner names, review data, website copy
  • Export rules: which fields should become CSV columns
  • Outreach guardrails: do not invent facts, do not use invalid emails, do not send without approval

A markdown skill file is a good format for that. Claude reads it like project instructions, then follows the same sequence every time.

The alternatives: what most tools give you

There are plenty of ways to get local business lists. The important question is not "can it scrape leads?" The question is "does it return enough structured context for an AI agent to decide what to do next?"

Here is the practical map.

ToolBest forWhat Claude getsWhat is usually missing
Outscraperraw Google Maps-style business exports at low per-record costnames, categories, phones, websites, ratings, addresses, export/API accessowner names, verified emails, phone type, multi-page website text, service extraction, AI-ready business summaries
D7 Lead Finderclassic lead finder searches with emails, social links, and some website flagsbusiness names, phone, website, email, address, review fields, social URLs, WordPress/pixel/analytics flagsdeeper website crawl, owner extraction, email quality scoring, phone carrier/type, richer service and selling-point fields
Apify Google Maps actorsflexible scraping infrastructure and actor-based workflowsplace records, reviews, images, optional contact-detail scraping depending on the actor/settingsone consistent enrichment schema, owner names, verified outreach fields, opinionated CRM export mapping
Google Places-style APIsapplication features that need place dataofficial place identifiers, names, addresses, ratings, location dataoutreach-specific enrichment, website crawl, owner names, emails, phone intelligence, personalization context
DIY scrapermaximum control when you have engineering timewhatever you buildmaintenance, blocking, dedupe, retries, enrichment, verification, schema design, CSV mapping
LocalProspectsAI-assisted local prospecting and outreach prepsearch plus owner names, verified emails, phone type, tech stack, website pages, services, summaries, socials, CRM export fieldsnot meant for generic map-app features; it is built around prospecting and enrichment

Outscraper, D7, Apify, and DIY scripts can all get you some version of "local businesses in a city." That is not the hard part anymore.

The hard part is producing data Claude can use to make a good decision:

  • Which businesses are worth contacting?
  • What should the pitch be?
  • Is there a person to address?
  • Is the email usable?
  • Is the phone likely mobile, landline, VoIP, or unknown?
  • What website weakness or business context can the outreach reference?
  • Which records should be excluded before they hit the CRM?

That is why LocalProspects is different. It is not just a list provider. It returns the enrichment layer Claude needs for filtering, scoring, personalization, and exports.

Where LocalProspects fits

LayerWhat Claude getsHow it is collected
Listing databusiness name, category, website, address, phone, rating, review count, rank, claimed status, locationpulled from the local business search result
Website identityofficial name, business type, address, phone, email, schema.org dataextracted from the business website and structured metadata
Website pagespage URLs, titles, meta descriptions, visible text, contact detailscrawled from the homepage and useful internal pages like contact, about, team, and service pages
Owner signalowner, founder, principal, or manager name when availablechecked from business records and extracted from website copy when explicitly stated
Emailsall discovered emails plus a promoted best emailcollected from website pages and metadata, deduped, then verified
Email qualityverified, catch-all, invalid, or unverified status; role-based and free-provider flagschecked through domain mail records and mailbox verification where possible
Phoneslisting phone plus discovered website phonesnormalized, deduped, and enriched with line type and carrier when available
Web presencesocial profiles, logo, blog presence, meta description, theme colorextracted during the website crawl
Tech stackCMS, CDN, server, chat tools, analytics, ad pixels, frameworks, other detected toolsdetected from website markup and technical fingerprints
Servicesservices, specialties, service areas, selling points, customer type, year established, employee hintsextracted from website text and structured into outreach-friendly fields

This is the data Claude wants. Not because it is more data for its own sake, but because each field maps to an action.

If you sell websites, Claude can look for outdated CMS choices, missing analytics, thin pages, weak metadata, or no blog.

If you sell SEO, Claude can look at categories, service areas, review counts, website copy, and local positioning.

If you sell paid ads, Claude can look for businesses with enough reviews and service pages but no obvious ad or analytics stack.

If you sell recruiting, software, bookkeeping, insurance, or any other local B2B service, Claude can use the business summary, services, employee hints, owner signal, and contact quality to build a tighter target list.

How this turns into money

The simplest agency workflow looks like this:

  1. Pick a niche with a clear pain point, like roofers, dentists, med spas, HVAC companies, or personal injury attorneys.
  2. Pick a city or region.
  3. Ask Claude to run the LocalProspects skill.
  4. Filter for businesses with a reason to buy: weak tech stack, no analytics, low review count, unclaimed profile, missing blog, thin service pages, or poor contact quality.
  5. Generate one or two personalized lines per lead.
  6. Export the list to your outreach system.
  7. Track replies, booked calls, and closed deals.

You can also package the output as a product:

  • a niche lead list with verified contacts
  • a local market map for an agency client
  • a website audit spreadsheet
  • a competitor intelligence report
  • a weekly "new prospects in this city" feed
  • a CRM enrichment job for an existing list

The key is that Claude is not just scraping. Claude is operating the workflow: gathering data, interpreting it, and producing the next artifact you can use to sell.

Example Claude prompts

Once the skill is installed, you can ask for outcomes instead of individual API steps.

Find med spas in Scottsdale. Keep businesses with websites, owner names, or verified emails. Add a personalization field based on their services or website copy. Export the top 100.

Find roofers in Tampa with 20+ reviews and no obvious analytics stack. Create a CSV for a website audit campaign.

Search dentists in Austin. Filter out chains, keep owner-led practices, and write a first line that references their services, reviews, or website.

Enrich these 10 business domains and tell me which ones are best for a cold email campaign.

This is the real value of the skill: Claude can move from "get data" to "prepare a campaign."

Paste this skill into Claude Code

Save the following as CLAUDE.md in a project, paste it into Claude Code's instructions, or adapt it for any coding assistant that reads markdown skill files.

# LocalProspects Lead Generation Skill

You can use LocalProspects to search for local businesses, enrich them with contact and website intelligence, and export the results to CSV.

## When to use this skill

Use this skill when the user asks for local lead generation, local business research, prospect lists, agency prospecting, CRM enrichment, owner-name research, verified business emails, local outreach lists, or website-intelligence reports.

Examples:

- "Find roofers in Tampa and export them to CSV."
- "Get dentists in Austin with owner names and verified emails."
- "Build a prospect list of med spas in Scottsdale."
- "Find local businesses running WordPress with no obvious analytics."
- "Enrich these business domains with contact data."

## Authentication

All API requests require an `x-api-key` header.

Ask the user for their LocalProspects API key before making requests. The key starts with `lp_`.

Base URL:

```text
https://localprospects.ai
```

Header:

```text
x-api-key: lp_your_key_here
```

## Main workflow: search and enrich local businesses

### Step 1: Find the location code

Search requires a `location_code`. Look it up by city or region first.

```bash
curl -s "https://localprospects.ai/api/v1/locations?q=Austin" \
  -H "x-api-key: <API_KEY>"
```

Response shape:

```json
{
  "locations": [
    {
      "location_code": 1026201,
      "name": "Austin",
      "region": "Texas",
      "country": "US",
      "type": "City",
      "full_name": "Austin, Texas, US"
    }
  ]
}
```

Pick the best matching city or region. Prefer US city matches when the user gives a US city.

### Step 2: Start the search

Start a search with a business category keyword and the selected `location_code`.

```bash
curl -s -X POST "https://localprospects.ai/api/v1/search" \
  -H "Content-Type: application/json" \
  -H "x-api-key: <API_KEY>" \
  -d '{
    "keyword": "plumber",
    "location_code": 1026201
  }'
```

The response returns a `job_id` and initial business counts. Enrichment continues asynchronously.

Important behavior:

- Searches require enough lead credits to run.
- Credits are based on businesses found and enriched.
- The initial response may include basic listing data.
- Do not treat the initial response as the final enriched result.

### Step 3: Poll the job

Poll every 5 seconds until `status` is `completed`.

```bash
curl -s "https://localprospects.ai/api/v1/job/<JOB_ID>" \
  -H "x-api-key: <API_KEY>"
```

While the job is running, expect progress fields like:

```json
{
  "job_id": "job-id",
  "status": "enriching",
  "total_businesses": 62,
  "enriched_count": 30,
  "failed_count": 2,
  "progress": 51
}
```

### Step 4: Fetch completed results

When the job is complete, fetch the enriched businesses.

```bash
curl -s "https://localprospects.ai/api/v1/job/<JOB_ID>/results" \
  -H "x-api-key: <API_KEY>"
```

Response shape:

```json
{
  "businesses": [
    {
      "name": "Example Plumbing",
      "category": "Plumber",
      "website": "https://example.com",
      "owner": "Jane Smith",
      "summary": "Short business intelligence summary.",
      "email": "jane@example.com",
      "phone": "(512) 555-0101",
      "phone_type": "mobile",
      "contact": {
        "address": "100 Main St, Austin, TX",
        "city": "Austin",
        "state": "Texas",
        "state_code": "TX",
        "lat": 30.2672,
        "lng": -97.7431,
        "all_emails": [
          {
            "email": "jane@example.com",
            "status": "verified",
            "is_role_based": false,
            "is_free_provider": false
          }
        ],
        "all_phones": [
          {
            "number": "(512) 555-0101",
            "line_type": "mobile",
            "carrier": "T-Mobile"
          }
        ]
      },
      "reputation": {
        "rating": 4.8,
        "reviews": 124,
        "review_snippet": "Great service...",
        "is_claimed": true
      },
      "services": {
        "list": ["Drain Cleaning", "Water Heater Repair"],
        "specialties": ["Emergency Plumbing"],
        "areas": ["Austin", "Round Rock"],
        "selling_points": ["24/7 Service", "Licensed & Insured"],
        "customer_types": "both",
        "year_established": 2015,
        "employees": "10+"
      },
      "web": {
        "tech": {
          "cms": "wordpress",
          "cdn": "cloudflare",
          "server": null,
          "chat": null,
          "analytics": ["google_analytics"],
          "frameworks": [],
          "advertising": ["facebook_pixel"],
          "other": []
        },
        "socials": {
          "facebook": "https://facebook.com/example"
        },
        "has_blog": false,
        "meta_description": "Austin plumbing company...",
        "pages_crawled": 4,
        "pages": [
          {
            "url": "https://example.com/about",
            "title": "About Example Plumbing",
            "meta_description": null,
            "text": "Visible page text..."
          }
        ]
      }
    }
  ]
}
```

## What each enrichment layer means

Use these fields when analyzing, filtering, or exporting results.

### Listing data

Fields: `name`, `category`, `additional_categories`, `website`, `phone`, `rank`, `reputation.rating`, `reputation.reviews`, `reputation.review_snippet`, `reputation.is_claimed`, `contact.address`, `contact.city`, `contact.state`, `contact.lat`, `contact.lng`.

Use for market sizing, territory filtering, review-based scoring, and basic CRM fields.

### Identity data

Fields: `owner`, `summary`, `services.year_established`, `services.employees`, `services.customer_types`.

Use for owner-led outreach, account research, and lead scoring.

Owner names come from business-record lookups when available and from explicit website statements when the website names an owner, founder, principal, or manager. Do not guess an owner from an email address, domain name, or business name.

### Email data

Primary field: `email`.

All emails: `contact.all_emails[]`.

Email statuses:

- `verified`: mailbox or domain checks indicate the email is likely usable
- `catch-all`: domain accepts broad mail, so the address may work but is less certain
- `invalid`: email should not be used
- `unverified`: not enough signal to confirm

Prefer non-role-based verified emails for outreach. Avoid invalid emails.

### Phone data

Primary fields: `phone`, `phone_type`.

All phones: `contact.all_phones[]`.

Common line types:

- `mobile`
- `landline`
- `voip`
- `toll_free`
- `unknown`

Use `mobile` for SMS workflows only when the user explicitly wants SMS-ready records. Otherwise, preserve all phone numbers in the export.

### Website and tech data

Fields: `web.tech`, `web.socials`, `web.has_blog`, `web.meta_description`, `web.pages_crawled`, `web.pages`.

Use these fields for:

- website audit targeting
- WordPress, Wix, or Squarespace segmentation
- analytics and ad-pixel detection
- personalization from page text
- identifying businesses with weak or thin web presence

### Service data

Fields: `services.list`, `services.specialties`, `services.areas`, `services.selling_points`.

Use for outreach personalization and niche segmentation.

Examples:

- target emergency plumbers
- find cosmetic dentists
- isolate roofers that mention storm damage
- write first lines based on service areas

## Optional workflow: enrich known domains

If the user already has business domains, use `/api/v1/enrich` instead of search.

Maximum: 10 leads per request.

```bash
curl -s -X POST "https://localprospects.ai/api/v1/enrich" \
  -H "Content-Type: application/json" \
  -H "x-api-key: <API_KEY>" \
  -d '{
    "leads": [
      {
        "domain": "https://example.com",
        "business_name": "Example Plumbing",
        "city": "Austin",
        "state": "TX",
        "country_iso_code": "US"
      }
    ]
  }'
```

Use this when the user provides an existing list and wants owner names, verified emails, phones, services, tech stack, socials, and website intelligence.

## CSV export

When the user asks for a CSV, flatten each business into one row.

Use this exact header order:

```csv
Google Maps Rank,Name,Category,Website,Owner,Email,Phone,Phone Type,Address,City,State,Rating,Reviews,Review Snippet,Claimed,Socials,Logo URL,Main Image URL,Email 1,Email 1 Status,Email 2,Email 2 Status,Email 3,Email 3 Status,Email 4,Email 4 Status,Email 5,Email 5 Status,Phone 1,Phone 1 Type,Phone 1 Carrier,Phone 2,Phone 2 Type,Phone 2 Carrier,Phone 3,Phone 3 Type,Phone 3 Carrier,Phone 4,Phone 4 Type,Phone 4 Carrier,Phone 5,Phone 5 Type,Phone 5 Carrier,Page 1 URL,Page 1 Title,Page 1 Meta,Page 1 Text,Page 2 URL,Page 2 Title,Page 2 Meta,Page 2 Text,Page 3 URL,Page 3 Title,Page 3 Meta,Page 3 Text,Page 4 URL,Page 4 Title,Page 4 Meta,Page 4 Text,Page 5 URL,Page 5 Title,Page 5 Meta,Page 5 Text
```

Mapping rules:

- `Google Maps Rank`: `rank`
- `Name`: `name`
- `Category`: `category`
- `Website`: `website`
- `Owner`: `owner`
- `Email`: `email`
- `Phone`: `phone`
- `Phone Type`: `phone_type`
- `Address`: `contact.address`
- `City`: `contact.city`
- `State`: `contact.state_code` or `contact.state`
- `Rating`: `reputation.rating`
- `Reviews`: `reputation.reviews`
- `Review Snippet`: `reputation.review_snippet`
- `Claimed`: `reputation.is_claimed`
- `Socials`: JSON-stringified `web.socials`
- `Logo URL`: `logo`
- `Main Image URL`: `main_image`
- `Email 1-5`: first five entries from `contact.all_emails`
- `Email 1-5 Status`: each email's `status`
- `Phone 1-5`: first five entries from `contact.all_phones`
- `Phone 1-5 Type`: each phone's `line_type`
- `Phone 1-5 Carrier`: each phone's `carrier`
- `Page 1-5 URL`: first five entries from `web.pages[].url`
- `Page 1-5 Title`: first five entries from `web.pages[].title`
- `Page 1-5 Meta`: first five entries from `web.pages[].meta_description`
- `Page 1-5 Text`: first five entries from `web.pages[].text`

Save the CSV locally using a descriptive file name like:

```text
<keyword>-<city>-localprospects.csv
```

What Claude can do after the skill is installed

Once Claude has those instructions, the user can make higher-level requests instead of walking through each API call manually.

For example:

Find HVAC companies in Dallas, keep only businesses with at least 30 reviews, and export the ones with owner names or verified emails.

Claude can resolve Dallas, run the search, wait for enrichment, filter by reputation.reviews, check owner and email, and write the final CSV.

Or:

Find dentists in Phoenix whose websites run WordPress and write a first-line personalization field for each.

Claude can use web.tech.cms, web.pages, services.list, and summary to build a more useful export than a basic name-phone-address list.

Why this works better than prompt-only lead gen

Prompt-only lead gen breaks because the assistant has no stable source of truth. It can write search queries, scrape random pages, and make a spreadsheet, but every run is a little different.

A skill file gives Claude a contract:

  • the API endpoint is fixed
  • the authentication method is clear
  • the polling loop is documented
  • the output schema is known
  • the CSV columns are already decided

That lets Claude focus on the parts AI is good at: filtering, classifying, summarizing, writing outreach angles, and turning structured data into useful workflow artifacts.

The takeaway

The practical version of "Claude lead gen" is not asking an assistant to browse around and improvise a list. It is giving Claude a specific skill: search local businesses, enrich them, understand the fields, and export the result.

LocalProspects provides the data access. The skill file tells Claude how to use it. Together, they turn a coding assistant into a local business research agent you can run from a project folder.

Get an API key, paste the skill into CLAUDE.md, and Claude can start building enriched local prospect lists from plain English requests.

Your leads are waiting

Search any niche and city. Get 500 leads free, no credit card required.

Plumber
Search 500 leads for freeNo credit card required