# Google Maps Lead Scraper: Emails, Phones & Socials (`vaunted/google-maps-lead-scraper`) Actor

Extract emails, phones, social profiles, reviews, and photos from any business on Google Maps. Fast engine with deep email discovery beyond the homepage. Per-result billing - you only pay when an email, social, or review is actually delivered.

- **URL**: https://apify.com/vaunted/google-maps-lead-scraper.md
- **Developed by:** [Sage](https://apify.com/vaunted) (community)
- **Categories:** Lead generation, Social media, SEO tools
- **Features:** Limited permissions
- **Stats:** 59 total users, 6 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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 Lead Scraper is a **Google Maps email extractor** and lead generation tool. It pulls **business emails, phone numbers and social profiles** from Google Maps at scale, without a Google Maps API key. Give it a search term and a location — `dentist` in `Miami, FL` — and it returns a clean, export-ready list of local businesses with the contact details you need for outreach.

It runs on pure HTTP with no browser, so runs are fast and cheap, and you are billed per result delivered rather than per hour of compute.

### What data can you extract from Google Maps?

| Field | Notes |
|---|---|
| **Business name** | As listed on Google Maps |
| **Category & categories** | Primary category plus every secondary category Google assigns |
| **Emails** | Found on the business website — homepage, contact, about and team pages |
| **Phone** | From the Google listing |
| **Extra phones** | Additional numbers found on the business website |
| **Website** | Cleaned of UTM tracking parameters |
| **Social profiles** | Facebook, Instagram, LinkedIn, X (Twitter), YouTube, TikTok, Pinterest |
| **Address** | Full formatted address |
| **Coordinates** | Latitude and longitude |
| **Star rating** | The rating shown on the listing |
| **Review count** | Total number of reviews |
| **Opening hours** | Per-day open and close times, where Google publishes them |
| **Price level** | $ to $$$$, where Google shows one |
| **Reviews** | Review text, star rating, author, profile link and publish date (optional add-on) |
| **Photos** | Photo URLs from the listing (optional add-on) |
| **Status flags** | Permanently closed, temporarily closed |
| **Google Maps URL & Place ID** | Deep link plus Google's unique place identifier |
| **Run metadata** | Which search query and location produced each row, and when |

### How to extract emails from Google Maps

1. **Enter search queries.** Business types such as `dentist`, `plumber`, `coffee shop`, `real estate agent`.
2. **Enter locations.** Cities, regions or countries: `Miami, FL`, `London, UK`, `Tokyo, Japan`. Every query runs against every location, so three queries across two locations is six searches.
3. *(Optional)* **Paste Google Maps URLs** instead of typing a query. Search URLs and place URLs both work, and any `/@lat,lng,zoom` coordinates in the URL are used as the search area.
4. *(Optional)* **Set filters.** Only businesses with a website, only those that yielded an email, a minimum star rating, specific categories, or skip permanently closed places.
5. *(Optional)* **Turn on add-ons.** Set **Max Reviews Per Place** to pull recent reviews (sorted by most relevant, newest, highest or lowest rating), and **Max Photos Per Place** for photo URLs. Both are off by default and billed per item delivered.
6. **Click Start.** Results stream into the dataset as each business finishes, so you can watch leads land instead of waiting for the whole run.
7. **Export.** CSV, Excel, JSON, or straight into Google Sheets.

#### Getting a higher email hit rate

Keep **Deep Email Search** on. Many businesses publish an email only on their contact or about page, never the homepage. Pair it with **Website Availability → Only with website**: a business with no website has no page to extract an email from, so filtering those out first spends your budget where it can actually pay off.

Be specific with locations. `plumber` in `Brooklyn, NY` returns a denser, more useful list than `plumber` in `New York`, and splitting a metro area into neighbourhoods or ZIP codes covers far more ground than one broad search.

### How much does it cost to scrape Google Maps?

You pay per event delivered, not for run time. On the Free tier:

| Event | Price | When you are charged |
|---|---|---|
| Place scraped | $0.0035 | Per business delivered to the dataset |
| Email found | $0.0048 | Per business where at least one email was found |
| Social profile found | $0.0009 | Per business where at least one social profile was found |
| Review scraped | $0.00049 | Per review delivered, only when reviews are enabled |
| Photo scraped | $0.00049 | Per photo URL, only when photos are enabled |
| Actor start | $0.00005 | Per GB of memory, once per run |

Prices drop on higher Apify plans.

**A realistic 1,000-place run.** At a typical 25% email hit rate and 30% social hit rate, with reviews and photos off:

- 1,000 places × $0.0035 = **$3.50**
- 250 emails × $0.0048 = **$1.20**
- 300 socials × $0.0009 = **$0.27**

**Total ≈ $4.97 for 1,000 businesses**, around half a cent per lead. You are never charged for a business where no email was found, so a low-yield niche costs less rather than more.

The 25% figure is not pessimism — most Google Maps listings have no email on them at all, and the address has to be found on the linked website instead. Industry write-ups generally put the achievable rate at 15–25%; runs during testing landed between 22% and 28% depending on the niche. Dense professional categories such as dentists and law firms do considerably better than retail.

To cap spending on a run, set **Maximum cost per run** in the Apify UI. The scraper checks the remaining budget before delivering each batch and stops cleanly when it runs out, so it never overshoots the limit you set.

### Input example

```json
{
    "searchQueries": ["dentist", "orthodontist"],
    "locations": ["Los Angeles, CA", "San Francisco, CA"],
    "country": "us",
    "maxResultsPerSearch": 200,
    "onlyWithEmails": true,
    "onlyWithWebsite": "withWebsite",
    "deepSearch": true,
    "maxPagesPerSite": 3
}
```

This pulls dentists and orthodontists across two California cities, keeps only businesses that have a website and yielded at least one email, and scans up to three pages per site.

### Output example

```json
{
    "name": "Pitt Street Dental Centre",
    "category": "Dentist",
    "categories": ["Dentist", "Cosmetic dentist", "Orthodontist"],
    "rating": 4.9,
    "reviewCount": 549,
    "address": "Pitt Street, Sydney, NSW, AU, 2000",
    "phone": "+61-2-92334399",
    "emails": ["info@pittstdentalcentre.com.au"],
    "emailCount": 1,
    "website": "https://pittstdentalcentre.com.au/",
    "facebook": "https://www.facebook.com/PittStDentalCentre",
    "instagram": "https://www.instagram.com/pittstdentalcentre",
    "latitude": -33.8661351,
    "longitude": 151.208973,
    "openingHours": [{ "day": "Monday", "hours": "08:00-17:00" }],
    "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:...",
    "placeId": "/g/11c1b5_example",
    "searchQuery": "dentist",
    "searchLocation": "Sydney, Australia",
    "scrapedAt": "2026-09-12T13:35:59.000Z"
}
```

### Filtering and targeting options

- **Only with emails** — drop every business that did not yield an email, so the export is outreach-ready.
- **Website availability** — only businesses with a website, or only those without.
- **Minimum star rating** — drop low-rated businesses. Unrated places are excluded once you set a threshold above 0.
- **Category filter** — restrict to specific Google categories. `restaurant` matches `Italian restaurant`, `Chinese restaurant`, and so on.
- **Skip permanently closed** — exclude closed and temporarily closed listings.
- **Geolocation fields** — country, state/province, city and postal code, for when a place name alone is ambiguous.
- **Results language** — affects category and description text, not contact details.

### Why use this instead of the Google Maps API?

The official Places API requires a billing-enabled Google Cloud project, caps how many results a single search returns, and does not give you the business's email address at all — that lives on the company website, not in Google's data. This scraper needs no API key, no Google account, and returns the contact details the API never exposes.

It also runs without a browser. Most Google Maps scrapers drive a headless Chrome instance, which is slow and memory-hungry; this one talks to the same HTTP endpoints Google Maps itself calls, which is why a 120-business run with contact enrichment finishes in under three minutes on 2 GB of memory.

### Integrations and automation

Because it runs on Apify, you get the platform around it for free: schedule runs, trigger them via API, monitor them, and push results straight into Make, Zapier, Google Sheets, Slack, Airtable, or your own webhook. Every run's dataset is available over a REST API in JSON, CSV, Excel and XML.

### FAQ

#### Is it legal to scrape Google Maps?

The scraper collects publicly available business information — the same listing data any visitor can see without logging in. Business contact details are not personal data in most jurisdictions, but you are responsible for how you use the output. If you send marketing email, follow the rules that apply to you, such as GDPR in the EU and CAN-SPAM in the US.

#### Are the emails verified?

No. Every address is validated structurally — correct format, real TLD, and a filter that removes placeholder addresses, template defaults, image filenames and other false positives. There is no mailbox check, so an address here is genuinely published by the business rather than proven deliverable. Run the export through a dedicated verification service before a large campaign.

#### Why do some businesses have no email?

Many local businesses never publish one. They take enquiries through a contact form, a phone number, or social DMs. The scraper finds what is actually on the public web, and you are not charged for a business where nothing was found.

#### Can I extract Google Maps reviews too?

Yes. Set **Max Reviews Per Place** above 0 and each business comes back with its recent reviews — text, star rating, author name and profile link, publish date and the language the review was written in. Choose the order with **Reviews Sort**: most relevant, newest, highest rating or lowest rating. Reviews are billed per review delivered, so leave it at 0 when you only want contact data.

#### Can I scrape Google Maps outside the US?

Yes, anywhere Google Maps operates. Enter any city or country in **Locations**, or use the **Country** dropdown, which covers 60+ countries. Results in the southern hemisphere, Europe and Asia are all supported, with correct coordinates.

#### How many results can I get per search?

Up to 500 per query-and-location pair. Google itself typically surfaces 20–120 results for a given search depending on how dense the area is, so splitting a large city into neighbourhoods or postal codes returns far more total businesses than raising the limit on one broad search.

#### Will my IP be blocked?

No. Runs go through Apify's residential proxy network by default and your own IP is never used.

#### How do I export Google Maps leads to CSV or Excel?

Every run's results land in a dataset you can download as CSV, Excel, JSON or XML in one click, or pull over the Apify API. There is also a direct Google Sheets integration if you would rather the leads appear in a sheet automatically.

#### How do I get the data into my CRM?

Export as CSV or JSON and import into HubSpot, Salesforce, Pipedrive or similar, or wire the run to your CRM directly with an Apify integration or webhook.

### Other Actors by this developer

| Actor | What it does |
|---|---|
| [Airtable Workspace Provisioner](https://apify.com/vaunted/airtable-workspace-provisioner) | Build out an Airtable base from a schema — a natural place to land the leads this scraper produces |
| [iHerb Scraper](https://apify.com/vaunted/iherb-scraper) | Search, products, reviews and price monitoring for iHerb |
| [Textbook Arbitrage](https://apify.com/vaunted/textbook-arbitrage) | Compare textbook buy and sell prices across marketplaces |

### Support

Found a bug, or need a field that isn't here? Open an issue on the Actor's **Issues** tab in Apify Console. Custom variations of this scraper are possible on request.

# Changelog

This Actor's version history is a separate document: https://apify.com/vaunted/google-maps-lead-scraper/changelog.md

# Actor input Schema

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

What types of businesses are you looking for? Enter keywords like 'dentist', 'restaurant', 'plumber', etc. Each query runs against every location you specify.

Use distinct terms for best results. Similar terms (e.g., 'bar' vs 'pub') may slightly increase capture rate but are less efficient.

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

Paste Google Maps URLs to replicate a search you already have open. Supported formats:
• google.com/maps/search/restaurants/@40.7,-74.0,13z
• google.com/maps/place/Business+Name/...
• maps.google.com/maps?q=dentist+miami

Each URL is self-contained and is <b>not</b> combined with the Locations field. If the URL carries /@lat,lng coordinates they set the search area; otherwise the URL's own text is searched as-is, so include the place in it (for example <code>dentist+miami</code>). To run one query across several cities, use Search Queries and Locations instead.

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

Where should we search? Enter cities, areas, or regions. Each search query runs against every location listed here.

Works worldwide — 'Miami, FL', 'London, UK', 'Tokyo, Japan', etc.

For precise results, use 'City, Country' format.

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

Narrow results to a specific country. Helps when your location text is ambiguous (e.g., 'Portland' exists in both Oregon and Maine).

## `state` (type: `string`):

Optionally set a state or province for tighter results (e.g., 'California', 'Ontario', 'Bavaria'). Mainly useful for US, Canada, and Australia.

## `city` (type: `string`):

Enter a city name for area targeting. Use this instead of or alongside the Locations field for more precise definition.

Do not include state or country names here — use the separate fields.

## `postalCode` (type: `string`):

Target a specific postal code area. Combine with Country for best results. Only one postal code per run.

Use with Country, not with City.

## `maxResultsPerSearch` (type: `integer`):

How many businesses to find per search query + location combination. Default is conservative for quick runs — bump it up (to 100, 200, or the 500 max) for larger lead-gen jobs. Google Maps typically returns 20–120 results depending on the area and business type; smaller or more niche markets may have fewer.

## `onlyWithEmails` (type: `boolean`):

Only include businesses where at least one email was found. Keeps your export clean and ready for outreach.

## `onlyWithWebsite` (type: `string`):

Filter businesses by whether they have a website listed on Google Maps. 'With website' is recommended for email extraction since businesses without websites won't have extractable emails.

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

Only include places matching these Google Maps categories. Leave empty to include all.

Google Maps has thousands of categories. Be broad — 'restaurant' will match 'Chinese restaurant', 'Italian restaurant', etc.

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

Only include businesses rated this high or above. Set to 0 to include all. Places without reviews are included unless this is set above 0.

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

Exclude businesses marked as temporarily or permanently closed on Google Maps.

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

Scan beyond the homepage for emails. Many businesses only list their email on the Contact or About page. Keep this ON for the best hit rate.

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

How many pages to scan per business website (the homepage is always included). Higher = more thorough, slightly slower. Default 3 covers homepage + contact + about pages, which catches the vast majority of emails.

## `extractSocials` (type: `boolean`):

Find Facebook, Instagram, LinkedIn, Twitter/X, YouTube, TikTok, and Pinterest profiles from business websites.

## `maxReviewsPerPlace` (type: `integer`):

How many recent reviews to extract per business. Set to 0 to skip reviews (default — keeps cost down). Each review delivered is billed.

## `reviewsSort` (type: `string`):

How to sort reviews when fetching. Ignored if Max Reviews Per Place is 0.

## `maxPhotosPerPlace` (type: `integer`):

How many photo URLs to extract per business. Set to 0 to skip photos (default). Each photo delivered is billed.

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

Language for Google Maps results. Affects business descriptions and categories — emails and contact info are not affected.

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

Proxy settings. Residential proxies are pre-configured and recommended — no changes needed for most users.

## Actor input object example

```json
{
  "searchQueries": [
    "dentist",
    "plumber",
    "real estate agent"
  ],
  "startUrls": [],
  "locations": [
    "Los Angeles, CA",
    "Chicago, IL",
    "Houston, TX"
  ],
  "country": "",
  "state": "",
  "city": "",
  "postalCode": "",
  "maxResultsPerSearch": 20,
  "onlyWithEmails": false,
  "onlyWithWebsite": "all",
  "categoryFilter": [],
  "minRating": 0,
  "skipClosedPlaces": true,
  "deepSearch": true,
  "maxPagesPerSite": 3,
  "extractSocials": true,
  "maxReviewsPerPlace": 0,
  "reviewsSort": "newest",
  "maxPhotosPerPlace": 0,
  "language": "en",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All businesses found with their emails, phones, social profiles, and Google Maps data. Each item represents one business listing.

# 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": [
        "restaurant"
    ],
    "startUrls": [],
    "locations": [
        "New York, NY"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("vaunted/google-maps-lead-scraper").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": ["restaurant"],
    "startUrls": [],
    "locations": ["New York, NY"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("vaunted/google-maps-lead-scraper").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": [
    "restaurant"
  ],
  "startUrls": [],
  "locations": [
    "New York, NY"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call vaunted/google-maps-lead-scraper --silent --output-dataset

```

## MCP server setup

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

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/bSE91kiVwGmivtVen/builds/tdpXTVTs9c0a1yqW6/openapi.json
