Google Maps Email Leads Scraper — MX-Checked Business Emails avatar

Google Maps Email Leads Scraper — MX-Checked Business Emails

Pricing

from $1.80 / 1,000 leads

Go to Apify Store
Google Maps Email Leads Scraper — MX-Checked Business Emails

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

Mohammed Samaan

Maintained by Community

Actor stats

0

Bookmarked

82

Total users

12

Monthly active users

6 days ago

Last modified

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:

  1. Search — give it search terms + a location and it pulls the places from Google Maps through a maintained Maps actor, then enriches them.
  2. 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

FieldWhat it is
name / categoryBusiness name and Google Maps category
emailBest available email for the business
emailStatusvalid (domain has mail servers, named inbox) / risky-role (generic inbox like info@) / invalid (no MX)
emailSourceWhich page the email was found on
phone / websiteContact details
rating / reviewsGoogle rating and review count
address / city / country / lat / lngLocation
placeId / mapsUrlGoogle Maps identifiers (when the Maps data has them)
openingHoursFlattened hours string
facebook / instagram / linkedin / twitter / youtube / tiktokSocial profile links found on the site
allEmails / emailCountEvery email found, each tagged with its status
searchTerm / scrapedAtProvenance

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 a website field (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 searchTerms or location fails the run with "Provide searchTerms + location, or pick a Google Maps dataset in placesDatasetId". A placesDatasetId that is empty or unreadable fails the run with a message saying the dataset needs a website field per row.
  • Google Maps step fails. In search mode the actor starts compass/crawler-google-places in 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 use placesDatasetId. 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-us and /about in 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 onlyWithEmail on (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. verifyEmails is 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 marked invalid.
  • 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. With placesDatasetId, 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 ApifyClient
client = 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


Using this actor? A quick review helps other buyers find it: google-maps-verified-email-scraper

New output fields (Sep 2026)

FieldWhat it is
contactName, contactRoleThe 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, siteCopyrightYearCopyright year in the footer; true when it is 3+ years old — a common sign of a neglected site.
siteMobileFriendlyWhether the homepage declares a mobile viewport.
siteHasAnalytics, siteHasFacebookPixel, siteCmsGoogle 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.

  • 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.