# Google Maps Business Lead & Email Finder (`dataspryva/google-maps-business-lead-and-email-finder`) Actor

Find business leads on Google Maps by category, keyword, or location and collect name, address, phone, website, rating, review count, and coordinates. Optionally adds emails and social links found on each business's own website.

- **URL**: https://apify.com/dataspryva/google-maps-business-lead-and-email-finder.md
- **Developed by:** [Dataspryva](https://apify.com/dataspryva) (community)
- **Categories:** Lead generation, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.49 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Business Lead & Email Finder

Build a local prospecting list without a Google account, browser cookie or developer key. The actor searches Google Maps for the businesses you describe, then visits each business's own public website to collect the email addresses, extra phone numbers and social profiles that the business publishes.

### Three ways to use it

- Search Maps by category or phrase. One row per business with its listing details and Google Maps link.
- Look up places you already have. Paste Google Maps place links or Place IDs.
- Enrich a website list. Bring your own domains and skip the Maps search entirely.

### What you get

Each lead carries the business name, Google Maps categories, a split address, phone, website, rating, review count, Place ID, coordinates and a clean Google Maps URL. With contact extraction on, the row also carries emails found on the business's website, an MX-checked subset, the source page for each email, additional website phone numbers and up to ten social profiles.

Maps itself has no email field. An address is only reported when the business publishes it on its own site, and every missing field is left out rather than guessed.

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `searchPlaces` | Search Maps, look up specific places, or enrich websites |
| `searchQueries` | string\[] | – | Phrases for Maps, such as `roofers in Dallas TX` |
| `locationQuery` | string | – | Shared location appended to each phrase |
| `category` | string | `bakery` | Category used when keyword and phrases are empty |
| `keyword` | string | – | Custom term that takes priority over category |
| `state` | select | `All` | US state, or `All` for nationwide |
| `country` | select | `US` | Country for the search |
| `websites` | string\[] | – | Domains for website mode; bare domains are accepted |
| `placeUrls` | string\[] | – | Google Maps place links for specific-place mode |
| `placeIds` | string\[] | – | Place IDs starting with `ChIJ` |
| `max_results` | integer | `100` | Total lead cap (1–100,000) |
| `minRating` | number | – | Keep places rated at least this value (1.0–5.0) |
| `extractEmails` | boolean | `true` | Read business websites for contact details |
| `maxEmailsPerWebsite` | integer | `5` | Email cap per business website |
| `maxContactPagesPerWebsite` | integer | `3` | Homepage plus contact/about/legal/privacy pages |
| `onlySaveResults` | select | `allPlaces` | All places, only with an email, or only with contacts |
| `categoryFilter` | string\[] | – | Keep categories containing all words of any entry |
| `websiteFilter` | select | `allPlaces` | All places, with a website, or without one |
| `skipClosedPlaces` | boolean | `false` | Leave out permanently or temporarily closed places |
| `language` | select | `en` | Maps interface language (74 options plus two legacy codes) |

#### Examples

```json
{"mode":"searchPlaces","searchQueries":["bakeries in London"],"max_results":50,"extractEmails":true}
```

```json
{"mode":"specificPlaces","placeIds":["ChIJ…"],"extractEmails":true}
```

```json
{"mode":"enrichWebsites","websites":["example-bakery.com","example-dentist.de"]}
```

### Output

- Listing: `name`, `googleBusinessCategories`, `street`, `city`, `state`, `zip`, `country`, `countryCode`, `phoneNumber`, `url`, `reviewScore`, `reviewsNumber`, `placeId`, `featureId`, `googleMapsUrl`, `priceLevel`, `plusCode`, `location`, `websiteType`.
- Contacts: `email`, `emails`, `emailsMxValid`, `emailProvenance`, `websitePhones`, `contactPageUrl`, `websitePagesCrawled`, `facebook`, `instagram`, `linkedin`, `twitter`, `youtube`, `tiktok`, `pinterest`, `threads`, `whatsapp`, `telegram`.
- Context: `recordType`, `sourceUrl`, `scrapedAt`.

`emailProvenance` names the signal and the page that supplied each address. `websiteType` marks social-profile and directory links so a platform page is never treated as the business's own site.

### How many emails should I expect?

In a 128-business sample across Austin, London, Berlin and Paris, 74% published an email within the homepage plus two contact pages; reading deeper pages lifted the measured rate to 77% of businesses with a website. About 76% of the businesses with a website had at least one MX-valid address (98% of the email-bearing sites in the sample). European businesses often publish a legally required Impressum page, which helps those markets; sites that only offer a contact form, hide their address in JavaScript, or block automated visits cannot yield one. Treat 66–77% as a realistic range, not a promise for every market.

### Limitations

- A single Maps phrase exposes a ranked window of roughly 150–220 businesses. Run several related phrases, or split by area, to widen coverage; duplicates are removed by Place ID.
- Some websites publish no email, use a contact form only, or block automated access. Those rows keep their Maps details and simply omit website contacts.
- `priceLevel` is rarely exposed by Google's public listing data and is omitted rather than invented.
- `plusCode` is the code computed from the coordinates; Google's optional locality label is not appended.
- `emailsMxValid` confirms that the address domain publishes an MX record. It cannot prove that a person reads the inbox or detect a catch-all mailbox.
- Closed-place checks use Google's public status. A place whose status cannot be read is kept.

### FAQ

**Do I need an API key, cookies or a proxy?**
No. Searches and business websites are read from public pages. You do not configure a connection.

**Why is a row missing an email?**
Not every business has a website, and not every website publishes an address. Some use a contact form or a booking widget. The row is still a valid lead unless you choose `onlySaveResults: "onlyWithEmails"`; that filter keeps the matching rows among the places fetched up to your lead cap.

**What does `emailsMxValid` mean?**
It is the part of `emails` whose domain had an MX record when the run executed. An address is kept in `emails` even when DNS has no answer; it is simply not listed as MX-valid.

**What is `emailProvenance`?**
A small list that pairs each email with its signal (`mailto`, `jsonLd`, `cloudflare`, `text`, `obfuscated` or `raw`) and the page where it was found.

**Can I use the actor without Google Maps?**
Yes. Choose `enrichWebsites` and paste the domains. Each row is keyed to the website you supplied.

**Does it find owner or decision-maker emails?**
No. It reports public business contact details; personal or executive addresses are not inferred.

Use public data lawfully and in line with Google's terms. This actor is not affiliated with Google.

# Actor input Schema

## `mode` (type: `string`):

Search Google Maps, look up specific places, or enrich a list of websites you already have.

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

Natural-language searches such as 'coffee shops in Austin TX'. Include the place in each phrase, or use the location field below.

## `locationQuery` (type: `string`):

Adds a shared location to every search phrase, for example 'Austin, TX, USA'. Leave empty when your phrases already name the place.

## `category` (type: `string`):

Business category such as bakery, dentist or plumber. Used when keyword and search phrases are empty.

## `keyword` (type: `string`):

Custom search term such as 'boutique coffee' or 'pet grooming'. Takes priority over category.

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

US state for the search. Choose 'All' for nationwide. Ignored for non-US countries.

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

Country for the search. Other countries can be named directly in a search phrase.

## `websites` (type: `array`):

Websites to read for contact details, one per line. Bare domains such as example.com are accepted.

## `placeUrls` (type: `array`):

Google Maps place links copied from the address bar or a previous export.

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

Canonical Google Place IDs starting with 'ChIJ'.

## `max_results` (type: `integer`):

Maximum number of leads to save. Google returns a ranked window of roughly 150-220 businesses per search phrase, so a larger request may end when that window ends.

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

Keep only businesses rated at least this value (1.0-5.0). Leave empty for any rating.

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

Visit each business website for public emails, phone numbers and social profiles. Turn off for a faster Maps-only run.

## `maxEmailsPerWebsite` (type: `integer`):

Maximum email addresses to keep for one business website.

## `maxContactPagesPerWebsite` (type: `integer`):

Homepage plus contact, about, legal, privacy or careers pages to read. More pages find more contacts but take longer.

## `onlySaveResults` (type: `string`):

Save every business, only businesses with an email, or only businesses with any contact detail.

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

Keep places whose Google Maps category contains all words of at least one entry. Leave empty for no category filter.

## `websiteFilter` (type: `string`):

Keep all places, only places with a website, or only places without one.

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

Check Google's public status and leave out permanently or temporarily closed places.

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

Language of the Google Maps interface and listing text.

## Actor input object example

```json
{
  "mode": "searchPlaces",
  "searchQueries": [],
  "category": "bakery",
  "state": "CA",
  "country": "US",
  "websites": [],
  "placeUrls": [],
  "placeIds": [],
  "max_results": 3,
  "extractEmails": true,
  "maxEmailsPerWebsite": 3,
  "maxContactPagesPerWebsite": 2,
  "onlySaveResults": "allPlaces",
  "categoryFilter": [],
  "websiteFilter": "allPlaces",
  "skipClosedPlaces": false,
  "language": "en"
}
```

# Actor output Schema

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

One row per business with Maps listing data, website contact details, email provenance and social profiles.

# 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 = {
    "mode": "searchPlaces",
    "searchQueries": [],
    "locationQuery": "",
    "category": "bakery",
    "state": "CA",
    "country": "US",
    "websites": [],
    "placeUrls": [],
    "placeIds": [],
    "max_results": 3,
    "extractEmails": true,
    "maxEmailsPerWebsite": 3,
    "maxContactPagesPerWebsite": 2,
    "onlySaveResults": "allPlaces",
    "categoryFilter": [],
    "websiteFilter": "allPlaces",
    "skipClosedPlaces": false,
    "language": "en"
};

// Run the Actor and wait for it to finish
const run = await client.actor("dataspryva/google-maps-business-lead-and-email-finder").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 = {
    "mode": "searchPlaces",
    "searchQueries": [],
    "locationQuery": "",
    "category": "bakery",
    "state": "CA",
    "country": "US",
    "websites": [],
    "placeUrls": [],
    "placeIds": [],
    "max_results": 3,
    "extractEmails": True,
    "maxEmailsPerWebsite": 3,
    "maxContactPagesPerWebsite": 2,
    "onlySaveResults": "allPlaces",
    "categoryFilter": [],
    "websiteFilter": "allPlaces",
    "skipClosedPlaces": False,
    "language": "en",
}

# Run the Actor and wait for it to finish
run = client.actor("dataspryva/google-maps-business-lead-and-email-finder").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 '{
  "mode": "searchPlaces",
  "searchQueries": [],
  "locationQuery": "",
  "category": "bakery",
  "state": "CA",
  "country": "US",
  "websites": [],
  "placeUrls": [],
  "placeIds": [],
  "max_results": 3,
  "extractEmails": true,
  "maxEmailsPerWebsite": 3,
  "maxContactPagesPerWebsite": 2,
  "onlySaveResults": "allPlaces",
  "categoryFilter": [],
  "websiteFilter": "allPlaces",
  "skipClosedPlaces": false,
  "language": "en"
}' |
apify call dataspryva/google-maps-business-lead-and-email-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dataspryva/google-maps-business-lead-and-email-finder"
        }
    }
}
```

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/nzmL4XdPKeDa1Ahe3/builds/wdMPBcMnl2mFScdCG/openapi.json
