# Google Maps Email Scraper: Business Leads with Emails (`redfoxscout/google-maps-leads-with-emails`) Actor

Get business leads from Google Maps with emails: name, category, address, phone, website, rating and reviews from Google Maps, plus emails, extra phones and Instagram, Facebook, LinkedIn and X profiles read from each business's website and contact page.

- **URL**: https://apify.com/redfoxscout/google-maps-leads-with-emails.md
- **Developed by:** [Red Fox Scout](https://apify.com/redfoxscout) (community)
- **Categories:** Lead generation, Travel
- **Stats:** 12 total users, 6 monthly users, 98.9% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.25 / 1,000 leads

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

Get **business leads from Google Maps with emails you can actually send to**. Every email is **checked for a working mail server** (dead domains dropped, the best address first, the page it came from attached), and **Cover the whole area** returns every matching business in a city, not just the first page of one search. For every place in a Google Maps search you get the Maps data (**name, category, address, phone, website, rating, reviews, hours**), and the Actor then visits the business's **own website and contact page** to add **emails, extra phone numbers and Instagram, Facebook, LinkedIn and X profiles**. One run, one table, ready for outreach. For sales teams and agencies building local B2B lead lists.

**Price: $3 per 1,000 leads.** Duplicates and failed searches are free, and with "Only leads with an email" you pay only for leads that have one. Apify's free plan ($5 monthly credit) covers about 1,600 leads a month.

[![Dentists in Dubai with checked emails: real output preview (Dentists in Dubai, only leads with an email, every email checked for a working mail server)](https://raw.githubusercontent.com/TikTop-Data/apify-store-assets/main/images/google-maps-leads-with-emails-output.png)](https://apify.com/redfoxscout/google-maps-leads-with-emails)

### Questions it answers

- What are the emails of dentists, contractors or agencies in my target city?
- Which local businesses have an Instagram page I can reach them on?
- Which leads have both a phone number and an email?
- How do these businesses rate on Google, and how many reviews do they have?

### Who uses this

- 📈 **Sales and lead generation:** local B2B lead lists with emails, by niche and city.
- 🏢 **Agencies:** prospects for web design, SEO, ads and social media services.
- 🧑‍💼 **Freelancers and consultants:** build a targeted outreach list in minutes.
- 🗂️ **CRM teams:** enrich local accounts with emails and social profiles.

### Why this Google Maps Email Scraper

- 📬 **Emails you can send to:** every email is checked for a working mail server; dead domains are dropped and the best address comes first.
- 🗺️ **Every business in a city:** Cover the whole area returns every matching place, not just the first page of one search.
- 🧩 **Maps data and website contacts in one row:** no second Actor, no joining files.
- 📄 **Contact pages included:** it follows each website's contact, about and imprint links, where emails usually are.
- 💰 **Pay for what you want:** turn on "Only leads with an email" and leads without one are free.
- 🧹 **Clean emails:** placeholders, image file names and tracking addresses are filtered out; the business's own role address (info@, office@) comes first.
- 💵 **$3 per 1,000 leads** with everything included.

### How to use the Google Maps Email Scraper

1. Click **Try for free** (a free Apify account is enough).
2. Enter what to search, one per line, e.g. `dentists in Austin TX`. Or enter `dentists` and add cities under Locations.
3. Optional: turn on **Only leads with an email**, set a minimum rating.
4. Click **Start**, then download as CSV or Excel, or send the leads to Google Sheets or your CRM.

### Input

| Field | Default | What it does |
|---|---|---|
| `searchQueries` | – | Searches as typed in Google Maps, one per line. |
| `locations` | – | Optional cities or areas; every search runs in each. |
| `onlyWithEmail` | `false` | Deliver and charge only leads with an email. |
| `minRating` | – | Skip places rated below this. |
| `maxPagesPerSite` | 3 | Contact, about or imprint pages checked per website. |
| `language` | `en` | Language of names and categories. |
| `countryCode` | `us` | Country Google uses for regional results. |
| `checkEmailDomains` | `true` | Check each email's domain for mail servers and drop addresses that cannot receive mail. |
| `includePeople` | `false` | Also list the people on the website's team, leadership and about pages, with title and the email, phone or LinkedIn shown beside them. |
| `searchWholeArea` | `false` | Cover the whole area: every place in the city or map circle, not just one search. |
| `startUrls` / `placeIds` | – | Google Maps search or place URLs, or place IDs, instead of (or with) searches. |
| `latitude`, `longitude`, `radiusKm` | – / – / 5 | Search a circle around a map point. |
| `skipClosedPlaces` | `false` | Leave out permanently or temporarily closed places. |
| `categoryFilterWords` | – | Keep only places whose Google category contains one of these words. |
| `searchMatching` | `all` | Brand searches: keep only places whose name contains (or equals) the search words. |
| `minReviews` | – | Skip places with fewer reviews. |
| `skipWithoutPhone` | `false` | Skip places without a phone number. |
| `maxItems` | 40 | Leads per search. A normal search ends after ~120-250 places; with Cover the whole area use hundreds or thousands. |
| `proxyConfiguration` | off | Optional proxy for very large runs. |

Example (the input behind the table above):

```json
{ "searchQueries": ["dentists in Austin TX"], "maxItems": 20 }
```

### Output

One row per business. A real row from that run (hours shortened):

```json
{
  "name": "ATX Family Dental",
  "category": "Dentist",
  "address": "1700 S 1st St, Austin, TX 78704",
  "phone": "(512) 717-3147",
  "website": "https://www.atxfamilydental.com/",
  "rating": 4.9,
  "reviewsCount": 914,
  "openingHours": { "Tuesday": "8 AM–5 PM", "Wednesday": "8 AM–5 PM", "...": "..." },
  "placeId": "ChIJb5gBC-u0RIYRHkntaUcdJGs",
  "email": "info@atxfamilydental.com",
  "emails": ["info@atxfamilydental.com"],
  "websitePhones": ["(512) 717-3147"],
  "instagram": "https://www.instagram.com/atxfamilydental",
  "facebook": null,
  "linkedin": null,
  "contactPageUrl": "https://www.atxfamilydental.com/contact",
  "websiteStatus": "ok",
  "searchQuery": "dentists in Austin TX"
}
```

Each row also has `categories`, `street`, `city`, `neighborhood`, `latitude`, `longitude`, `cid` and `googleMapsUrl`. `websiteStatus` says why contacts are empty when they are (`no website`, `HTTP 403`, `unreachable`).

### Example tasks

Ready-made inputs you can open, change and run:

- [Dentists in Dubai with checked emails](https://apify.com/redfoxscout/google-maps-leads-with-emails/examples/dentist-leads-dubai-checked-emails)
- [Get real estate agency emails in Miami](https://apify.com/redfoxscout/google-maps-leads-with-emails/examples/real-estate-agents-emails)
- [Get restaurant emails and Instagram pages in London](https://apify.com/redfoxscout/google-maps-leads-with-emails/examples/restaurant-emails-google-maps)
- [Find roofing contractors with emails in Dallas](https://apify.com/redfoxscout/google-maps-leads-with-emails/examples/contractors-leads-with-emails)
- [Get marketing agency emails in Dubai](https://apify.com/redfoxscout/google-maps-leads-with-emails/examples/marketing-agencies-emails)
- [Get gym and fitness studio emails in Sydney](https://apify.com/redfoxscout/google-maps-leads-with-emails/examples/gyms-emails-google-maps)

### People on team pages

With **People on team pages** on, each lead also gets `people` and `peopleCount`: the people the business's own website lists on its team, attorneys, leadership and about pages, with `name` and `title`, and `email`, `phone` or `linkedin` only when the page shows them next to that person. The team pages share the contact-page budget (`maxPagesPerSite`), and it adds nothing to the price. It is off by default, so existing runs are unchanged.

Real lead from `{ "searchQueries": ["law firms in Chicago"], "maxItems": 3, "includePeople": true }` (shortened to three people):

```json
{
  "name": "Ankin Law",
  "website": "https://ankinlaw.com/",
  "peopleCount": 21,
  "people": [
    { "name": "Howard H. Ankin", "title": "Partner", "email": null, "phone": null, "linkedin": null, "sourceUrl": "https://ankinlaw.com/attorneys/" },
    { "name": "Ian M. Zenziper", "title": "Managing Partner", "email": null, "phone": null, "linkedin": null, "sourceUrl": "https://ankinlaw.com/attorneys/" },
    { "name": "Telly J. Liapis", "title": "Partner", "email": null, "phone": null, "linkedin": null, "sourceUrl": "https://ankinlaw.com/attorneys/" }
  ]
}
```

Titles are copied as the page shows them. Some sites list no team page, and then `peopleCount` is 0.

### Emails you can send to

Lead lists fail when the addresses bounce. This Actor checks every email it finds before you see it:

- **Mail-server check (on by default):** each email's domain is looked up for mail servers (MX). Addresses on domains that cannot receive mail are dropped from `email` and `emails`; you still see them in `emailsChecked` with the reason (`no-mx`, `domain-not-found`).
- **Best address first:** the business's own domain beats free mail, sales@, info@ and contact@ beat named roles, no-reply and privacy addresses go last. `emailType` says which kind `email` is.
- **Proof:** `emailSources` names the page each email was on.
- **Phones in E.164** (`websitePhonesE164`) when the country is known, ready for dialers and WhatsApp.
- We check domains, not mailboxes: no SMTP probing of individual addresses.

A real row (dentists in Dubai Marina): `email` = `info@skyclinicjlt.com` (valid-mx), while `info@skyclinicdentalcenter.com`, also on the site, was dropped because that domain has no mail server.

### Every business in a city

A normal Google Maps search ends after ~120-250 places. Turn on **Cover the whole area** and the city (from Locations or "in <city>") is split into map tiles, busy tiles are split again, and every matching place is checked once. Duplicates are free. You can also start from a map point and radius, Google Maps URLs or place IDs.

### How much does it cost?

$3 per 1,000 leads, Maps data and website contacts included.

- 100 leads: about $0.30
- 10,000 leads: about $30
- Duplicates, failed searches and (with the email-only option) leads without an email: free

Apify's free plan gives $5 of credit every month, enough for about 1,600 leads.

### FAQ

**Is this legal?** It combines public Google Maps business listings with contact details that businesses publish on their own websites. You are responsible for how you contact them, including email marketing laws (CAN-SPAM, GDPR) in your market.

**What does this Actor not do?** It does not guess or look up personal emails of owners or staff, does not log in anywhere and does not read review texts. It returns the contact details, and the names and titles on team pages, that a business publishes on its own website.

**Why do some leads have no email?** Many small businesses only offer a contact form or a phone number. Turn on "Only leads with an email" to skip and not pay for those.

**How many leads per search?** Google shows up to about 140 places per search. Split big cities by neighborhood for more.

### Related Actors

- [Google Maps Scraper](https://apify.com/redfoxscout/google-maps-business-scraper): the same Maps data without the website visit, at $1 per 1,000 places.
- [Website Contact Extractor](https://apify.com/redfoxscout/website-contact-extractor): emails and socials for any list of websites.
- [Tech Stack Detector](https://apify.com/redfoxscout/tech-stack-detector): which technologies each business website runs on.

# Actor input Schema

## `searchQueries` (type: `array`):

Searches as you would type them in Google Maps, one per line, e.g. dentists in Dubai, or just dentists with a location below. Optional when you give Google Maps URLs or place IDs.

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

Cities or areas. Every search is run in every location (<search> in <location>).

## `searchWholeArea` (type: `boolean`):

Google Maps shows at most ~120 places per search. On: the area (location, "in <city>" or your map point) is split into map tiles, busy tiles are split again, and every matching place is returned once. Duplicates are free. Use with a higher max results.

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

Google Maps search URLs (maps/search/...@lat,lng,zoom), place URLs, ?cid= links or maps.app.goo.gl short links.

## `placeIds` (type: `array`):

Google place IDs such as ChIJ1S_Bov20RIYRe7MiR8tYawY. One row per place.

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

Deliver (and charge) only businesses where an email was found on their website.

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

On (default): each email's domain is checked for mail servers (MX). Addresses on domains that cannot receive mail are dropped from email and emails (still listed in emailsChecked), so the best sendable address comes first.

## `includePeople` (type: `boolean`):

Also list the people the business's website shows on its team, leadership and about pages: name, title, and the email, phone or LinkedIn shown beside them. Team pages count toward Contact pages per website. Off by default.

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

Language of names and categories, e.g. en, de, ar, fr.

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

Two-letter country code Google uses for regional results, e.g. us, gb, ae.

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

Search around a point instead of a named place, e.g. 25.2048. Use with longitude and radius.

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

e.g. 55.2708.

## `radiusKm` (type: `number`):

Size of the area around the map point. With 'Cover the whole area' every place inside it is returned.

## `skipClosedPlaces` (type: `boolean`):

Leave out places Google marks as permanently or temporarily closed.

## `categoryFilterWords` (type: `array`):

Keep a place only if one of its Google categories contains one of these words, e.g. dentist, orthodontist.

## `searchMatching` (type: `string`):

Useful for brand searches (e.g. Starbucks): drop places Google adds that are not that business.

## `minRating` (type: `integer`):

Skip places rated below this.

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

Skip places with fewer reviews.

## `skipWithoutPhone` (type: `boolean`):

Skip places that list no phone.

## `maxPagesPerSite` (type: `integer`):

Besides the home page, how many contact, about or imprint pages to check on each website.

## `maxItems` (type: `integer`):

Stop each search after this many leads. A normal search ends at ~120 places; with Cover the whole area use hundreds or thousands.

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

How many searches run at once.

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

Off by default and usually not needed. Turn on for very large sweeps if Google starts rate-limiting.

## Actor input object example

```json
{
  "searchQueries": [
    "dentists in Austin TX"
  ],
  "searchWholeArea": false,
  "onlyWithEmail": false,
  "checkEmailDomains": true,
  "includePeople": false,
  "language": "en",
  "countryCode": "us",
  "radiusKm": 5,
  "skipClosedPlaces": false,
  "searchMatching": "all",
  "skipWithoutPhone": false,
  "maxPagesPerSite": 3,
  "maxItems": 40,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchQueries": [
        "dentists in Austin TX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("redfoxscout/google-maps-leads-with-emails").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 = { "searchQueries": ["dentists in Austin TX"] }

# Run the Actor and wait for it to finish
run = client.actor("redfoxscout/google-maps-leads-with-emails").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 '{
  "searchQueries": [
    "dentists in Austin TX"
  ]
}' |
apify call redfoxscout/google-maps-leads-with-emails --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,redfoxscout/google-maps-leads-with-emails"
        }
    }
}
```

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/SB555auGkWFJFOrrB/builds/3xbI8cDhLn2sdgzWb/openapi.json
