# Google Maps Lead Scraper: Email, Phone number, Fast & Lean (`code-node-tools/google-maps-lead-scraper`) Actor

Fast Google Maps lead scraper. Searches Google Maps for businesses matching your queries, fetches full contact details (website, phone, email, socials), and streams leads to the dataset. Uses Apify residential proxy on the platform and direct connection locally.

- **URL**: https://apify.com/code-node-tools/google-maps-lead-scraper.md
- **Developed by:** [CodeNodeTools](https://apify.com/code-node-tools) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 5 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 results

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

A fast, lightweight **Google Maps lead scraper** that turns any search query — "plumbers in Chicago", "dentists in Berlin", "coffee shops in Amsterdam" — into a clean list of business leads with **email, phone number, website, rating, and social links**. No browser, no database, no reviews scraping. Just HTTP requests, streamed straight to your dataset as they're found.

If you've been searching for **lead generation tools** — a **Google Maps extractor** that's actually fast, or a straightforward answer to **how to get leads from Google Maps** without paying for a bloated browser-automation tool — this Actor is built for exactly that job.

### What is this Google Maps Lead Scraper?

This Actor is a **Google Maps lead extractor**: give it one or more search queries, and it searches Google Maps, opens each result's business listing, and pulls out everything you'd normally have to copy-paste by hand — name, address, phone number, website, star rating, business status, and (when available) a contact email and social links.

It's built for **local lead generation, sales prospecting, and market research** — not for scraping reviews or building a directory site. That focus is what keeps it fast: no browser rendering, no unnecessary pages, no reviews pagination. Just the request-based endpoints Google Maps itself uses, called directly.

#### How to get leads from Google Maps in 3 steps

1. **Add your search queries.** Type in what you're looking for and where — e.g. `"roofing contractors in Austin"`, `"hair salons in Manchester"`. Add as many queries as you want; each one is scraped independently with its own results budget.
2. **Set your filters (optional).** Cap results per keyword, filter by star rating range, business status (operational / temporarily closed / permanently closed), and choose whether to drop leads with no way to contact them.
3. **Run the Actor.** Leads stream into your Apify dataset in real time as they're scraped — export to CSV, JSON, Excel, or Google Sheets, or pull them via the API into your CRM.

### What data can this Google Maps lead extractor collect?

For every business, you get:

- **Contact info**: phone number, email (extracted from the business's own website when Google Maps doesn't already list one), and social media links
- **Identity**: business name, category/type, Google Maps place ID
- **Location**: full address, latitude/longitude
- **Trust signals**: star rating, review count, business status (open, temporarily closed, permanently closed)
- **Web presence**: website URL

This makes it a genuinely useful **Google Maps leads finder** for agencies, freelancers, and sales teams who need a targeted list of local businesses to reach out to — not just a scrape of everything Google Maps happens to know.

### Why use this Google Map lead generator

- ⚡ **Fast** — no browser, no page rendering. Pure HTTP requests to Google Maps' own search and place-detail endpoints, run with several workers in parallel.
- 📮 **Built for outreach** — email extraction and a "drop leads with no contact info" filter mean your dataset is ready for a cold email or calling campaign, not full of dead-end listings.
- 🎯 **Precise filtering** — star rating range, business status, and per-keyword result caps, so you only pay for and store leads that actually match your criteria.
- 🌱 **Genuinely lean on bandwidth** — this matters more than it sounds. A typical browser-based Google Maps scraper pulls down megabytes of JavaScript, images, and fonts per page. This Actor doesn't load a browser at all, and on top of that:
  - Business websites (fetched only to find a contact email) are streamed and cut off the instant an email is found, or after a small byte cap — not downloaded in full.
  - Known social/aggregator domains (Facebook, Instagram, LinkedIn, etc.) are skipped entirely when they show up as a "website," since they're JS-heavy pages that never contain a plain contact email anyway.
  - Non-HTML responses (PDFs, images) are detected from the response headers and abandoned before a single byte of the body is downloaded.
  - If the same website shows up across multiple locations — common for franchises and chains — it's only ever fetched once for the whole run.
  - Duplicate businesses across your different search queries are de-duplicated by their Google Maps place ID *before* any detail page is fetched, not after.
- 🔁 **Streaming, not batch** — leads are pushed to your dataset continuously as they're scraped, so you can start working a list before a long run even finishes.

As far as **lead generation tools: Google Maps extractor** options go, most either drag in a full browser (slow, expensive) or scrape everything indiscriminately (noisy, unfiltered). This one aims to just get you a clean, contactable list, quickly.

### Input

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `queries` | `string[]` | — (required) | Google Maps search queries, e.g. `["restaurants in Paris", "dentists in Berlin"]`. |
| `maxResultsPerKeyword` | `int` | `50` | Max places to scrape **per query**. Leave empty for unlimited. |
| `extractEmails` | `bool` | `true` | Visit business websites to find a contact email when Google Maps doesn't already list one. |
| `minRating` | `float` | — | Drop places rated below this (1–5). |
| `maxRating` | `float` | — | Drop places rated above this (1–5). |
| `businessStatus` | `string[]` | all three | Keep only `OPERATIONAL`, `CLOSED_TEMPORARILY`, and/or `CLOSED_PERMANENTLY` listings. |
| `dropIfNoContact` | `bool` | `true` | Drop leads with no email, phone, or social link — nothing worth adding to an outreach list. |
| `workers` | `int` | `4` | Concurrent HTTP workers (1–32). |
| `lang` / `gl` | `string` | `en` / `us` | Google Maps language and country/region code. |
| `minDelay` | `float` | `2.0` | Minimum seconds between requests per worker. |
| `keepExtraFields` | `bool` | `false` | Keep heavier fields (`photos`, `menu`, `about`) in the output. |

### Output example

Each dataset item is one lead:

```json
{
  "query": "restaurants in Paris",
  "place_id": "0x47e66e1f06e2b75f:0x61d70c42f18c2b3b",
  "name": "Le Bouillon Chartier",
  "rating": 4.3,
  "review_count": 12450,
  "phone": "+33 1 47 03 36 79",
  "email": "contact@bouillonchartier.com",
  "website": "https://www.bouillonchartier.com",
  "social_links": [{ "platform": "facebook", "url": "https://..." }],
  "address": "7 Rue du Faubourg Montmartre, 75009 Paris",
  "business_status": "OPERATIONAL",
  "primary_type": "French restaurant",
  "coordinates": { "lat": 48.8718, "lng": 2.3432 },
  "categories": ["French restaurant", "Restaurant"]
}
```

The dataset ships with two ready-made views: **All leads**, and **Leads with email or phone** for a quick filtered export.

### Pricing

Check the **Pricing** tab on this Actor's page for the exact rate. In general, cost scales with how much you actually scrape — more queries, a higher `maxResultsPerKeyword`, and `extractEmails` turned on will all use more Apify platform compute. Keeping `keepExtraFields` off and using rating/status filters to narrow your results are the easiest ways to keep a run cheap, since you're only paying to process leads you actually want.

### Proxy behavior

- **On the Apify platform**: automatically uses Apify's **residential proxy**, so your requests come from real residential IPs.
- **Running locally**: no proxy is used — a direct connection — so you can develop and test without spending residential proxy traffic.

### FAQ

**Is this legal?**
This Actor only reads publicly visible Google Maps listing data. You're responsible for how you use the resulting leads — always follow applicable data-protection laws (e.g. GDPR, CAN-SPAM) when contacting people, and Google's own Terms of Service regarding automated access.

**Does it get emails for every lead?**
No — only when a business's own website has a visible contact email (in a `mailto:` link or plain text on the page). Email extraction is best-effort, not guaranteed, since not every business publishes one.

**Can I search multiple cities or categories at once?**
Yes — add as many queries as you want to the `queries` list. Each one gets its own `maxResultsPerKeyword` budget and results stream in as they're found, so you don't need to run the Actor once per query.

**How is this different from a browser-based Google Maps scraper?**
No browser means no rendering overhead, no screenshots, no wasted bandwidth on JavaScript/CSS/fonts/images your data doesn't need — just the underlying requests. That generally makes it faster and cheaper to run for the same number of leads.

**Why did I get fewer leads than my `maxResultsPerKeyword`?**
Your filters (`minRating`, `maxRating`, `businessStatus`, `dropIfNoContact`) are applied per place as it's scraped. If a query simply doesn't have enough matching businesses on Google Maps, you'll get fewer than the cap — that's Google Maps' own result count, not a limitation of the Actor.

# Actor input Schema

## `queries` (type: `array`):

List of Google Maps search queries. Each query is scraped independently with its own per-keyword max-results cap. Example: \['restaurants in Paris', 'dentists in Berlin', 'coffee shops in Amsterdam'].

## `maxResultsPerKeyword` (type: `integer`):

Maximum number of places to scrape PER query. Each query gets its own budget — e.g. 50 with 3 queries = up to 150 leads. Leave empty for unlimited (use with caution).

## `extractEmails` (type: `boolean`):

When ON, visit each business's website to extract a contact email when Google Maps does not already provide one. Turn OFF to skip website visits entirely and speed-up extraction.

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

Drop places with a star rating BELOW this value (1.0 - 5.0). Leave empty for no minimum. Example: 4.0 keeps only 4-star and above. Places with no rating are kept regardless.

## `maxRating` (type: `number`):

Drop places with a star rating ABOVE this value (1.0 - 5.0). Leave empty for no maximum. Example: 4.5 keeps only 4.5-star and below. Useful for finding underperforming competitors.

## `businessStatus` (type: `array`):

Keep only places whose Google Maps status matches one of these. Defaults to all three (no filtering).

## `dropIfNoContact` (type: `boolean`):

When ON (default), drop places that have NONE of: phone number, or social links. Lead-generation mode — only keep businesses you can actually contact. Turn OFF to keep all places regardless of contact info.

## `lang` (type: `string`):

Google Maps UI language code (hl parameter). Affects the language of returned text fields like address, categories, etc.

## `gl` (type: `string`):

Google Maps country/region code (gl parameter). Affects which regional results are returned.

## `keepExtraFields` (type: `boolean`):

When ON, retain photos, menu, and about sections in the output. OFF (default) strips these heavy fields to speed up processing, recommended for pure lead generation.

## Actor input object example

```json
{
  "queries": [
    "restaurants in Paris"
  ],
  "maxResultsPerKeyword": 150,
  "extractEmails": false,
  "businessStatus": [
    "OPERATIONAL",
    "CLOSED_TEMPORARILY",
    "CLOSED_PERMANENTLY"
  ],
  "dropIfNoContact": true,
  "lang": "en",
  "gl": "us",
  "keepExtraFields": true
}
```

# Actor output Schema

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

Default dataset containing all scraped leads as JSON items.

# 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 = {
    "queries": [
        "restaurants in Paris"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("code-node-tools/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 = { "queries": ["restaurants in Paris"] }

# Run the Actor and wait for it to finish
run = client.actor("code-node-tools/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 '{
  "queries": [
    "restaurants in Paris"
  ]
}' |
apify call code-node-tools/google-maps-lead-scraper --silent --output-dataset

```

## MCP server setup

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