Google Maps Email Extractor avatar

Google Maps Email Extractor

Pricing

from $1.50 / 1,000 business leads

Go to Apify Store
Google Maps Email Extractor

Google Maps Email Extractor

Scrapes Google Maps places and optionally enriches each business with website contact emails and social links.

Pricing

from $1.50 / 1,000 business leads

Rating

0.0

(0)

Developer

Camilo Aguilar

Camilo Aguilar

Maintained by Community

Actor stats

0

Bookmarked

13

Total users

0

Monthly active users

14 days ago

Last modified

Security

Limited permissions

Share

Google Maps Email Extractor

Find local businesses on Google Maps and get their public website emails, source URLs, phone numbers and social profiles in one run. Each saved lead also carries an email confidence value, partial rows when a website cannot be read, a transparent lead score, and review "pain signals" sampled from recent Google reviews. Optionally, it can collect publicly listed staff names, titles and work emails from team pages.

It is built for B2B outreach to local businesses such as car dealerships, dental and medical clinics, law firms, home-service contractors, real estate offices and agencies, and for anyone who needs a Maps lead list plus contact data without chaining a Maps scraper to a separate email crawler.

Quick start

  1. Open the Actor, set Search terms and Location, and click Start.
  2. Download the dataset as JSON, CSV or Excel, or read it through the Apify API.

Example input: Hyundai dealerships near Burlington, Ontario, with staff extraction on.

{
"searchTerms": ["Hyundai dealership"],
"location": "Burlington, ON",
"maxItems": 20,
"contactExtraction": "emails",
"emailVerification": "mx",
"staffExtraction": true
}

Example output row (trimmed; all values here are invented):

{
"title": "Example Hyundai",
"category_name": "Hyundai dealer",
"address": "100 Sample Rd, Burlington, ON",
"phone": "(905) 555-0100",
"website": "https://www.examplehyundai.ca/",
"domain": "examplehyundai.ca",
"total_score": 4.4,
"reviews_count": 812,
"emails": ["info@examplehyundai.ca", "gm@examplehyundai.ca"],
"primary_email": "info@examplehyundai.ca",
"email_status": "mx_found",
"email_confidence": 0.98,
"email_type": "role",
"email_sources": [
{
"email": "info@examplehyundai.ca",
"url": "https://www.examplehyundai.ca/contact",
"type": "mailto",
"context": "Questions? Email us at info@examplehyundai.ca"
}
],
"staff_contacts": [
{
"name": "Sam Placeholder",
"title": "General Manager",
"department": "Management",
"email": "gm@examplehyundai.ca",
"phone": null,
"source_url": "https://www.examplehyundai.ca/our-team",
"is_decision_maker": true
}
],
"social_profiles": ["https://www.facebook.com/examplehyundai"],
"review_status": "sampled",
"pain_total": 1,
"lead_score": 52.1,
"chain_status": "independent",
"google_maps_url": "https://www.google.com/maps/place/Example+Hyundai/...",
"detail_status": "success",
"contact_status": "success",
"contact_error": null
}

Many sites will not return staff data, so staff_contacts is often an empty list. See What to expect.

What you get

  • Business discovery from search terms plus a location, or from Google Maps search and place URLs. Duplicates are removed within a run.
  • Google Maps fields: name, category, address, coordinates, phone, website, rating and review count (best effort).
  • Website enrichment: the Actor visits the business website (home, contact, contact-us and about pages) and extracts public emails and social profiles.
  • Email audit fields: primary_email, email_status, email_confidence, email_type and email_sources, where each source records the exact page URL and the surrounding text.
  • Partial rows: if a website is missing, blocked or unreachable, the Maps record is still saved and contact_status says why.
  • Review pain signals: phrase matching over a small sample of recent reviews (for example unanswered phones, no call back, long holds), with links to the matching reviews.
  • Lead score: a 0-100 score built from five visible sub-scores so you can sort and prioritize a list.
  • Staff contacts (optional, off by default): names, titles and work emails published on team pages.

Emails come from public pages on the business website. Google Maps itself does not normally show email addresses.

Input options

All fields are optional. If you provide neither searchTerms nor startUrls, the Actor falls back to ["dentists"] and logs a warning.

InputDefaultDescription
searchTermsnone (falls back to ["dentists"])Google Maps search terms, for example Hyundai dealership or HVAC contractors.
locationOrleans, ONCity, region, postal code or country appended to each search term. Set it for your target market.
startUrlsnoneGoogle Maps search or place URLs, used instead of or in addition to search terms.
maxItems100Maximum unique places to save (1 to 10,000).
maxResultsPerSearch100Maximum place URLs to process from each Google Maps search page (1 to 1,000).
contactExtractionemailsnone (Maps fields only), basic (adds website, domain and social profiles) or emails (also visits contact pages and extracts emails).
emailVerificationsyntaxnone, syntax, or mx (a real MX-record lookup, recommended). dns is an alias for mx.
staffExtractionfalseAlso fetch team/staff pages and fill staff_contacts. Collects personal data about named people. Only applies when contactExtraction is emails. See Responsible use.
requireEmailfalseSave only places where at least one email was found.
requireWebsitefalseSave only places that have a website.
minRatingnoneSkip places below this rating. Applied only when Google exposes the rating; places with an unknown rating are kept.
minReviewCountnoneSkip places with fewer reviews. Applied only when Google exposes the count; places with an unknown count are kept.
categoriesnoneOnly save places whose Google category matches one of these (case-insensitive, exact match).
excludeCategoriesnoneSkip places whose category matches one of these.
inferCategoriestrueWhen categories is empty, apply a conservative category allow-list for some common searches. See Category filtering.
includeReviewstrueParse the few recent review snippets already present in the place data and compute pain signals. No extra requests.
scrapeDetailPagestrueFetch the Google Maps place page for extra fields before contact enrichment.
maxConcurrency5Maximum parallel HTTP connections (1 to 50).
requestRetries2Retries for failed page requests (0 to 10).
requestTimeoutSecs30Timeout per request (5 to 120).
requestDelayMillis0Optional delay between Google Maps search pages.
proxyUrlnoneExplicit proxy URL. Takes priority over proxyConfiguration.
proxyConfigurationnoneApify Proxy configuration (the standard proxy editor).
useDefaultProxytrueWhen you configure no proxy of your own, the Actor may route requests through a proxy it provides. Set to false to connect directly.

Common alias names from other Maps scrapers are also accepted, for example searchStrings, maxCrawledPlaces and scrapeEmails. The canonical names above win when both are present.

Category filtering

Google Maps returns loosely related places for any search, so the Actor can filter by the category Google assigns.

  • categories and excludeCategories are matched against the place's Google category names, case-insensitively and exactly. Your explicit categories list always takes priority.
  • inferCategories (on by default) applies only when you give no categories, and only when the search term matches one of four groups: law firms, dentists, coffee shops, and car dealerships.
  • The dealership group is triggered by search terms containing dealership, car dealer, auto dealer or used car. It keeps categories such as Auto dealer, Car dealer, New car dealer, Used car dealer and Truck dealer, plus brand-specific Google categories ending in dealer (for example Hyundai dealer).
  • Search terms outside these groups get no inferred filter, so everything Google returns is kept unless you set categories.
  • To turn the automatic filter off, set inferCategories to false.

Output

Each saved dataset item is one business lead. The dataset has a stable set of fields, so CSV and API exports are consistent. The default Overview view shows the most useful columns.

GroupFields
Identitytitle, category_name, categories, description, google_maps_url, place_id, cid, fid
Locationaddress, street, city, state, postal_code, country_code, latitude, longitude, plus_code
Reputationtotal_score, reviews_count, reviews_distribution
Contactphone, phone_unformatted, website, domain, emails, primary_email, social_profiles
Email auditemail_status, email_confidence, email_type, email_sources
Staffstaff_contacts
Review signalsreview_status, reviews_sampled, recent_reviews, sampled_reviews_last_30d, _90d, _365d, owner_responses_sampled, owner_response_rate_sampled, pain_signals, pain_total
Lead scorepain_score, volume_score, owner_access_score, value_estimate, difficulty_estimate, lead_score, lead_score_breakdown
Chain annotationchain_status, chain_confidence, chain_signals
Run statusdetail_status, contact_status, contact_error, scraped_at, input_query, input_location, search_string, rank

Notes on specific fields:

  • total_score and reviews_count are best effort. Google does not expose them on every page, so null means unknown, not zero. reviews_distribution is currently always {}.
  • email_type is role for shared inboxes such as info@ and sales@, and personal otherwise. Role addresses are kept because they are often the only monitored inbox of a small business.
  • Placeholder, system and platform addresses (for example noreply@, example.com samples, and vendor addresses leaking from embedded widgets) are dropped before primary_email is chosen. An address on the business's own website domain is preferred as primary_email.

contact_status values

ValueMeaning
successPages were fetched and, with contactExtraction: "emails", at least one email was found.
no_emailPages were fetched but no usable email was found.
no_websiteThe place has no website to check.
host_unreachableThe website host repeatedly failed earlier in the run and was skipped.
failedNo page could be fetched for another reason (timeouts, 404s and similar).
blockedEvery page request was refused with HTTP 401, 403, 429 or 503. contact_error holds the most common status, for example http_403.
not_requestedcontactExtraction was none.

email_status values

ValueMeaning
mx_foundWith emailVerification: "mx": the domain has a mail server configured. This is stronger than syntax alone, but it does not prove a specific mailbox is monitored.
syntax_validThe address is well formed (syntax mode, or an MX lookup that could not be completed). It does not confirm the domain accepts mail.
mx_absentThe MX lookup completed and found no mail server for the domain.
not_verifiedAn email was found and emailVerification was none.
not_foundNo usable email was found.
not_requestedEmail extraction was not enabled.
invalidA candidate address was rejected.

staff_contacts

With staffExtraction: true and contactExtraction: "emails", staff_contacts is a list of up to 50 objects with name, title, department, email, phone, source_url and is_decision_maker. Without staffExtraction, it is an empty list.

  • Pages checked: /team, /our-team, /staff, /meet-the-team, /about-us, plus up to two same-site links found on the homepage whose link text mentions team, staff, meet or our people.
  • Only people with a published email on the business's own domain are kept. Entries are de-duplicated by email. department is only filled for data formats that provide it.
  • is_decision_maker is a title-based flag for general managers and sales managers. It is not a verification of anyone's authority, and titles such as assistant, associate, service, parts, finance and similar are not flagged. Decision-makers are listed first.
  • Staff emails are also added to emails and email_sources (source type staff_page), so requireEmail counts them. They do not replace a regular email on the business domain as primary_email.

Review signals and lead score

With includeReviews on, the Actor reads the handful of recent review snippets Google includes in the place data (typically a few, not the full history). Treat the review fields as a directional sample:

  • review_status is sampled, no_reviews_found or not_requested.
  • sampled_reviews_last_* and owner_response_rate_sampled describe the sample only, not the whole business.
  • pain_signals lists matched categories (such as phone_unanswered, no_callback, hold_time, appointment_access, billing_clarity, cancellation, repeat_contact, no_show and quote_follow_up) with the matched phrases and evidence_urls linking to the reviews. Read the linked reviews before using a signal in outreach.

lead_score (0-100) is a weighted blend of pain_score (30%), volume_score (20%), owner_access_score (25%) and value_estimate (25%), minus difficulty_estimate (15%). lead_score_breakdown shows each value, weight and contribution. value_estimate and difficulty_estimate are coarse guesses from the business category, not measurements. Use lead_score to sort a list, not as a valuation.

chain_status (independent, likely_chain or unknown) is an annotation only and never removes a row. It reflects only places processed earlier in the same run.

Run summary

Each run writes a RUN-SUMMARY record to the key-value store. Counters include:

  • saved_count, duplicate_count, filtered_count, discovered_places
  • contact_success_count: places with contact_status success.
  • contact_blocked_count: places with contact_status blocked. Blocked places are never counted as successes.
  • contact_error_count: places whose processing raised an unexpected error, plus failed dataset pushes.
  • filter_unverified_count: places kept by minRating or minReviewCount because Google did not expose the value.
  • stop_reason: completed, max_items_reached, no_places_found or deadline_reached.

no_email, no_website, host_unreachable and failed places are not counted in the three contact counters.

What to expect and limitations

How a run works:

  1. Searches Google Maps for each search term and location (or reads your start URLs) and removes duplicates.
  2. Optionally fetches each Maps place page for more business fields.
  3. Visits the business website's home, contact, contact-us and about pages (and team pages if staffExtraction is on), then extracts and cleans emails and social profiles.
  4. Applies your filters and saves the row. A failure on one site never fails the run.

Limitations to plan around:

  • Some websites block automated requests. Those rows are saved with contact_status: "blocked" and a contact_error such as http_403. The Actor does not attempt to bypass bot protection, CAPTCHAs or access controls, and it only reads pages a normal visitor could open. Blocked rows still have the Maps data, phone number and website.
  • Staff extraction only works where the site publishes staff data in a supported format: structured team data embedded by some dealership website platforms, or schema.org Person JSON-LD. Many sites use neither, so an empty staff_contacts is common even when the site has a visible team page.
  • Emails come only from publicly published pages on the business website. If a site does not publish an address, or hides it behind a contact form, the Actor will not find one.
  • A valid-looking email is not a guaranteed inbox. Even mx_found only means the domain can receive mail.
  • Rating, review count and reviews are best effort. Google does not expose them on every page, and review analysis uses a small sample.
  • Results depend on what Google Maps and each website return at run time and may vary between runs.

Responsible use

Business websites can list personal data, and staff extraction deliberately collects names, titles and work emails of named people.

  • Use the data only for lawful purposes and only for contacts that businesses have publicly listed for business use.
  • You are responsible for complying with the laws that apply to your outreach, such as CASL in Canada, CAN-SPAM in the United States and GDPR in the EU and UK, and with the terms of the websites you collect from. That includes honoring consent rules, providing identification and an unsubscribe option, and responding to removal requests.
  • staffExtraction is off by default for this reason. Enable it only where your use is lawful.
  • Review the data before you contact anyone. Do not use the Actor to harass people or to build lists of private individuals.

Pricing

Billing is pay-per-event, per saved business lead in the dataset. Places that are filtered out or skipped are not saved. See the pricing tab for current prices.

Example setups

Paste any of these into the Input tab (JSON view), change location, and optionally click Save as a new task to reuse or schedule it.

Dental clinics with verified emails only:

{
"searchTerms": ["dentists", "dental clinics", "orthodontists"],
"location": "Orleans, ON",
"maxItems": 200,
"contactExtraction": "emails",
"emailVerification": "mx",
"requireEmail": true
}

Home-service contractors that have a website:

{
"searchTerms": ["HVAC contractors", "plumbers", "roofing companies"],
"location": "Dallas, TX",
"maxItems": 200,
"contactExtraction": "emails",
"requireWebsite": true
}

Maps-only market sizing, no website visits:

{
"searchTerms": ["coffee shops"],
"location": "Austin, TX",
"maxItems": 100,
"contactExtraction": "none"
}

Start from Google Maps URLs instead of search terms:

{
"startUrls": [
"https://www.google.com/maps/search/law+firms+miami",
"https://www.google.com/maps/place/Example+Business/"
],
"maxItems": 100,
"contactExtraction": "emails"
}

Pre-saved example tasks you can open and run:

Tips

  • Use specific searches such as emergency dentists or family law attorneys instead of broad terms like businesses, and always set location.
  • Keep requireEmail off for a complete market list, then filter on email_status and contact_status after export.
  • Use emailVerification: "mx" to separate domains that can receive mail from those that cannot.
  • Run contactExtraction: "none" first to size a market, then rerun the niches you care about with emails.
  • Schedule a task to refresh a list, and connect the dataset to your CRM, Google Sheets, Make, Zapier or n8n through Apify integrations and the Apify API.

FAQ

Does this scrape emails from Google Maps directly? No. Google Maps usually does not show email addresses. The Actor finds the business and its website on Maps, then reads public pages on that website.

Why is a row blocked? The business website refused every automated request, typically with HTTP 403 or 429, because of bot protection. The Actor does not try to bypass it. The row keeps its Maps data, and contact_error shows the status code.

How do I get contacts for a blocked site? Call the phone number in the row, or use the contact form on the website, both of which are normal ways for a person to reach the business. You can also rerun later, since some blocks are temporary, or try a different proxy through proxyUrl or proxyConfiguration.

Why is there no email on a row? Common reasons: the business has no website (no_website), the site does not publish an address, it only offers a contact form, the address is on a page the Actor does not visit, or the site could not be read (blocked, failed or host_unreachable). Check contact_status to see which case applies.

Why is staff_contacts empty? staffExtraction is off by default. When it is on, many sites still return nothing because they do not publish staff data in a supported format, or do not publish staff emails on the business's own domain.

Does it use a proxy? The Actor may route requests through a proxy. You can supply your own with proxyUrl, use Apify Proxy through proxyConfiguration, or set useDefaultProxy to false to connect directly.

What happens if a business has no website or no email? The Maps record is still saved, unless you set requireWebsite or requireEmail, in which case that row is skipped.

Can I export the data? Yes. Apify datasets export as JSON, CSV, Excel, XML, RSS or HTML, and are available through the Apify API.

Can I use these emails for bulk campaigns? Only if your campaign complies with the laws and site terms described in Responsible use. Emails come from public pages, which does not by itself mean you may send marketing messages to them.

Support

Report issues or request features on the Issues tab.