# Google Maps Email Extractor & Scraper: Business Leads (`s_actors/google-maps-email-extractor`) Actor

Google Maps email extractor and lead scraper: business emails from websites, mail server (MX) checked, social profiles, contact page, phone, address. Pay only for places with an email: $1.49 per 1,000. Free lead filters, no repeat leads.

- **URL**: https://apify.com/s_actors/google-maps-email-extractor.md
- **Developed by:** [Superior Actors](https://apify.com/s_actors) (community)
- **Categories:** Lead generation, Marketing, AI
- **Stats:** 5 total users, 0 monthly users, 95.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.19 / 1,000 lead with emails

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Google Maps Email Extractor & Scraper: Business Leads, Pay Only for Emails Found

Extract **emails** from **Google Maps** businesses and build **lead lists** in Excel, CSV or JSON. The Actor searches Google Maps for any business type and area, reads each business's **website** (contact, imprint and about pages too) and returns its **emails**, **social profiles**, contact page, phone, address and rating. What sets it apart:

- **You pay only for places with an email: $1.49 per 1,000.** Places whose website shows no email are free (or left out, as you choose). The best-known Google Maps email extractor charges $4 per 1,000 places plus $2 per 1,000 for "company contacts", whether an email is found or not.
- **Every email checked for a mail server.** Each email domain is looked up for DNS mail (MX) records. Typos and dead domains (`info@chakrarestauarant.com`) go to `invalidEmails` and do not count as a lead; `emailMailServer` shows the result.
- **The right email first.** `email` is the address on the business's own domain (`info@`, `hello@`, `office@` first), `emails` has all of them, `emailSourceUrl` the page it was on.
- **Social profiles and contact page, free.** Facebook, Instagram, LinkedIn, X, TikTok, YouTube, Pinterest, Yelp and WhatsApp links from the website, and the **contact page** URL for businesses that only have a form.
- **Sites other scrapers miss.** Emails hidden in page data (JSON-LD, buttons) and sites behind Cloudflare are read like a browser would: on 40 Austin dentists, 21 emails instead of 15 with a plain page fetch.
- **No repeat leads.** Turn on **Only new leads** and the next run skips every business you already received: never pay twice for the same lead, and catch new businesses as they open.
- **Free lead filters**: unclaimed listings, few reviews, minimum rating, with a phone, categories. More than Google's ~120 places per search with automatic **map tiles**.

```json
{ "searchTerms": ["dentist"], "locations": ["Austin, TX"], "maxPlacesPerSearch": 50 }
```

#### What you get

**One row per business with an email.** Real examples, dentists in Austin, TX, October 2026:

| business | email | mail server | phone | social profiles |
|---|---|---|---|---|
| Enamel Dentistry Parmer Park | hello@enameldentistry.com | ✅ | (512) 588-5199 | Instagram, LinkedIn |
| Healing Tooth - Comprehensive Family Dentistry | austin@healingtooth.com | ✅ | (512) 451-1182 | Facebook, Instagram |
| Swish Dental Downtown | downtown@swishsmiles.com | ✅ | (512) 713-1099 | Facebook, Instagram, TikTok |
| Toothbar | info@toothbar.com | ✅ | (512) 607-4268 | Instagram, Facebook, LinkedIn, Yelp |
| The Tooth Inc | toothinctx@gmail.com | ✅ | (512) 593-1874 | Facebook, Instagram |

| Field | Description |
|---|---|
| `email` | The best address to write to: on the business's own domain first, mail server checked |
| `emails`, `invalidEmails` | All emails found on the website; emails whose domain cannot receive mail |
| `emailMailServer` | `true` = the domain has a mail server (MX), `null` = not checked or DNS did not answer |
| `emailSourceUrl`, `contactPageUrl`, `websiteReachable` | Page where the email was found, the site's contact page, whether the site answered |
| `facebook`, `instagram`, `linkedin`, `x`, `tiktok`, `youtube`, `pinterest`, `yelp`, `whatsapp`, `socialProfiles` | Profiles linked from the website |
| `name`, `category`, `categories`, `description` | The business, its Google categories and Google's short description |
| `phone`, `phoneInternational`, `website`, `domain` | Phone as shown and in +1 format; the website and its domain |
| `rating`, `reviewsCount`, `reviewsUrl` | Stars, number of Google reviews, the reviews page |
| `address`, `street`, `neighborhood`, `city`, `postalCode`, `state`, `countryCode`, `latitude`, `longitude`, `timezone` | Where it is |
| `openingHours`, `businessStatus`, `isClaimed`, `ownerName`, `attributes`, `imageUrl` | Hours, open or closed, claimed listing or not, owner name, Google attributes, photo |
| `leadSignals` | `no email`, `unclaimed`, `no phone`, `fewer than 10 reviews`, `rating under 4`, `website down` |
| `placeId`, `cid`, `fid`, `kgmid`, `googleMapsUrl` | Google's IDs of the place and a link that always opens it |
| `searchTerm`, `searchLocation`, `searchUrl`, `placeUrl`, `rank`, `isNew`, `scrapedAt` | Which search found it, its position, new leads |

Six table views: **Leads**, **Emails**, **Social profiles**, **Location**, **Details** and **Searches**.

#### How it works

| Step | What happens |
|---|---|
| 1. Search | Each search term is searched in each location on Google Maps ("Austin, TX", "10001", "London", "Bavaria"), 20 places a page; past Google's ~120-200 per search the area is split into map tiles |
| 2. Filters | Closed places, places without a website and your lead filters are removed first: free, and their sites are not read |
| 3. Website | The page Google links is read like a browser; while no email is found, up to 2 contact-like pages of the same site (contact, imprint / Impressum, about, appointment, team) |
| 4. Emails | From mailto links, visible text, Cloudflare-protected addresses, page data (JSON-LD) and "name \[at] domain \[dot] com"; placeholders (`you@example.com`) and tracking addresses are dropped |
| 5. Check | Each email domain is looked up for mail (MX) records; the best address goes to `email` |
| 6. Charge | Only places that come back with an email are charged; the Actor reads up to 6 places per lead you ask for |

#### Why this Actor

| | This Actor | Typical Google Maps email extractor |
|---|---|---|
| Price | **$1.49 per 1,000 places with an email** | $3-$10 per 1,000 places, emails or not (leader $4 + $2 contacts add-on) |
| Places without an email | ✅ Free, or left out | ❌ Charged |
| Mail server (MX) check | ✅ Every email | ⚠️ Paid add-on or none |
| Best email picked | ✅ Own domain first | ❌ A list |
| Emails in page data and behind Cloudflare | ✅ | ⚠️ Often missed |
| Social profiles and contact page | ✅ Included | ⚠️ Paid add-on in some |
| No repeat leads across runs | ✅ Seen places free, sites not read again | ❌ |
| Lead filters (unclaimed, few reviews, rating) | ✅ Free | ⚠️ Paid "filter" add-on |
| More than ~120 places per search | ✅ Automatic map tiles | ⚠️ Some |

#### Pricing

Pay per event, no subscription needed. Apify Scale and Business plans pay less:

| Event | Free and Starter plans | Scale plan | Business plan |
|---|---|---|---|
| Run start | $0.001 | $0.001 | $0.001 |
| Lead with email (all fields) | $0.00149 | $0.00134 | $0.00119 |

**1,000 businesses with an email = $1.49.** Free: places without an email, places removed by your filters, duplicates, places already seen with **Only new leads**. Platform usage is included. Set a maximum cost per run in the run options: the Actor stops there.

#### Ready-made tasks

| Task | What it does |
|---|---|
| [Scrape Business Emails from Google Maps](https://apify.com/s_actors/google-maps-email-extractor/examples/scrape-emails-from-google-maps) | Emails, phones and social profiles of local businesses, mail server checked |

#### Email lists in three steps

1. Search terms = the businesses you sell to ("roofing contractor", "dentist", "real estate agency"); locations = your cities or ZIP codes.
2. **Max leads per search** = how many businesses with an email you want from each search.
3. Export the **Leads** view to Excel or Google Sheets, or send it to your CRM or email tool with Make, Zapier or **n8n**.

For a full local list (calls, forms, social outreach) turn **Only places with an email** off: places without an email come free, with their phone, contact page and social profiles.

#### FAQ

**How many places have an email?** Depends on the trade: in October 2026 tests, 21 of 40 Austin dentists, 12 of 16 London plumbers, 10 of 17 Berlin restaurants. Many small businesses have only a contact form: their `contactPageUrl` is in the row when **Only places with an email** is off.

**Where do the emails come from?** Only from the business's own website, the page linked on its Google Maps listing and its contact pages. No guessing (`info@` + domain) and no third-party databases.

**What does the mail server check prove?** That the domain can receive email (it has MX records). It does not log in to the mailbox: a real address on a working domain can still bounce if it was deleted.

**Why did I get fewer leads than I asked for?** The area has fewer businesses with an email on their website, or your filters are strict. The Actor reads up to 6 places per lead asked for, then stops; widen the area or add search terms.

**Can I get emails for my own list of places?** Yes: paste Google Maps place links, place IDs or CIDs into **Place links or IDs**.

**Which languages and countries?** Any: set **Language** and **Country** (Google region, such as `de` for Germany). German sites: the Impressum page is read.

**Do I need a Google account or API key?** No. The Actor reads the public Google Maps pages and public business websites any visitor sees.

#### Use with the API and AI agents

Run it from the Apify API, the JavaScript or Python client, **n8n**, Make or Zapier, or from AI agents through the [Apify MCP server](https://mcp.apify.com) (Claude, ChatGPT, Cursor). One call: `POST https://api.apify.com/v2/acts/s_actors~google-maps-email-extractor/run-sync-get-dataset-items` with the input above returns the leads as JSON.

#### Other Google tools

| Actor | What it does |
|---|---|
| [Google Jobs Scraper](https://apify.com/s_actors/google-jobs-scraper) | Jobs from every board in Google Jobs with all apply links, salary per year, job alerts |
| [Google Search Results Scraper](https://apify.com/s_actors/google-search-scraper) | Real Google results with AI Overview, People also ask, rank tracker |
| [Google AI Overview Scraper & Tracker](https://apify.com/s_actors/google-ai-overview-scraper) | Full Google AI Overview answers with real source URLs; is your brand mentioned or cited |
| [Google Ads Transparency Center Scraper](https://apify.com/s_actors/google-ads-transparency-scraper) | Competitors' Google ads with ad copy, YouTube videos, countries |
| [Google Maps Scraper](https://apify.com/s_actors/google-maps-scraper) | Every Google Maps place with phone, website, rating, hours: $0.89 per 1,000 |
| [Google Shopping Price Tracker](https://apify.com/s_actors/google-shopping-price-tracker) | Google Shopping prices and sellers, price changes |
| [Google Hotels Scraper](https://apify.com/s_actors/google-hotels-scraper) | Hotel prices from every booking site |
| [Google Flights Scraper](https://apify.com/s_actors/google-flights-scraper) | Flight prices, cheapest dates, price alerts |
| [Google Play Scraper](https://apify.com/s_actors/google-play-scraper) | Apps, ratings, reviews, keyword rankings |
| [Bulk Image Downloader](https://apify.com/s_actors/bulk-image-downloader) | Google Images and image links to a ZIP file |

#### Is it legal?

The Actor reads public Google Maps business listings and the public websites of those businesses, the pages anyone can open without an account. Business emails are published by the businesses themselves; use them according to the laws that apply to you (GDPR, CAN-SPAM, CASL, ePrivacy for cold email) and Google's terms.

# Actor input Schema

## `searchTerms` (type: `array`):

What you would type into Google Maps, one per line: "plumber", "dentist", "coffee shop", "roofing contractor", "italian restaurant", "car dealer". Each term is searched in every location below. Without locations, write the place into the term: "dentist in Austin TX".

## `locations` (type: `array`):

City, ZIP / postal code, region or country, one per line: "Austin, TX", "10001", "London", "Bavaria, Germany", "SW1A 1AA". The Actor finds the area on Google Maps and searches inside it. Several = each term in each location.

## `maxPlacesPerSearch` (type: `integer`):

Places WITH an email per search term and location (with "Only places with an email" on; otherwise places in total). The Actor keeps reading Google Maps until it has this many, up to 6 places per lead asked for. Places without an email are free.

## `onlyWithEmail` (type: `boolean`):

On: only places whose website shows an email (you pay only for these). Off: also places without an email, free, with their phone, social profiles and contact page.

## `checkEmailDomains` (type: `boolean`):

Look up each email domain for a mail server (DNS MX records). Emails whose domain cannot receive mail (typos, expired domains) go to invalidEmails and do not make a lead. emailMailServer shows the result.

## `contactPages` (type: `integer`):

When the page Google links shows no email, also read up to this many contact-like pages of the site (contact, imprint / Impressum, about, appointment, team). 0 = the linked page only.

## `deepSearch` (type: `boolean`):

When Google stops listing (its limit is ~120-200 places per search), split the area into smaller map tiles and search each, to reach more businesses in a city. Off = one search, the places Google lists first.

## `onlyUnclaimed` (type: `boolean`):

Only listings whose owner has not claimed them on Google ("Claim this business" on Maps): leads for Google Business Profile and local SEO services. Every row has isClaimed.

## `onlyWithPhone` (type: `boolean`):

Skip places without a phone number on Google Maps.

## `minRating` (type: `number`):

Only places rated at least this (1-5). Empty = any.

## `minReviews` (type: `integer`):

Only places with at least this many Google reviews. Empty = any.

## `maxReviews` (type: `integer`):

Only places with at most this many reviews: new or small businesses that need reviews and marketing. Empty = any.

## `categoryFilter` (type: `array`):

Keep places whose Google category contains one of these words: "plumber" drops the HVAC companies and general contractors Google also lists for "plumber". Empty = all.

## `skipClosed` (type: `boolean`):

Skip places marked temporarily or permanently closed. Every row has businessStatus.

## `onlyNewPlaces` (type: `boolean`):

Remember every place checked and next time skip places seen before (each new row isNew: true). First run = everything. Places seen before are free and their websites are not read again.

## `monitorName` (type: `string`):

Separate memory for each lead list: "dentists-austin", "roofers-texas". Same name = same list.

## `searchUrls` (type: `array`):

Links copied from Google Maps after a search, such as https://www.google.com/maps/search/coffee/@30.26,-97.74,14z. The words and the map area of the link are used.

## `placeUrls` (type: `array`):

Single places: Google Maps place links, place IDs (ChIJ...), CIDs or https://maps.google.com/?cid=... links. Each becomes one row with the same fields and the emails of its website (filters apply).

## `language` (type: `string`):

Language of categories, opening hours and descriptions.

## `countryCode` (type: `string`):

Two-letter country code Google uses for the results (us, gb, de, fr, in, au...). Set it to the country you search in.

## `maxConcurrency` (type: `integer`):

Google Maps pages read at once (websites: four times as many).

## `proxyConfiguration` (type: `object`):

The Actor reads Google Maps and websites directly and switches to Apify Proxy (datacenter, then residential) only if Google starts refusing; a website that refuses gets one more try through a datacenter IP.

## `debugLog` (type: `boolean`):

Log every retry.

## Actor input object example

```json
{
  "searchTerms": [
    "dentist"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxPlacesPerSearch": 50,
  "onlyWithEmail": true,
  "checkEmailDomains": true,
  "contactPages": 2,
  "deepSearch": true,
  "onlyUnclaimed": false,
  "onlyWithPhone": false,
  "skipClosed": true,
  "onlyNewPlaces": false,
  "monitorName": "default",
  "language": "en",
  "countryCode": "us",
  "maxConcurrency": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "debugLog": false
}
```

# Actor output Schema

## `overview` (type: `string`):

Business, best email, phone and website.

## `emails` (type: `string`):

All emails of each place, the mail server check and where they were found.

## `social` (type: `string`):

Social profiles linked from each website.

## `location` (type: `string`):

Address parts and coordinates.

## `details` (type: `string`):

Categories, status, claimed or not, opening hours, description, photo.

## `search` (type: `string`):

Search term, location and rank of each lead.

## `all` (type: `string`):

Every field of every lead.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchTerms": [
        "dentist"
    ],
    "locations": [
        "Austin, TX"
    ],
    "maxPlacesPerSearch": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("s_actors/google-maps-email-extractor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchTerms": ["dentist"],
    "locations": ["Austin, TX"],
    "maxPlacesPerSearch": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("s_actors/google-maps-email-extractor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchTerms": [
    "dentist"
  ],
  "locations": [
    "Austin, TX"
  ],
  "maxPlacesPerSearch": 50
}' |
apify call s_actors/google-maps-email-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s_actors/google-maps-email-extractor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/cX2EIIZ54oa1HKMEI/builds/2vtYRSfb0GAQs8gMV/openapi.json
