Google Maps Email Leads Scraper — MX-Checked Business Emails
Pricing
from $1.80 / 1,000 leads
Google Maps Email Leads Scraper — MX-Checked Business Emails
Google Maps email scraper: one row per business with MX-checked email, owner name, phone, website and socials. No login. Pay per lead.
Pricing
from $1.80 / 1,000 leads
Rating
0.0
(0)
Developer
Mohammed Samaan
Maintained by CommunityActor stats
0
Bookmarked
82
Total users
12
Monthly active users
6 days ago
Last modified
Categories
Share
Find local businesses on Google Maps and get back a checked business email — not just a scraped address, one whose domain is confirmed to accept mail (MX check) and tagged with its MX status (valid, risky-role or invalid) — plus phone, website, rating, address, coordinates, opening hours and social links, as one clean CSV/JSON row per business.
Already have Google Maps data? Pick that dataset in
placesDatasetId(from any Google Maps scraper) and this Actor skips the Maps step entirely — you pay only for our enrichment (email, contact name, socials, website signals) on the places that have a website, not for the Maps scrape again.
Two ways to feed it:
- Search — give it search terms + a location and it pulls the places from Google Maps through a maintained Maps actor, then enriches them.
- Enrich a dataset you already have — pick any Google Maps scraper run
from your account (
placesDatasetId) and it skips the Maps step entirely, visiting each business website and adding checked emails and socials. No second Maps bill.
The enrichment step uses no browser and no proxies: plain HTTP requests to each business's own home / contact / about pages, then a DNS MX lookup per domain.
Who it's for
- Cold-email agencies and SMMAs building local-business lead lists
- SDR teams tired of cleaning scraped lists before they can send
- Anyone pitching local businesses (web design, marketing, SaaS) who needs a contact email, not just a name and a phone number
- Teams that already scrape Google Maps and just want the email layer added
What you get
| Field | What it is |
|---|---|
name / category | Business name and Google Maps category |
email | Best available email for the business |
emailStatus | valid (domain has mail servers, named inbox) / risky-role (generic inbox like info@) / invalid (no MX) |
emailSource | Which page the email was found on |
phone / website | Contact details |
rating / reviews | Google rating and review count |
address / city / country / lat / lng | Location |
placeId / mapsUrl | Google Maps identifiers (when the Maps data has them) |
openingHours | Flattened hours string |
facebook / instagram / linkedin / twitter / youtube / tiktok | Social profile links found on the site |
allEmails / emailCount | Every email found, each tagged with its status |
searchTerm / scrapedAt | Provenance |
Example output
One real row from a search run (digital marketing agency, Australia). openingHours is shortened here.
{"name": "Potent","category": "Marketing agency","email": "enquiries@potent.com.au","emailStatus": "risky-role","emailSource": "https://www.potent.com.au","emailPickConfidence": 0.93,"contactName": null,"contactRole": null,"phone": "+61 1300 853 557","website": "https://www.potent.com.au/","rating": 4.9,"reviews": 50,"address": "Suite 409/102 Werribee St N, Werribee VIC 3030, Australia","city": "Werribee","country": "AU","state": "Victoria","postalCode": "3030","categories": "Marketing agency; Advertising agency; Graphic designer; Internet marketing service; Web hosting company; Website designer","priceLevel": null,"permanentlyClosed": false,"lat": -37.9012655,"lng": 144.6534986,"placeId": "ChIJP4IEKqaF1moRE4umP2CfeJ0","mapsUrl": "https://www.google.com/maps/search/?api=1&query=Potent&query_place_id=ChIJP4IEKqaF1moRE4umP2CfeJ0","openingHours": "Monday: 8:30 AM to 4 PM | Tuesday: 8:30 AM to 4 PM | … (shortened)","facebook": "https://www.facebook.com/potentweb","instagram": "https://www.instagram.com/potentweb","linkedin": "https://au.linkedin.com/company/potent-web","twitter": null,"youtube": null,"tiktok": null,"allEmails": "enquiries@potent.com.au (risky-role); updates@potent.com.au (valid)","emailCount": 2,"siteHttps": true,"siteMobileFriendly": true,"siteCopyrightYear": 2026,"siteLooksOutdated": false,"siteHasAnalytics": true,"siteHasFacebookPixel": false,"siteCms": null,"searchTerm": "digital marketing agency","scrapedAt": "2026-10-04T16:21:41.933Z"}
emailStatus is an MX check only: valid means the domain can receive mail, not that the mailbox exists.
Input
{"searchTerms": ["dentist", "orthodontist"],"location": "Austin, TX","maxResults": 50,"verifyEmails": true,"onlyWithEmail": true,"maxEmailsPerSite": 5}
Or, to enrich an existing Google Maps dataset (skips the Maps search):
{"placesDatasetId": "<pick one of your datasets>","verifyEmails": true,"onlyWithEmail": true}
searchTerms— business types to search;location— a city or area.maxResults— places per search term.verifyEmails(on) — the MX check that tags each email valid / risky-role / invalid.onlyWithEmail(on) — only businesses with an email are delivered and billed.placesDatasetId— any dataset whose rows have awebsitefield (compass, lukaskrivka, or this actor's own output all work).
Pricing — read this before your first run
This actor is pay-per-result: one charge per row delivered, and with
onlyWithEmail on (the default) only rows with an email are delivered. The
per-row price is on the Pricing tab.
In search mode the Google Maps step is a separate actor with its own price.
This actor calls compass/crawler-google-places in your account, and Apify
bills that run to you directly at that actor's rate (about $4 per 1,000
places on the free plan, less on paid plans) plus its compute. A run that
finds 1,000 places and 350 emails therefore costs roughly the Maps actor's
price for 1,000 places + this actor's price for 350 rows.
If you already have Google Maps data, use placesDatasetId and pay only for
the enrichment rows.
How it compares
Most Google Maps scrapers hand you a raw list; every email here is MX-checked and tagged with an MX status (valid, risky-role or invalid) before it reaches your dataset, and social links are pulled from the business site at no extra step. What this actor does not do: mailbox-level (SMTP) verification or catch-all detection — an MX check confirms the domain accepts mail, not that the exact inbox exists. Run the output through the Bulk Email Verifier if you need that.
Use with n8n / Make / Zapier / MCP
Add an Apify integration node, point it at this actor, run it with your input, then read the finished dataset back into your workflow — feed the rows straight into your CRM or outreach tool. Every input has an example value, so an AI agent can call it via the Apify MCP server without guidance.
Errors and limits
How the actor behaves when things go wrong (read from its code):
- No usable input. In search mode, an empty
searchTermsorlocationfails the run with "Provide searchTerms + location, or pick a Google Maps dataset in placesDatasetId". AplacesDatasetIdthat is empty or unreadable fails the run with a message saying the dataset needs awebsitefield per row. - Google Maps step fails. In search mode the actor starts
compass/crawler-google-placesin your account (30-minute timeout). A failed start is retried once after 5 seconds. If your Apify account is already at its concurrent-run limit, the actor waits and retries for about 3 minutes before failing with a message telling you to wait or useplacesDatasetId. If the Maps run ends in any status other than SUCCEEDED (for example out of credits) or returns no dataset, this actor fails with that status and the run id. The Maps run is billed to your account by its own actor, whether or not this actor then delivers rows. - Slow, blocked or broken business sites. Each place's site is checked at
/,/contact,/contact-usand/aboutin parallel; each page has an 8-second timeout and a 1.5 MB size cap. Any HTTP error, timeout, block (403) or non-text response yields no content for that page, silently. One place gets at most 45 seconds in total; after that it is skipped (with a warning in the log) and the run continues. Social-media, Google, Yelp, delivery-app and link-in-bio websites are not crawled. There are no proxies and no retries, and JavaScript-only pages are read as static HTML. - Places with no website or no email. With
onlyWithEmailon (the default), places where no email was found are not delivered and not charged. Turn it off to also get rows without an email, which are charged like any other row. A repeated name-and-website pair is processed once. - Email status.
verifyEmailsis a DNS MX lookup (5-second timeout):invalid= no mail server found for the domain,risky-role= generic inbox such as info@,valid= the domain accepts mail and the address is not a generic role. Mailbox-level (SMTP) verification and catch-all detection are not done. An address whose domain MX lookup times out is markedinvalid. - One bad lead does not stop the run. If enriching or writing a single lead fails, a warning is logged and the run continues with the next one.
- Charging. One charge per row delivered to the dataset (the paid event is
apify-default-dataset-item), applied when the row is written. A run that fails before any row is written delivers and charges nothing from this actor. If your max-charge limit is reached the run stops early with what it has. WithplacesDatasetId, at most 5,000 places are enriched per run.
FAQ
Does it need my own Google Maps API key? No. In search mode it runs a maintained Google Maps actor in your account; that actor's usage is billed to you by Apify separately from this actor's per-row price (see Pricing above). In dataset mode there is no Maps step at all.
What does "risky-role" mean? The domain accepts mail but the address is a
generic inbox like info@ or sales@ rather than a named person — still worth
having, just a lower reply rate.
Why is email sometimes null? Not every business site has a discoverable
email on its home / contact / about pages, or the domain has no mail servers.
With onlyWithEmail off those businesses still come through with phone,
website, rating and socials.
Can I run it against a whole country? Run it per city — Google Maps results are location-bound, and splitting by city keeps runs fast and easy to re-run.
Does it respect site terms? It only visits each business's own public site pages. You are responsible for lawful use of the contact data you collect.
Send results to Notion (new, Sep 2026)
Authorize Notion once in Apify Console → Settings → API & Integrations → MCP connectors (choose Notion, sign in). Then pick that connector in Notion connector and paste the link of any Notion page in Notion page to create the table in. The first run creates a table inside that page and fills it with the Maps leads (up to 500 rows per run; the full set is always in the dataset). To keep adding to the same table on later runs, paste the table ID from the log into Existing Notion table ID. This Actor never sees your Notion login: Apify's connector proxy holds it. If the Notion step fails, your dataset results are still delivered and the reason is logged.
Use it from an AI agent (MCP)
Add this Actor to any MCP client (Claude, Cursor, VS Code) with one URL:
https://mcp.apify.com?tools=leadharbor/google-maps-verified-email-scraper
Or call it through the Apify API with an input like this:
{"searchTerms": ["dentist"],"location": "Austin, TX","maxResults": 20}
Returns one row per local business: name, category, MX-checked email, phone, website, address, owner name when found, social links. Results land in the run's default dataset (JSON, CSV or Excel). No login or API key is needed for the sites it reads, and pay-per-event pricing works with Apify's x402 agent payments.
API usage
Run it from your own code with an Apify API token. The input below is this actor's prefilled example.
curl (runs the actor and returns the dataset items):
curl -X POST "https://api.apify.com/v2/acts/leadharbor~google-maps-verified-email-scraper/run-sync-get-dataset-items" \-H "Authorization: Bearer $APIFY_TOKEN" \-H "Content-Type: application/json" \-d '{"searchTerms": ["dentist"],"location": "Austin, TX","maxResults": 20,"onlyWithEmail": true}'
Python (pip install apify-client):
from apify_client import ApifyClientclient = ApifyClient("<APIFY_TOKEN>")run = client.actor("leadharbor/google-maps-verified-email-scraper").call(run_input={"searchTerms": ["dentist"],"location": "Austin, TX","maxResults": 20,"onlyWithEmail": True})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
Changelog
28 Sep 2026 — More place fields (state, postal code, all categories, price level); works with a dataset alone; optional Notion output; MCP agent section. Plus 5 public example tasks with their own pages.
More from leadharbor
- Website Contact Extractor
- Bulk Email Verifier
- USA Business Email Finder
- UK Business Email Finder
- UAE Business Email Finder
- UAE Property Broker Contacts
- Local Review Booster
- App Store Reviews Scraper + Monitor
- Shopify Products Scraper + Price Drop & Restock Monitor
- Reddit Keyword Search Scraper + Mention Monitor
- YouTube Scraper
- Airbnb Scraper
- LinkedIn Jobs Scraper
Using this actor? A quick review helps other buyers find it: google-maps-verified-email-scraper
New output fields (Sep 2026)
| Field | What it is |
|---|---|
contactName, contactRole | The owner / founder / principal when the website clearly names one (e.g. "Dr Adil Sarwar, Founder"). An AI model only selects among names that appear on the site — it never invents one. Empty when the site doesn't name anyone. |
siteLooksOutdated, siteCopyrightYear | Copyright year in the footer; true when it is 3+ years old — a common sign of a neglected site. |
siteMobileFriendly | Whether the homepage declares a mobile viewport. |
siteHasAnalytics, siteHasFacebookPixel, siteCms | Google Analytics / Tag Manager present, Meta pixel present, and the site builder (WordPress, Wix, Squarespace, Shopify, Webflow). |
When a site lists several emails, the returned email is the business's own main inbox — form placeholders
(example@mysite.com, you@company.com), platform addresses and jobs inboxes are no longer picked.
Related actors
- Disposable Email & Domain Checker — Flags throwaway and free-provider email domains using 5 merged public lists. $0.30 per 1,000 checks.
- Domain Trust Check — 0-100 trust score for a domain from domain age, SSL, SPF/DKIM/DMARC and disposable-domain lists. $2.50 per 1,000 domains.
- Bulk Email Verifier — Verifies email addresses: syntax, MX, disposable and role flags, and a 0-100 score. $0.50 per 1,000.
- Website Contact Extractor — Pulls emails, phone numbers and social links from website URLs.
- Website Technology Detector — Detects the CMS, frameworks, analytics and 100+ other technologies a website uses from its homepage. $9 per 1,000 sites.