# Google Maps Email & Phone Enrichment (`foo121/maps-enrich`) Actor

Enrich Google Maps businesses with verified emails & phone numbers in one run — bulk B2B lead generation, cheaper than stacked multi-tool scrapers. Export CSV/JSON.

- **URL**: https://apify.com/foo121/maps-enrich.md
- **Developed by:** [ziv shay](https://apify.com/foo121) (community)
- **Categories:** Lead generation, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Google Maps Email & Phone Enrichment 📍📧📞

**Google Maps leads WITH email + phone in one run — half the price.**

Most Maps lead workflows cost you twice: one charge to scrape the listings, then a
second stacked add-on (~$9 / 1,000) to find the emails and phones. This actor
**bundles enrichment into a single pay-per-result run** so you get a finished,
ready-to-outreach B2B lead list at a fraction of the cost.

Feed it business website URLs (or pipe the output of any Google Maps scraper) and
it returns **one structured lead per business** with verified emails, phones and
social profiles.

---

### 💡 What it does

For every business website you provide, the actor:

1. Fetches the **homepage** plus common contact paths (`/contact`, `/contact-us`,
   `/about`, `/about-us` — configurable).
2. Extracts:
   - **Emails** — from `mailto:` links and page text, deduped, lowercased, with
     image/asset false-positives (`logo@2x.png`) and placeholders stripped. Each
     email is flagged **role-based** (`info@`, `sales@`) vs **personal** so you
     can segment outreach.
   - **Phones** — from `tel:` links and page text, normalized to **E.164-ish**
     format (`+14155552671`).
   - **Socials** — LinkedIn, Facebook, Twitter/X, Instagram profile URLs.
3. Pushes **one clean result per business** to the dataset — pay-per-result ready.

One bad/slow/dead site **never kills the run** — every site is isolated with its
own timeout and try/catch, and even unreachable sites produce a result row with a
`status` so your billing and your CRM stay consistent.

---

### 🆚 Why it beats stacking Outscraper-style add-ons

| | Typical stack | **maps-enrich** |
|---|---|---|
| Maps listings | Scraper $ | Bring your own / chain upstream |
| Email + phone enrichment | **+ ~$9 / 1,000** add-on | **bundled** |
| Runs | Two tools, two bills | **One run** |
| Price target | stacked | **~$0.004 / enriched result** |
| Output | merge yourself | **one row per business, ready to export** |

---

### 📥 Input

| Field | Type | Required | Description |
|---|---|---|---|
| `websites` | array | ✅ | URLs (`"https://acme.com"`) **and/or** objects with a `website` field (e.g. Maps-scraper output). |
| `searchTerms` | array | — | Maps discovery keywords. Recorded only — see *Chaining maps discovery*. |
| `location` | string | — | Maps discovery location. Recorded only. |
| `maxResults` | integer | — | Cap on businesses enriched. `0` = no cap. |
| `contactPaths` | array | — | Extra relative paths probed per site. Default `["/contact","/contact-us","/about","/about-us"]`. |
| `maxConcurrency` | integer | — | Sites crawled in parallel. Default `10`. |
| `requestTimeoutSecs` | integer | — | Per-request timeout. Default `20`. |
| `proxyConfiguration` | object | — | Apify Proxy config. Residential recommended at scale. |

#### Example input

```json
{
  "websites": [
    "https://www.apify.com",
    { "name": "Example Co", "website": "https://example.com" }
  ],
  "maxConcurrency": 10,
  "requestTimeoutSecs": 20,
  "proxyConfiguration": { "useApifyProxy": true }
}
````

You can also paste raw Google Maps scraper output directly — any object with a
`website` (or `url`/`domain`) key is accepted, and the `name`/`title` is carried
through.

***

### 📤 Output

One dataset item per business:

```json
{
  "name": "Example Co",
  "website": "https://example.com/",
  "domain": "example.com",
  "emails": ["info@example.com", "jane.doe@example.com"],
  "emailDetails": [
    { "email": "info@example.com", "type": "role" },
    { "email": "jane.doe@example.com", "type": "personal" }
  ],
  "phones": ["+14155552671"],
  "linkedin": "https://www.linkedin.com/company/example",
  "facebook": "https://facebook.com/example",
  "twitter": null,
  "instagram": null,
  "hasEmail": true,
  "hasPhone": true,
  "emailCount": 2,
  "phoneCount": 1,
  "pagesScanned": 3,
  "status": "enriched",
  "error": null,
  "scrapedAt": "2026-06-19T12:00:00.000Z"
}
```

`status` is one of: `enriched`, `no_contacts_found`, `unreachable`, `error`.

Export to CSV / Excel / JSON from the run's **Dataset** tab or via the API.

***

### 🔗 Chaining maps discovery (upstream dependency)

Full Google Maps scraping is anti-bot heavy and fragile, so this actor **does not
reimplement it**. Instead, chain a dedicated, battle-tested Maps scraper and feed
its output here. The clean integration point: any object with a `website` field
is enriched automatically.

**Recommended chain (Apify Console → Integrations, or via API):**

1. Run a maps-scrape actor (e.g. `compass/google-maps-scraper`) with your
   `searchTerms` + `location`.
2. Feed its dataset into this actor's `websites` input.

API example:

```bash
## 1) Maps discovery (upstream)
apify call compass/google-maps-scraper \
  --input='{"searchStringsArray":["dentist"],"locationQuery":"Austin, TX","maxCrawledPlacesPerSearch":50}'

## 2) Pipe that dataset's items (each has a `website`) into enrichment
apify call YOUR_USERNAME/maps-enrich \
  --input='{"websites": <items-from-step-1>}'
```

The `searchTerms`/`location` fields on this actor exist to record discovery intent
and emit a clear log notice; they do not perform scraping themselves.

***

### 💰 Pricing model

Built for **pay-per-result** (Apify's per-event pricing). Bill per enriched lead
pushed to the dataset (target ~**$0.004 / result**). Rental pricing is **not**
used (Apify retired rental pricing in October 2026).

To set it up: Console → your actor → **Publication → Monetization → Pay per
result** (or Pay per event), then set the per-result price.

***

### 🚀 Run locally

```bash
npm install
npm test          # unit tests for the extraction logic (no network)
apify run         # runs against storage/key_value_stores/default/INPUT.json
```

Requires Node 20+ and the [Apify CLI](https://docs.apify.com/cli) (`npm i -g apify-cli`).

***

### 📦 Publish to Apify

```bash
npm i -g apify-cli
apify login                 # paste your API token
cd projects/maps-enrich
apify push                  # builds the Docker image & uploads the actor
```

Then in **Apify Console → your actor**:

1. **Builds** — confirm the latest build is green.
2. **Publication → Display information** — title, description, categories
   (Lead generation, Business, E-commerce).
3. **Publication → Monetization** — choose **Pay per result**, set the price.
4. **Publish** to the Apify Store.

***

### 🔍 Listing SEO keywords

`google maps email scraper` · `google maps lead scraper` · `email and phone
extractor` · `b2b lead generation` · `contact scraper` · `business email finder`
· `outscraper alternative` · `website email scraper` · `lead enrichment` ·
`sales prospecting tool` · `bulk email finder`

# Actor input Schema

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

List of business website URLs to enrich. You can paste plain URLs (e.g. "https://acme.com") OR objects that contain a `website` field (e.g. the output of a Google Maps scraper like compass/google-maps-scraper). Each entry produces ONE enriched lead in the dataset.

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

OPTIONAL. Keywords to discover businesses on Google Maps (e.g. "dentist", "plumber"). Maps discovery is NOT done in this actor — it is a documented upstream dependency. Provide these to record discovery intent; see README to chain a maps-scrape actor that feeds `websites`.

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

OPTIONAL. Geographic location for Maps discovery (e.g. "Austin, TX"). Used together with searchTerms by the upstream maps-scrape actor.

## `maxResults` (type: `integer`):

Cap on the number of businesses to enrich. 0 = no cap (process every website provided).

## `contactPaths` (type: `array`):

Relative paths probed on each site in addition to the homepage to find contact details.

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

How many sites to crawl in parallel.

## `requestTimeoutSecs` (type: `integer`):

Abort a single page fetch after this many seconds. A slow or dead site never stalls the run.

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

Proxy used for outbound requests. Apify Residential or Datacenter proxy is recommended for scale and to avoid rate limits.

## Actor input object example

```json
{
  "websites": [
    "https://www.apify.com",
    {
      "name": "Example Co",
      "website": "https://example.com"
    }
  ],
  "searchTerms": [],
  "maxResults": 0,
  "contactPaths": [
    "/contact",
    "/contact-us",
    "/about",
    "/about-us"
  ],
  "maxConcurrency": 10,
  "requestTimeoutSecs": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "websites": [
        "https://www.apify.com",
        {
            "name": "Example Co",
            "website": "https://example.com"
        }
    ],
    "searchTerms": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("foo121/maps-enrich").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 = {
    "websites": [
        "https://www.apify.com",
        {
            "name": "Example Co",
            "website": "https://example.com",
        },
    ],
    "searchTerms": [],
}

# Run the Actor and wait for it to finish
run = client.actor("foo121/maps-enrich").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "websites": [
    "https://www.apify.com",
    {
      "name": "Example Co",
      "website": "https://example.com"
    }
  ],
  "searchTerms": []
}' |
apify call foo121/maps-enrich --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=foo121/maps-enrich",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Email & Phone Enrichment",
        "description": "Enrich Google Maps businesses with verified emails & phone numbers in one run — bulk B2B lead generation, cheaper than stacked multi-tool scrapers. Export CSV/JSON.",
        "version": "1.0",
        "x-build-id": "2WjwwlQQ7ay2TIEeJ"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/foo121~maps-enrich/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-foo121-maps-enrich",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/foo121~maps-enrich/runs": {
            "post": {
                "operationId": "runs-sync-foo121-maps-enrich",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/foo121~maps-enrich/run-sync": {
            "post": {
                "operationId": "run-sync-foo121-maps-enrich",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "websites"
                ],
                "properties": {
                    "websites": {
                        "title": "Business websites to enrich",
                        "type": "array",
                        "description": "List of business website URLs to enrich. You can paste plain URLs (e.g. \"https://acme.com\") OR objects that contain a `website` field (e.g. the output of a Google Maps scraper like compass/google-maps-scraper). Each entry produces ONE enriched lead in the dataset."
                    },
                    "searchTerms": {
                        "title": "Search terms (Maps discovery — optional)",
                        "type": "array",
                        "description": "OPTIONAL. Keywords to discover businesses on Google Maps (e.g. \"dentist\", \"plumber\"). Maps discovery is NOT done in this actor — it is a documented upstream dependency. Provide these to record discovery intent; see README to chain a maps-scrape actor that feeds `websites`.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "location": {
                        "title": "Location (Maps discovery — optional)",
                        "type": "string",
                        "description": "OPTIONAL. Geographic location for Maps discovery (e.g. \"Austin, TX\"). Used together with searchTerms by the upstream maps-scrape actor."
                    },
                    "maxResults": {
                        "title": "Max results",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Cap on the number of businesses to enrich. 0 = no cap (process every website provided).",
                        "default": 0
                    },
                    "contactPaths": {
                        "title": "Extra contact paths to crawl",
                        "type": "array",
                        "description": "Relative paths probed on each site in addition to the homepage to find contact details.",
                        "default": [
                            "/contact",
                            "/contact-us",
                            "/about",
                            "/about-us"
                        ],
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "How many sites to crawl in parallel.",
                        "default": 10
                    },
                    "requestTimeoutSecs": {
                        "title": "Per-request timeout (seconds)",
                        "minimum": 5,
                        "maximum": 120,
                        "type": "integer",
                        "description": "Abort a single page fetch after this many seconds. A slow or dead site never stalls the run.",
                        "default": 20
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxy used for outbound requests. Apify Residential or Datacenter proxy is recommended for scale and to avoid rate limits.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
