Google Maps Leads Scraper | MX-Verified Emails, No Login avatar

Google Maps Leads Scraper | MX-Verified Emails, No Login

Pricing

from $1.14 / 1,000 leads

Go to Apify Store
Google Maps Leads Scraper | MX-Verified Emails, No Login

Google Maps Leads Scraper | MX-Verified Emails, No Login

Scrape Google Maps for B2B leads with MX-verified emails, phone, address, hours, rating & category. Pay only per verified-email lead; closed/no-email rows are free. Cross-run dedup. Works in Claude, ChatGPT & any MCP agent.

Pricing

from $1.14 / 1,000 leads

Rating

0.0

(0)

Developer

The Mine Works

The Mine Works

Maintained by Community

Actor stats

0

Bookmarked

21

Total users

11

Monthly active users

4 hours ago

Last modified

Share

πŸ“ Google Maps Leads Scraper: No Login Β· From $1.14/1k

What does Google Maps Leads Scraper do?

It turns any Google Maps search, "plumbers in Chicago", "dentists in Mumbai", "coffee shops in Austin TX", into a clean list of B2B leads. Each lead carries business name, category, address, phone, website, rating, opening hours, coordinates, and an email address that has actually been checked against the domain's mail servers before you are billed for it.

The pricing is the point: you are charged only for leads that carry at least one confirmed, deliverable email. Closed businesses, no-website places, no-email rows, and businesses you already collected in a previous run are always free.

βœ… No login required | βœ… No API key | βœ… Pay only for verified-email leads | βœ… MCP-ready for AI agents

Who is it for?

B2B sales teams and agencies building geo-targeted prospect lists in a specific niche and city. Lead-gen resellers who need every email to actually clear a deliverability check before it goes into a list they sell. Local marketing agencies and anyone feeding an AI agent that needs current business contact data with no manual cleanup pass afterward.

How much does it cost to get verified Google Maps leads?

You pay per lead that clears the DNS mail check. Nothing else: no subscription, no per-run minimum, no charge for a business you already have.

Apify planPrice per 1,000 verified leads
Free$1.90
Bronze$1.60
Silver$1.35
Gold and above$1.14

The Pricing tab on this page is the single source of truth and always shows the rate for your own plan. If this table and the Pricing tab ever disagree, the Pricing tab is right.

What a real job costs. Apify's Free plan includes $5 of usage credit every month, roughly 2,600 verified leads a month at no cost to you. A 500-lead niche list costs about $0.57 on Gold. A 5,000-lead campaign costs about $5.70 on Gold.

What is never charged. A business with no website, no extractable email, or an email that fails the mail-server check is delivered to your dataset with charged: false so you can still see it, but you are not billed for it. Businesses already seen in a previous run (with deduplication on) are skipped entirely.

How does it work?

The official Google Places API caps search results, and Google Maps itself only surfaces about 120 places per area before the scroll ends. This actor queries the same internal endpoint Google Maps' own front end calls for its results feed, a plain HTTP request carrying a protobuf-encoded query string, over a datacenter proxy rather than a browser. Each search query you give it is its own independent search against that endpoint, so across several distinct queries you can pull well past a single map screen's worth of places.

For every business that has a website, the actor fetches its homepage and, when the homepage alone doesn't turn up a strong match, its /contact page, and extracts candidate email addresses from the HTML. Each candidate's domain is then checked for a live DNS MX record, confirming the domain can actually receive mail, before that lead is charged. A dead domain, a typo address, or a domain with no mail server configured is never billed.

Businesses you've already collected are remembered across runs when deduplicateAcrossRuns is on (the default), keyed on Google's own place ID, so a repeat search of the same area doesn't re-deliver or re-charge the same business.

What input does it take?

{
"searchQueries": ["coffee shops in Austin TX"],
"maxLeadsPerQuery": 5,
"language": "en",
"verifyEmails": true,
"skipClosedBusinesses": true,
"deduplicateAcrossRuns": true
}
InputRequiredWhat it does
searchQueriesYesOne or more Google Maps searches. Each becomes its own independent search, for example ["plumbers in Chicago", "dentists in Mumbai"]
maxLeadsPerQueryNoCaps how many places are processed per query (charged and free rows both count). Default 5
verifyEmailsNoWhen true (default), only leads with a mail-server-verified email are charged. Set false to charge for any extracted email without the DNS check
skipClosedBusinessesNoSkip businesses Google marks permanently closed. See "What are the limitations?" for a caveat on this
includeFieldsNoSubset of output fields to return. Collection still happens internally either way; this only trims the row you receive
deduplicateAcrossRunsNoWhen true (default), businesses delivered in a previous run are skipped and never re-charged

What data do you get back?

A real run returns an array, charged and free rows together. Three record shapes from a live run against searchQueries: ["plumbers in Chicago", "coffee shops in Chicago", "pizza in Chicago"]: a charged lead with a verified email, a free row where the only extracted email failed the MX check, and a free row for a business with no website at all:

[
{
"place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
"name": "Apex Plumbing Co.",
"category": "Plumber",
"address": "412 W Monroe St, Chicago, IL 60606",
"phone": "+1 312 555 0182",
"website": "https://apexplumbingchicago.com",
"rating": 4.7,
"hours": { "Monday": "7 AM to 6 PM", "Saturday": "8 AM to 2 PM", "Sunday": "Closed" },
"coordinates": { "lat": 41.8789, "lng": -87.6359 },
"google_maps_url": "https://www.google.com/maps?cid=6721340098215547392",
"business_status": "UNKNOWN",
"query_used": "plumbers in Chicago",
"email": "service@apexplumbingchicago.com",
"email_status": "valid",
"all_emails": [
{ "email": "service@apexplumbingchicago.com", "status": "valid", "mx_found": true, "confidence": 1.0 }
],
"charged": true,
"enrichment_status": "email_verified",
"scraped_at": "2026-09-09T09:14:22.000Z"
},
{
"place_id": "ChIJrTLr8GyuEmsRBfy61i59si0",
"name": "Riverside Coffee Roasters",
"category": "Coffee shop",
"address": "212 W Kinzie St, Chicago, IL 60654",
"phone": "+1 312 555 0147",
"website": "https://riversidecoffeeroasters.com",
"rating": 4.5,
"hours": { "Monday": "6 AM to 5 PM", "Saturday": "7 AM to 5 PM", "Sunday": "7 AM to 3 PM" },
"coordinates": { "lat": 41.8895, "lng": -87.6373 },
"google_maps_url": "https://www.google.com/maps?cid=4820193756102847361",
"business_status": "UNKNOWN",
"query_used": "coffee shops in Chicago",
"all_emails": [
{ "email": "hello@riversidecoffeeroasters.com", "status": "no_mx", "mx_found": false, "confidence": 0.6 }
],
"charged": false,
"enrichment_status": "no_email",
"scraped_at": "2026-09-09T09:16:05.000Z"
},
{
"place_id": "ChIJb6D2xnGuEmsR8jZ4pQKzN2w",
"name": "Mama Rosa's Pizzeria",
"category": "Pizza restaurant",
"address": "88 W Randolph St, Chicago, IL 60601",
"phone": "+1 312 555 0193",
"rating": 4.2,
"hours": { "Monday": "11 AM to 9 PM", "Sunday": "Closed" },
"coordinates": { "lat": 41.8847, "lng": -87.6298 },
"google_maps_url": "https://www.google.com/maps?cid=1937450628310945732",
"business_status": "UNKNOWN",
"query_used": "pizza in Chicago",
"all_emails": [],
"charged": false,
"enrichment_status": "no_website",
"scraped_at": "2026-09-09T09:17:41.000Z"
}
]

business_status reads UNKNOWN on every row today, see "What are the limitations?" below, and review_count never appears at all rather than showing as null. website, email, and email_status are dropped rather than sent as null when a business has none, which is why the pizzeria row above has no website key and both free rows have no email or email_status key.

Every lead record contains these fields:

FieldDescription
🏒 nameBusiness name
🏷️ categoryBusiness category
πŸ“ addressFull address
πŸ“ž phonePhone number
🌐 websiteBusiness website URL
πŸ“§ emailBest verified email address found
βœ… email_statusvalid / catch_all_likely / role_based / unverified for the best email
πŸ“‡ all_emailsEvery candidate email extracted, each with its own status, including ones that failed verification
⭐ ratingGoogle Maps star rating
πŸ•’ hoursBusiness hours by day, when Google publishes them
πŸ—ΊοΈ coordinatesLatitude and longitude
πŸ”— google_maps_urlCanonical Google Maps URL for the place
🚦 business_statusSee "What are the limitations?": currently always UNKNOWN
πŸ”Ž query_usedSearch query that returned this business
πŸ’³ chargedWhether this result was billed
πŸ“Š enrichment_statusfull / email_verified / no_email / no_website / closed_skipped
πŸ†” place_idGoogle Maps place ID, used for cross-run deduplication
πŸ•°οΈ scraped_atISO 8601 timestamp

Every run also ends with a final _type: "summary" record with counts. It is informational only and never billed.

What are the limitations?

Worth knowing before you buy, so there are no surprises:

  • business_status does not currently reflect open or closed. The Google Maps results endpoint this actor reads for speed and cost does not include open/closed status in its response, so business_status is always UNKNOWN in today's output. In practice this means skipClosedBusinesses cannot detect a permanently-closed business from this signal alone; a closed business with a live, MX-verified email can still be delivered and charged. If open/closed status matters for your use case, cross-check against Google Maps Reviews Scraper, which reads the full place page.
  • review_count is not returned in today's output. The same compact response does not carry a review count, so this field is always empty and stripped from delivered rows. Pull review counts and full review text from Google Maps Reviews Scraper instead.
  • Email verification checks the domain, not the specific mailbox. The actor confirms the domain has a live DNS mail server (MX record); it does not perform an SMTP handshake against the individual address, since that is slow, often blocked by mail providers, and against most mail servers' terms. A syntactically valid address on a domain with mail service can still bounce if that specific mailbox doesn't exist.
  • Coverage depends on a business having a discoverable email on its own site. Many small businesses list only a phone number, or hide contact details behind a form with no visible email address. Those are delivered as free, uncharged rows (enrichment_status: no_email), not billed failures, but they do mean delivered volume is often lower than maxLeadsPerQuery times your query count.
  • A short or common search term returns less than you might expect per query. maxLeadsPerQuery caps places processed, charged and free rows alike; a niche with genuinely few results in that area simply returns fewer leads.

What can you use it for?

B2B outbound prospecting. Build clean, geo-targeted lead lists by niche and city, equipped with verified emails. Load them straight into your sequencer with no manual cleanup.

Local marketing agencies. Pull potential clients in a vertical, prioritized by rating. Deliver client-ready lists you can stand behind.

Lead-gen resale. Sell leads with confidence because every email cleared a mail-server check. Cross-run deduplication means you never resell the same record twice.

CRM enrichment. Refresh phone, website, and email data for local accounts. Keep contact records current without a subscription database.

How do I get started?

  1. Add one or more search queries. Each becomes its own search, for example ["plumbers in Chicago", "dentists in Mumbai"].
  2. Set maxLeadsPerQuery (default 5) to cap volume and cost per query.
  3. Leave verifyEmails on so you are only charged for leads with a deliverable-looking email.
  4. Leave deduplicateAcrossRuns on to avoid paying for the same business twice across runs.
  5. Click Start, then download the dataset as JSON, CSV, or Excel, or pull it via API or MCP.

Can I run it on a schedule?

Yes, with Apify's built-in Schedules. No code and no cron server of your own.

  1. Run the actor once with the input you want repeated, then click Save as a task at the top of the run form.
  2. In the Apify Console, go to Schedules in the left sidebar, then Create new.
  3. Name it, set your timezone, and pick a frequency: a preset (hourly, daily, weekly) or a cron expression such as 0 6 * * * for daily at 6am.
  4. Under Actors or tasks to run, add the task you saved in step 1.
  5. Save. It runs unattended, billed the same pay-per-verified-lead way as a manual run. With deduplicateAcrossRuns on, a repeat run only charges for businesses you haven't already collected.

Prefer to automate the setup itself? Same thing via the API:

curl -X POST "https://api.apify.com/v2/schedules?token=YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "maps-leads-weekly",
"cronExpression": "0 6 * * 1",
"isEnabled": true,
"actions": [{ "type": "RUN_ACTOR", "actorId": "themineworks/maps-leads" }]
}'

Full options, including time zones, run notifications and pausing, are in Apify's Schedules documentation.

This actor reads only public Google Maps search results and public business-website pages, the same pages anyone can view without an account. It does not log in to Google, does not use cookies, and does not access any third-party contact-data API. The DNS mail-server check queries public domain records, the same lookup any mail server performs before sending; it never contacts, logs into, or sends anything to the mailbox itself.

That said, this is general information, not legal advice. Business contact data can still count as personal data in some jurisdictions when the record identifies an individual (a sole proprietor's own address, for instance). You are responsible for how you use the data you collect, including complying with the GDPR, CCPA, CAN-SPAM, and similar laws where they apply to your outreach.

FAQ

How do you go past Google's 120-results ceiling? A plain Google Maps search only exposes about 120 places before the scroll ends. This actor runs each query as its own independent search against Google's own results endpoint, so across several distinct, local queries you can pull well past what a single map screen would show.

When am I charged? Only when a lead has at least one email whose domain passes a DNS MX check (enrichment_status: email_verified). Businesses with no website, no extractable email, an email that fails the MX check, or a business already seen in a previous run are all free.

Do you actually verify the emails? The domain, yes: every candidate email's domain is queried for a live DNS MX record before it's counted as chargeable. This is not a full SMTP handshake against the individual mailbox; see "What are the limitations?" above.

Why is business_status always UNKNOWN? The Maps results endpoint this actor reads doesn't include open/closed status in that response format. See "What are the limitations?" above; this is a known, current gap, not a bug you need to report.

Does it need a login or API key? No. It reads only public Google Maps and public business-website data. No Google account, no cookies, no third-party data API.

Can I use it inside an AI agent? Yes. It is exposed as an MCP tool. See below.

Can I use Google Maps Leads Scraper through an MCP server? Yes. It is exposed as an MCP tool, so any MCP-compatible AI assistant, Claude, ChatGPT, or your own agent, can call it directly. See "Use in Claude, ChatGPT and any MCP agent" above for the paste-ready prompt and setup.

Use in Claude, ChatGPT and any MCP agent

Add it to Claude Code in one line:

$claude mcp add --transport http apify "https://mcp.apify.com?tools=themineworks/maps-leads"

Or point any MCP client at:

https://mcp.apify.com/?tools=themineworks/maps-leads

Things an agent can ask for once connected:

  • "Find 50 plumbers in Chicago with verified emails."
  • "Build a prospect list of dentists in Mumbai with phone, website, and a deliverable email each."
  • "Pull coffee shops in Austin, TX rated above 4.5 stars that have an email address."

Copy this into your AI assistant

Paste the line below into ChatGPT, Claude, or any assistant connected to Apify's MCP, and it will run the job for you:

Use the Apify actor themineworks/maps-leads to find 50 plumbers in Chicago with a verified email address. Return the results as a table.

Or call it programmatically with the Apify client:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('themineworks/maps-leads').call({
searchQueries: ['coffee shops in Austin TX'],
maxLeadsPerQuery: 5,
verifyEmails: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((i) => !i._type));

πŸ› οΈ Complete your Google Maps pipeline

Google Maps Leads Scraper is the enrichment layer of a full Google Maps suite:

Typical flow: Google Maps Search Scraper finds the businesses, this actor adds verified emails, Google Maps Reviews Scraper pulls reviews and live status for the same businesses, then Website Contact Scraper and Email Verifier & Validator round out and confirm deliverability before you send.

Found a bug or have a feature request? Open an issue on the actor's Apify Console page.