# Google Maps Email Extractor | Business Email List | $1 / 1K (`hridayrungta/google-maps-email-extractor`) Actor

Build a business email list from Google Maps: local business leads with name, category, address, phone, website, rating, plus emails (with source page), extra phones and LinkedIn/Facebook/Instagram/X/YouTube/TikTok. One flat CRM-ready row. $0.50/1K leads + $0.50/1K emails.

- **URL**: https://apify.com/hridayrungta/google-maps-email-extractor.md
- **Developed by:** [Hriday Rungta](https://apify.com/hridayrungta) (community)
- **Categories:** Lead generation, Automation, SEO tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 lead scrapeds

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

Build a **business email list from Google Maps** in one run. Type a business type and a place ("dentist" + "Austin, TX"), and get **local business leads** ready for a CRM: name, category, address, phone, website, rating and review count from Google Maps, plus the **emails**, extra phone numbers and **social profiles** (LinkedIn, Facebook, Instagram, X, YouTube, TikTok) found on each business's own website. One flat row per business, CSV and Excel friendly.

**$0.50 per 1,000 leads + $0.50 per 1,000 emails found** (so at most **$1 per 1,000 leads with an email**), plus a $0.003 start fee per run. No login, no API key, no browser.

### What you can use it for

- **Business email list for outreach:** every roofer, dentist, agency or restaurant in a city with its email, phone and website, ready to import into HubSpot, Pipedrive, Salesforce, Instantly, Lemlist or a Google Sheet.
- **Local business leads by city, state or country:** build a USA, UK, Canada or Australia business email list one category and location at a time, or cover a whole metro area with a radius.
- **Lead generation tool for agencies and freelancers:** find businesses to pitch (web design, SEO, ads, bookkeeping) with ratings and review counts to qualify them, and "Only leads with an email" to skip the ones you cannot reach.
- **Small business email list with source pages:** every email comes with the page it was found on, so you can check it before you send.
- **Social profiles for multichannel outreach:** the company LinkedIn page, Facebook, Instagram, X, YouTube and TikTok links in their own columns.
- **Google Maps leads for cold calling:** the Google Maps phone in local and E.164 format, plus extra numbers found on the website.
- **Market lists for sales territories:** count and list businesses per category and city with real addresses and coordinates.
- **Automated lead pipelines:** schedule it weekly and push new leads to a CRM through Make, n8n, Zapier or the Apify API.

### Which of our Google Maps Actors should you use?

| You have / you need | Use |
|---|---|
| A business type and a location, and you want **leads with emails** in one flat list | **This Actor** |
| Only Google Maps data (no emails), or extra fields like **opening hours** and descriptions, at the lowest price | [Google Maps Places Scraper](https://apify.com/hridayrungta/google-maps-places-scraper) ($0.30 per 1,000 places) |
| A list of **websites or domains** you already have, and you want their emails, phones and socials | [Contact Info Scraper](https://apify.com/hridayrungta/contact-info-scraper) |

This Actor runs the same Google Maps engine as the Places Scraper and the same website crawler as the Contact Info Scraper, joined into one lead-generation run with lead-friendly defaults: website enrichment always on, one row per company, the best email picked for you, flat columns only.

### What you get for every lead

| Column | What it is |
|---|---|
| `name`, `category`, `categories` | Business name and Google Maps categories |
| `email` | Best email for outreach: the business's own domain first, role inboxes (info@, contact@, hello@) before personal ones, no-reply and privacy addresses last |
| `emailType` | `business-domain`, `free-provider` (gmail, outlook...) or `other-domain` (a parent company or booking provider) |
| `emailFoundOn` | The web page where that email was found |
| `allEmails`, `allEmailsFoundOn` | Up to 10 emails from the website and the page each one came from, separated by `; ` |
| `phone`, `phoneE164` | Phone from Google Maps, local and international format |
| `websitePhones` | Up to 5 other numbers found on the website (E.164) |
| `website`, `domain` | Website listed on Google Maps |
| `linkedin`, `facebook`, `instagram`, `twitter`, `youtube`, `tiktok` | Social profiles linked from the website (company LinkedIn page preferred) |
| `address`, `street`, `city`, `postalCode`, `state`, `countryCode` | Address parts |
| `rating`, `reviewsCount` | Google star rating and number of reviews |
| `mapsUrl`, `placeId`, `latitude`, `longitude` | Google Maps link, stable place ID and coordinates |
| `enrichmentStatus` | `email-found`, `no-email-found`, `website-unreachable`, `no-website`, `website-is-social-profile`, `directory-link` |
| `pagesCrawled`, `searchTerm`, `searchLocation`, `scrapedAt` | How the lead was found |

No arrays and no nested objects, so a CSV or Excel export has exactly these columns. A `RUN_SUMMARY` record in the run's key-value store lists every search with its lead count, plus duplicates and skipped websites.

### How to build a lead list from Google Maps

1. Type one or more **business types** (dentist, roofing contractor, marketing agency).
2. Add **locations** (Austin, TX, USA / Manchester, UK / Bavaria, Germany). Every business type is searched in every location.
3. Set **Max leads in total**. For more than one Google Maps window (about 230 places) per search, set a **radius in km**.
4. Optional: **Only leads with an email**, **Only businesses with a website**, minimum rating or reviews, category filter, and how many website pages to check.
5. Click **Start**, then export as CSV, Excel or JSON, or read the dataset from the API.

#### Input

| Field | Default | What it does |
|---|---|---|
| `searchTerms` | | Business types or keywords, one per line |
| `locations` | | Cities, regions, states or countries |
| `maxLeads` | 200 | Cost cap for the run |
| `maxLeadsPerSearch` | 200 | Cap per business type + location pair |
| `onlyWithEmail` | false | Write only leads whose website shows an email; leads without one are free |
| `onlyWithWebsite` | false | Skip businesses with no website |
| `onlyWithPhone` | false | Skip businesses with no phone |
| `dedupeByDomain` | true | One row per website, so chains and franchises do not repeat the same email |
| `maxPagesPerWebsite` | 4 | Enrichment depth: homepage plus contact, about, team and imprint pages (1-6) |
| `radiusKm` | 0 | Cover a whole area around the location with many map windows |
| `latitude`, `longitude` | | Custom centre instead of a text location |
| `startUrls` | | Google Maps search URLs |
| `minRating`, `minReviews`, `categoryFilter` | | Free filters |
| `language`, `countryCode` | en, us | Google Maps language and region |

#### Example input

```json
{
    "searchTerms": ["roofing contractor"],
    "locations": ["Denver, CO, USA"],
    "maxLeads": 100,
    "onlyWithEmail": true,
    "minRating": 4
}
```

#### Example output (real row from a test run, 2026-10-21)

```json
{
    "name": "High 5 Plumbing, Heating, Cooling & Electric",
    "category": "Plumber",
    "categories": "Plumber, Air conditioning contractor, Air conditioning repair service, Drainage service, Electrician, Furnace repair service, Heating contractor, Hot water system supplier, HVAC contractor, Water softening equipment supplier",
    "email": "office@high5plumbing.com",
    "emailType": "business-domain",
    "emailFoundOn": "https://high5plumbing.com/denver/",
    "allEmails": "office@high5plumbing.com",
    "allEmailsFoundOn": "https://high5plumbing.com/denver/",
    "phone": "(720) 340-3843",
    "phoneE164": "+17203403843",
    "websitePhones": "+17207299224",
    "website": "https://high5plumbing.com/denver/",
    "domain": "high5plumbing.com",
    "linkedin": "https://linkedin.com/company/high-5-plumbing",
    "facebook": "https://facebook.com/high5plumbing",
    "instagram": "https://instagram.com/high5homefix",
    "twitter": "https://twitter.com/high5plumbing",
    "youtube": "https://youtube.com/channel/UCFbsjp03uvVcec3-JPAMVSQ",
    "tiktok": "https://tiktok.com/@high5plumbing",
    "address": "800 E 73rd Ave Unit 2, Denver, CO 80229",
    "street": "800 E 73rd Ave Unit 2",
    "city": "Denver",
    "postalCode": "80229",
    "state": "Colorado",
    "countryCode": "US",
    "rating": 4.7,
    "reviewsCount": 2908,
    "mapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJyetJ-np3bIcR36oneVBL_nc",
    "placeId": "ChIJyetJ-np3bIcR36oneVBL_nc",
    "latitude": 39.828617799999996,
    "longitude": -104.9774848,
    "enrichmentStatus": "email-found",
    "pagesCrawled": 3,
    "searchTerm": "plumber",
    "searchLocation": "Denver, CO, USA",
    "scrapedAt": "2026-10-21T13:07:17.581Z"
}
```

### How many leads have an email?

Measured on our test runs on 2026-10-21 (299 leads: dentists and coffee shops in Austin, plumbers, agencies and restaurants in Denver and Manchester, dentists in Munich, pizza in Leeds, yoga studios in Brooklyn): **68% of all leads and 74% of leads with a website had at least one email**, and 77% had at least one social profile. It varies by niche (share of websites with an email): restaurants and some US trades publish fewer (Denver restaurants 53%, Colorado roofers 54%, Austin dentists 60%), agencies, UK trades and German businesses with their legal imprint pages more (Manchester agencies 93%, Manchester plumbers 92%, Munich dentists 95%). Businesses that only offer a contact form, or load their contact details with JavaScript, have no email in the output.

### Pricing

Pay per event, no subscription:

| Event | Price |
|---|---|
| Actor started (once per run) | $0.003 |
| Lead scraped (every row written) | $0.0005 ($0.50 per 1,000) |
| Email found (rows with at least one email) | $0.0005 ($0.50 per 1,000) |

Worked examples:

| Run | Cost |
|---|---|
| 100 leads, 70 with an email | $0.003 + 100 x $0.0005 + 70 x $0.0005 = **$0.088** |
| 1,000 leads, 680 with an email | $0.003 + $0.50 + $0.34 = **$0.843** |
| 1,000 leads with "Only leads with an email" on | $0.003 + $0.50 + $0.50 = **$1.003** |
| A search that finds nothing | **$0.003** |

Never charged: places removed by your filters, duplicates (same place or, by default, same website), and leads without an email when "Only leads with an email" is on. Set a maximum cost per run in the Apify run options and the Actor stops at your limit, never writing a row it cannot charge for.

### Tips

- **More than ~230 businesses for one search?** Set `radiusKm` (10 to 15 for a city). The Actor geocodes your location, tiles the area with map windows and de-duplicates.
- **A whole state or country:** list several cities in `locations` rather than one big region: "roofer in Colorado" returns one window of about 230 businesses, ten cities return ten.
- **Only want reachable leads?** Turn on "Only leads with an email". The run looks at about twice as many places and stops early with a clear message if a niche publishes almost no emails.
- **Chains:** with "One lead per website" on (default), 20 locations of the same franchise become one row. Turn it off when every branch is a separate client for you.
- **Verify before you send:** emails are taken from public websites and can be outdated. Run the list through an email validator before a cold campaign (see Related Actors).

### Integrations and scheduling

- **CRM and spreadsheets:** export CSV or Excel, or use the Apify integrations for Google Sheets, HubSpot and others.
- **Make, n8n and Zapier:** start the Actor from a workflow and read the dataset when the run finishes. Typical flow: new leads, then verify emails, then add to an outreach sequence.
- **Webhooks and API:** call the Actor over the Apify REST API or the JavaScript and Python clients, and get a webhook when the run succeeds.
- **Apify Schedules:** run the same lead search weekly to catch new businesses. De-duplication works inside one run, so compare new and old datasets by `placeId` (or `domain`) to keep only new leads.
- **Tasks:** save a search (business type, city, filters) as an Apify Task and re-run it with one click.

### FAQ

#### Is this a bought email list?

No. Every lead is built live when you run it: the business comes from Google Maps and the emails from that business's own public website, with the page each email was found on. Nothing comes from a stale database.

#### Does Google Maps show emails?

No. Google Maps lists name, phone and website but not emails. That is why this Actor visits each business's website (homepage plus contact, about, team and imprint pages) and collects the emails published there.

#### Why does a lead have no email?

The website has no public email (contact form only), loads its contact details with JavaScript, was unreachable, or the business has no website at all. `enrichmentStatus` tells you which. Leads without email cost $0.0005 and never pay the email fee.

#### What does emailType "other-domain" mean?

The email is on a different domain than the website, typically a parent company, a hotel or restaurant group, or a booking provider. Usually still a valid contact; filter it out if you only want same-domain addresses.

#### How is this different from a person-lookup email finder?

It finds the emails a business publishes on its own website (info@, office@, sometimes named staff). It does not guess or look up personal addresses of employees.

#### How fast is it?

About 1 to 1.5 leads per second including the website check (90 leads in about 70 seconds, 150 leads in about 100 seconds in our tests). The Google Maps part alone takes a few seconds per search.

#### What are alternatives?

[Google Maps Email Extractor by Lukas Krivka](https://apify.com/lukaskrivka/google-maps-with-contact-details) and [Google Maps Scraper by Compass](https://apify.com/compass/crawler-google-places) with contact enrichment are the most-used options on the Store, with more detail fields (reviews, images, opening hours, popular times). Pick them when you need those extras. Pick this Actor when you want a flat, CRM-ready lead list with emails at a lower price per lead.

#### Is it legal to build a business email list this way?

It only reads public Google Maps listings and public business websites, without logging in or bypassing access controls. Business contact data can still be personal data (a sole trader's email, for example), and Google's terms restrict automated access. You are responsible for how you use the list: follow data protection law (GDPR, CCPA) and anti-spam rules (CAN-SPAM, PECR), give an opt-out, and only contact businesses where you have a legitimate reason. This is not legal advice.

### Limits

- **Results follow Google Maps ranking** and fuzzy matching: "dentist" can include dental labs, and a made-up location is matched to whatever Google thinks you meant. Use the category filter to narrow it.
- **Coverage is best effort.** Google returns about 230 places per map window; area mode covers much more but cannot guarantee every business.
- **No browser:** sites that render contact details with JavaScript or only have a contact form return no email.
- **No reviews, photos, opening hours or popular times** (use the Places Scraper for hours, a reviews scraper for reviews).
- **Emails are not verified.** They are what the website shows today.

### Related Actors

| Actor | What it does |
|---|---|
| [Google Maps Places Scraper](https://apify.com/hridayrungta/google-maps-places-scraper) | Google Maps listings only (with opening hours) at $0.30 per 1,000, optional enrichment |
| [Contact Info Scraper](https://apify.com/hridayrungta/contact-info-scraper) | Emails, phones and socials from a list of websites you already have |
| [Easy Bulk Email Validator](https://apify.com/xmiso_scrapers/easy-bulk-email-validator---verify-emails-from-1-7-1000-rows) | Check which emails are deliverable before a campaign |
| [Google Maps Scraper (Compass)](https://apify.com/compass/crawler-google-places) | The most-used Google Maps scraper, with reviews, images and detail fields |
| [Google Maps Reviews Scraper](https://apify.com/compass/Google-Maps-Reviews-Scraper) | Review text and ratings for places |

# Actor input Schema

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

What kind of businesses you want as leads, one per line: dentist, roofing contractor, marketing agency, restaurant, yoga studio. Each term is searched in every location below.

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

Cities, regions, states or countries, one per line (Austin, TX, USA / Manchester, UK / Bavaria, Germany). Google geocodes the text itself. A small area gives local results; for a whole city or region also set a radius below.

## `maxLeads` (type: `integer`):

Cost cap for the whole run: at most this many lead rows are written (and charged) across all searches.

## `maxLeadsPerSearch` (type: `integer`):

Stop each business type + location pair after this many leads. One Google Maps window holds at most about 230 places; for more, set a radius so the area is covered with many windows.

## `onlyWithWebsite` (type: `boolean`):

Skip businesses that list no website on Google Maps. Skipped places are free.

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

Write only businesses whose website shows at least one email address. Leads without an email are dropped and never charged. Typically 40-60% of businesses with a website publish an email, so the run looks at about twice as many places.

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

Skip businesses that list no phone number on Google Maps.

## `dedupeByDomain` (type: `boolean`):

Keep only the first location of businesses that share a website (chains and franchises), so the list has one row per company and no repeated emails. Places are always de-duplicated by Google place ID.

## `maxPagesPerWebsite` (type: `integer`):

Enrichment depth: the homepage plus contact, about, team and imprint pages, up to this many pages in total. 1 = homepage only (fastest), 4 = recommended, 6 = deepest.

## `radiusKm` (type: `integer`):

0 = one Google Maps window per search (up to about 230 places). Above 0 the Actor tiles the area around the location with many overlapping windows and de-duplicates, so a whole city or metro area can be covered. Only places inside the radius are kept.

## `latitude` (type: `number`):

Optional. Search around exact coordinates instead of (or as well as) a text location. Use together with longitude and a radius.

## `longitude` (type: `number`):

Optional. Longitude of the custom centre.

## `startUrls` (type: `array`):

Optional. Paste Google Maps search pages (google.com/maps/search/plumber+in+leeds/@53.8,-1.55,13z). The search text and map position are read from the URL. Single place pages and short links are not supported.

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

Keep only businesses with at least this Google star rating (0 = no filter). Filters never cost extra.

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

Keep only businesses with at least this many Google reviews (0 = no filter).

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

Optional, one per line. Keep only places whose Google category contains one of these words (for example: dentist, orthodontist). Case-insensitive.

## `tileZoom` (type: `integer`):

How small each window is when a radius is set: 15 = about 2 km windows (balanced), 16 = about 1 km (dense city centres, more requests), 14 = about 4 km (rural areas).

## `maxTilesPerSearch` (type: `integer`):

Safety cap on how many map windows are requested for one search when a radius is set. Searching stops early after 12 windows in a row with nothing new.

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

Language of the Google Maps interface: category names and address format follow it (en, de, fr, es, pt, it, ja...).

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

2-letter region code sent to Google (us, gb, de, in, au...). It nudges ranking and result language toward that country.

## `useProxy` (type: `string`):

"On block" goes direct and falls back to Apify datacenter proxy (fresh IP per attempt) only when Google Maps or a website refuses a request. "Always" uses the proxy for every Google Maps request (slower). "Never" never uses a proxy.

## Actor input object example

```json
{
  "searchTerms": [
    "dentist"
  ],
  "locations": [
    "Austin, TX, USA"
  ],
  "maxLeads": 10,
  "maxLeadsPerSearch": 200,
  "onlyWithWebsite": false,
  "onlyWithEmail": false,
  "onlyWithPhone": false,
  "dedupeByDomain": true,
  "maxPagesPerWebsite": 4,
  "radiusKm": 0,
  "minRating": 0,
  "minReviews": 0,
  "tileZoom": 15,
  "maxTilesPerSearch": 30,
  "language": "en",
  "countryCode": "us",
  "useProxy": "onBlock"
}
```

# Actor output Schema

## `leads` (type: `string`):

No description

## `summary` (type: `string`):

No description

# 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, USA"
    ],
    "maxLeads": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("hridayrungta/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, USA"],
    "maxLeads": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("hridayrungta/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, USA"
  ],
  "maxLeads": 10
}' |
apify call hridayrungta/google-maps-email-extractor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hridayrungta/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/OGpYisaNNPxfXE0Ge/builds/Dj0goHteuBNcNJsO7/openapi.json
