# Google Maps Email Extractor (Leads with Emails & Socials) (`juliob.rangel/google-maps-email-extractor`) Actor

Search Google Maps for any business type and city, then visit each business website to add emails and LinkedIn, Facebook, Instagram, X, YouTube, TikTok and WhatsApp links. Name, phone, website, address, rating and reviews included. Export to Excel, CSV or JSON.

- **URL**: https://apify.com/juliob.rangel/google-maps-email-extractor.md
- **Developed by:** [Julio Barcellos Rangel](https://apify.com/juliob.rangel) (community)
- **Categories:** Lead generation, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 place 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

## Google Maps Email Extractor (Leads with Emails & Socials)

This Google Maps email extractor turns a Google Maps search into a lead list: it finds the businesses for your search terms and city, then visits each business website to add emails and LinkedIn, Facebook, Instagram, X, YouTube, TikTok and WhatsApp links. It is made for sales teams, agencies and marketers who prospect local businesses. Use it as a Google Maps lead scraper or to get emails from Google Maps businesses, with name, phone, website, address, rating and reviews in the same row, ready to export to Excel or CSV.

### What does Google Maps Email Extractor do?

The robot works in two steps for every search:

1. **Google Maps search.** It runs the same list search Google Maps runs when you type a query and reads the places 20 at a time. With the term `dentist` and the location `Austin, TX`, it searches for `dentist in Austin, TX` (with Portuguese as the language it uses `em`: `academia em Florianópolis`). Each place comes with name, categories, rating, review count, phones, website, full address, coordinates, opening status, place ID and a Google Maps link.
2. **Website visit.** For each place that has a website, it loads the home page and the pages that look like contact pages on the same site (URLs with words such as `contact`, `about`, `team`, `impressum`, `support`, `contato` or `sobre`), up to **Max pages per website**. From those pages it collects emails (including simple obfuscation like `name [at] domain [dot] com`), phone numbers from click-to-call links and links to social profiles. Emails on the business's own domain come first.

You give it search terms, an optional location, how many places you want per search, how many pages to read on each website, and the language and country of the search. A place found by more than one search term is returned only once.

What comes out is one row per business with all the Google Maps data plus `emails`, `websitePhones`, seven social profile fields and `websiteCrawled`, which tells you whether the website could be read.

### What data can you extract?

| Field | What it means | Example |
|---|---|---|
| `searchTerm` | Full query sent to Google Maps (term plus location) | `dentist in Austin, TX` |
| `position` | Rank of the place in the results for that query, starting at 1 | `1` |
| `name` | Business name | `Emergency Dentist of Austin` |
| `category` | Main category | `Dentist` |
| `categories` | All categories shown on Google Maps | `["Dentist", "Cosmetic dentist", "Dental clinic"]` |
| `rating` | Average star rating | `4.8` |
| `reviewsCount` | Number of reviews | `90` |
| `phone` | Phone in local format, from Google Maps | `(512) 961-6200` |
| `phoneInternational` | Phone in international format, from Google Maps | `+1 512-961-6200` |
| `website` | Business website listed on Google Maps | `https://emergencydentistofaustin.com/` |
| `address` | Full address | `1030 Norwood Park Blvd #324, Austin, TX 78753` |
| `street` | Street and number | `1030 Norwood Park Blvd #324` |
| `neighborhood` | Neighborhood | `Heritage Hills` |
| `city` | City | `Austin` |
| `state` | State or region | `Texas` |
| `postalCode` | Postal or ZIP code | `78753` |
| `countryCode` | Two-letter country code | `US` |
| `latitude` | Latitude | `30.3406789` |
| `longitude` | Longitude | `-97.6924276` |
| `openingStatus` | Open or closed at the time of the run, in the search language | `Open · Closes 8 PM` |
| `description` | Short Google description, when there is one | `null` |
| `timezone` | Time zone of the place | `America/Chicago` |
| `placeId` | Google place ID | `ChIJpXb4FgrJRIYRyRpdhSsCHHk` |
| `cid` | Google CID (customer ID) of the place | `13243667843430391418` |
| `googleMapsUrl` | Link that opens the place on Google Maps | `https://www.google.com/maps/place/?q=place_id:ChIJpXb4FgrJRIYRyRpdhSsCHHk` |
| `thumbnail` | URL of the place's main photo, small size | `https://lh3.googleusercontent.com/…` |
| `emails` | Emails found on the website, own-domain addresses first | `["info@emergencydentistofaustin.com"]` |
| `websitePhones` | Phone numbers from click-to-call links on the website, digits only | `["5129616200", "+15129616200"]` |
| `linkedIn` | LinkedIn links found on the website | `["https://www.linkedin.com/company/38th-street-dental"]` |
| `facebook` | Facebook links found on the website | `["https://www.facebook.com/emergencydentistofaustin"]` |
| `instagram` | Instagram links found on the website | `["https://www.instagram.com/atxfamilydental"]` |
| `twitter` | X (Twitter) links found on the website, as `x.com` | `["https://x.com/yogaeastaustin"]` |
| `youtube` | YouTube channel links found on the website | `["https://www.youtube.com/@breezeoralcare"]` |
| `tiktok` | TikTok links found on the website | `["https://www.tiktok.com/@swishdental"]` |
| `whatsapp` | WhatsApp links found on the website | `["https://api.whatsapp.com/send?…"]` |
| `websiteCrawled` | `true` when at least one page of the website was read | `true` |
| `scrapedAt` | When the row was collected (UTC) | `2026-10-10T20:28:13.418Z` |
| `error` | Only on error rows: what went wrong | `No places found` |

Google Maps fields that a place does not have come back as `null`. Contact fields are always lists, empty (`[]`) when nothing was found or the place has no website.

### How to use Google Maps Email Extractor

1. Open the robot in Apify Console and go to the **Input** tab.
2. Add one or more **Search terms**, one per line, for example `dentist`, `real estate agency` or `yoga studio`.
3. Type a **Location** such as `Austin, TX`, `Lisbon` or `Curitiba`, or leave it empty if each term already says where.
4. Set **Max places per search** and **Max pages per website**.
5. Set **Language** and **Country**, for example `pt-BR` and `br` for Brazil.
6. Click **Start** and wait for the run to finish. Visiting websites takes longer than a plain Google Maps search.
7. Open the **Output** tab to see the Leads table, then export the data as JSON, CSV, Excel or HTML.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `searchTerms` | array of strings (required) | `["dentist"]` | What you would type in Google Maps. One search per entry; repeated terms are removed. |
| `location` | string | empty (the form shows `Austin, TX` as an example) | City, region or neighborhood added to every search term. Leave it empty if the place is already in the terms. |
| `maxPlacesPerSearch` | integer | `20` | Places per search, from 1 to 500. Google shows about 120 per search. |
| `maxPagesPerWebsite` | integer | `3` | Pages read on each business website, from 1 to 10 (home, contact, about…). |
| `language` | string | `en` | Language of the search, categories and opening status, e.g. `en`, `pt-BR`, `es`, `de`, `fr`. |
| `country` | string | `us` | Two-letter country code Google uses for the search, e.g. `us`, `br`, `gb`, `de`. |
| `proxy` | object | `{"useApifyProxy": true}` | Apify Proxy settings, used for Google Maps and for the website visits. |

Example input:

```json
{
  "searchTerms": ["dentist", "yoga studio"],
  "location": "Austin, TX",
  "maxPlacesPerSearch": 50,
  "maxPagesPerWebsite": 3,
  "language": "en",
  "country": "us",
  "proxy": { "useApifyProxy": true }
}
```

### Output example

One real row from the latest run (20 dentists in Austin, TX). The thumbnail URL is shortened.

```json
{
  "searchTerm": "dentist in Austin, TX",
  "position": 1,
  "name": "Emergency Dentist of Austin",
  "category": "Dentist",
  "categories": ["Dentist", "Cosmetic dentist", "Dental clinic", "Dental hygienist", "Emergency dental service", "Endodontist", "Medical Center", "Oral surgeon", "Orthodontist", "Periodontist"],
  "rating": 4.8,
  "reviewsCount": 90,
  "phone": "(512) 961-6200",
  "phoneInternational": "+1 512-961-6200",
  "website": "https://emergencydentistofaustin.com/",
  "address": "1030 Norwood Park Blvd #324, Austin, TX 78753",
  "street": "1030 Norwood Park Blvd #324",
  "neighborhood": "Heritage Hills",
  "city": "Austin",
  "state": "Texas",
  "postalCode": "78753",
  "countryCode": "US",
  "latitude": 30.3406789,
  "longitude": -97.6924276,
  "openingStatus": "Open · Closes 8 PM",
  "description": null,
  "timezone": "America/Chicago",
  "placeId": "ChIJpXb4FgrJRIYRyRpdhSsCHHk",
  "cid": "13243667843430391418",
  "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJpXb4FgrJRIYRyRpdhSsCHHk",
  "thumbnail": "https://lh3.googleusercontent.com/grass-cs/AABkmLfPUZ9K3kTbn8Qc3qWn2gCmSMBZR80MdIc3Vwlusx8L4ZqO5ELcPYkpb5YvU0CgodO83LfkrrQNFvNFucR9ZOJ3w4vCAnFt…=w86-h114-k-no",
  "emails": ["info@emergencydentistofaustin.com"],
  "websitePhones": ["5129616200", "+15129616200"],
  "linkedIn": [],
  "facebook": ["https://www.facebook.com/emergencydentistofaustin"],
  "instagram": [],
  "twitter": [],
  "youtube": [],
  "tiktok": [],
  "whatsapp": [],
  "websiteCrawled": true,
  "scrapedAt": "2026-10-10T20:28:13.418Z"
}
```

Not every business publishes an email. In that latest run, 18 of the 20 websites could be read and 9 businesses had at least one email.

### How much does it cost?

The robot uses **pay per event** pricing with two events. Platform usage is included in the price, so there is no separate charge for compute or proxy.

- **Place scraped:** $2.00 per 1,000 places ($0.002 each), for every business row returned.
- **Website contacts:** $2.00 per 1,000 websites ($0.002 each), only when the business has a website and at least one page of it loads (`websiteCrawled` is `true`).

| Apify plan | Per 1,000 places | Per 1,000 websites read |
|---|---|---|
| Free | $2.00 | $2.00 |
| Bronze (10% off) | $1.80 | $1.80 |
| Silver (20% off) | $1.60 | $1.60 |
| Gold and higher (30% off) | $1.40 | $1.40 |

Worked examples on the Free plan:

- The latest run: 20 places and 18 websites read = $0.040 + $0.036 = about **$0.08**.
- 1,000 places where 850 websites load = $2.00 + $1.70 = **$3.70**.
- 10,000 places, all with working websites = $20.00 + $20.00 = **$40.00** (or $28.00 on Gold).

What is **not** charged: error rows (`No places found`, `Google Maps did not respond, try again later`), places skipped as duplicates, and the website event when a place has no website, when its website does not load, or when the visit runs out of time. A website that loads is charged even if no email was found on it. The number of pages per website does not change the price.

### Use cases

- **Cold email lists for local businesses:** dentists, lawyers, gyms or restaurants in a city, with email, phone and website in one row.
- **Agency prospecting:** find businesses with a weak online presence, for example a low review count or no social profiles on their site.
- **Social media outreach:** collect the Instagram, Facebook and TikTok accounts of local businesses.
- **WhatsApp-first markets:** find businesses that link a WhatsApp chat on their website.
- **CRM enrichment:** refresh phones, websites and emails of the businesses you already work with.
- **Market research:** count and compare businesses in each neighborhood, with ratings and review counts.
- **Franchise and distributor search:** list shops of one type in many cities with their contact details.

### Tips and limits

- **About 120 places per search.** That is what Google Maps shows for one query. For a whole city, run one search per neighborhood or ZIP code; places found twice are returned once.
- **Location is optional.** From the API, `location` stays empty unless you send it, so a term like `plumber in Miami` is searched exactly as typed. In the Console form it comes pre-filled with `Austin, TX` as an example; clear it if your terms already say where.
- **45 seconds per website.** A slow website is cut off so it does not hold up the run; each page has a 12-second timeout and is tried up to 2 times. If nothing loaded, `websiteCrawled` is `false` and the contact lists are empty.
- **Same website only.** Only pages on the business's own host are read, without running JavaScript, so contacts that only appear in a browser can be missed.
- **Phones from the website come from click-to-call links only.** The Google Maps phone is always in `phone` and `phoneInternational`.
- **Review the social links.** Every matching link on the pages is kept, so a list can include a share button (for example a WhatsApp share link with no phone number) or a personal profile.
- **Emails are collected, not verified.** Run them through an email verification tool before a campaign.
- **No review texts.** You get `rating` and `reviewsCount` only.

### Use it from the API, Python or JavaScript

JavaScript (Node.js) with the official `apify-client` package:

```javascript
const { ApifyClient } = require('apify-client');

const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const input = { searchTerms: ['real estate agency'], location: 'Lisbon', maxPlacesPerSearch: 60, maxPagesPerWebsite: 3 };
const run = await client.actor('juliob.rangel/google-maps-email-extractor').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.filter((x) => x.emails && x.emails.length));
```

Python with the official `apify-client` package:

```python
from apify_client import ApifyClient

client = ApifyClient('YOUR_TOKEN')
input = {'searchTerms': ['academia'], 'location': 'Curitiba', 'language': 'pt-BR', 'country': 'br'}
run = client.actor('juliob.rangel/google-maps-email-extractor').call(run_input=input)
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

You can also connect the robot to Make, Zapier or n8n, export results to Google Sheets, send them to a webhook when a run finishes, or let AI agents call it through the Apify MCP server.

### FAQ

**Do I need a Google account, cookies or a Google Maps API key?**
No. The robot reads public Google Maps results and public business websites. You only need an Apify account.

**Can I export the leads to Excel or CSV?**
Yes. Download the dataset as JSON, CSV, Excel or HTML from the Output tab, or read it through the API.

**How many leads can I get?**
About 120 places per search, because that is what Google Maps shows. Add more search terms or split the city into neighborhoods or ZIP codes to get more.

**Why do some businesses have no email?**
Many businesses do not publish an email on their website, use only a contact form, or show it in a way the robot cannot read. When the website does not load, `websiteCrawled` is `false` and you are not charged for the website visit.

**What is the difference with Google Maps Scraper?**
Google Maps Scraper returns only the Google Maps data and is charged per place. This robot also visits each website for emails and social profiles, which adds the website event.

**Why did I get an error row?**
`No places found` means Google returned nothing for that query. `Google Maps did not respond, try again later` means the first result page could not be loaded after several tries. Error rows are free.

**Is it legal to collect emails from Google Maps businesses?**
The robot only collects publicly available data. You are responsible for complying with Google's terms, with privacy laws such as GDPR and LGPD, and with anti-spam laws such as CAN-SPAM. Some businesses are run by individuals under their own name, and personal data needs a legitimate reason to be processed.

### Related scrapers

- [Google Maps Scraper (Places, Phones, Websites, Ratings)](https://apify.com/juliob.rangel/google-maps-places-scraper-fast) when you only need the Google Maps data.
- [Website Contact Details Scraper (Emails, Phones, Socials)](https://apify.com/juliob.rangel/website-contact-details-scraper) to get contacts from any list of websites.
- [LinkedIn Company Scraper (No Login, Fast)](https://apify.com/juliob.rangel/linkedin-company-fast) to add company details from the LinkedIn links you found.
- [Instagram Profile Stats Scraper (Followers, Bio, Posts)](https://apify.com/juliob.rangel/instagram-profile-stats) to check the followers of the Instagram accounts you found.

***

## Extrator de E-mails do Google Maps (PT-BR)

Pesquise negócios no Google Maps por tipo e cidade e receba uma lista de contatos: nome, telefone, site, endereço, nota e, visitando o site de cada empresa, e-mails e redes sociais (Instagram, Facebook, LinkedIn, WhatsApp). Use idioma `pt-BR` e país `br`.

# Actor input Schema

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

What you would type in Google Maps, e.g. "dentist", "coffee shop", "plumber in Miami". One search per line.

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

City, region or neighborhood added to every search term, e.g. "Austin, TX" or "Curitiba". Leave empty if the location is already in the search terms.

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

Google Maps shows up to about 120 places per search. For more, split by neighborhood or zip code.

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

Pages visited on each business website to find emails (home, contact, about...).

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

Language of categories and opening hours, e.g. en, pt-BR, es, de, fr.

## `country` (type: `string`):

Two-letter country code that Google uses for the search, e.g. us, br, gb, de.

## `proxy` (type: `object`):

Apify Proxy settings.

## Actor input object example

```json
{
  "searchTerms": [
    "dentist"
  ],
  "location": "Austin, TX",
  "maxPlacesPerSearch": 20,
  "maxPagesPerWebsite": 3,
  "language": "en",
  "country": "us",
  "proxy": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "searchTerms": [
        "dentist"
    ],
    "location": "Austin, TX",
    "maxPlacesPerSearch": 20,
    "maxPagesPerWebsite": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("juliob.rangel/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"],
    "location": "Austin, TX",
    "maxPlacesPerSearch": 20,
    "maxPagesPerWebsite": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("juliob.rangel/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"
  ],
  "location": "Austin, TX",
  "maxPlacesPerSearch": 20,
  "maxPagesPerWebsite": 3
}' |
apify call juliob.rangel/google-maps-email-extractor --silent --output-dataset

```

## MCP server setup

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