# Google Maps Contact & Email Enricher (CRM-Ready Leads) (`enezli/maps-contact-cleaner`) Actor

Cleans any Maps scraper's raw output into CRM-ready contacts: cross-source dedup & merge, E.164 phone/social normalization, email quality class (corporate / role / free / disposable) and a "who you can safely contact" confidence verdict. No subscription — pay per record.

- **URL**: https://apify.com/enezli/maps-contact-cleaner.md
- **Developed by:** [Turgay NANTA](https://apify.com/enezli) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 clean contacts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Google Maps Contact Cleaner & Enricher — CRM-Ready Contacts

Turns a Google Maps scraper's **raw output into usable data**. This is **not** a scraper — it's the **quality layer** that runs *after* the scrape: it cleans, merges across sources, classifies email quality, and gives every contact a "who can I safely email" verdict. **No LLM, no API keys — fully deterministic.**

### What it does

Google Maps scrapers **extract** data but don't **clean** it: the same business shows up in 3 rows, phone formats are inconsistent, `info@` role accounts get mistaken for real people, and throwaway emails are never filtered out. This actor takes that output and turns it into a **clean, de-duplicated, confidence-labeled** contact list ready for your CRM.

### Input (any one of three)

| Field | Description |
|---|---|
| `records` | Raw business records (a Google Maps scraper dataset can be connected directly). `name`/`title`, `website`/`url`, `phone`, `emails`, `social` are auto-detected |
| `datasetId` | OR an Apify dataset ID holding the raw records to clean |
| `searchTerms` | OR, if you have no data yet, fetch it via an upstream Google Maps scraper (scraping is left to the upstream actor) |
| `liveMxCheck` | (Optional) live MX-record check for the best email's domain |

### Output (dataset, per record)

Each cleaned record carries English keys:

`name`, `website`, `phone` (E.164-style), `address`, `emails` (clean), `socials` (canonical), `email_classes`, `best_email` + `best_email_type`, **`contact_confidence`** (`SAFE` / `REVIEW` / `WEAK`) + `contact_confidence_reason`, `priority` (0–100), `socials_summary`. The final row `_summary` carries the run summary: `total_records`, `with_email`, `verdict_distribution`, `email_type_distribution`, `sendable_SAFE`, `reach_first_list`.

Email types: `corporate` · `free_provider` · `role_account` · `disposable` · `invalid`.

### Why this actor?

1. **Cross-source dedup + merge** — the same business becomes one rich record (fields are completed across sources via a multi-key union-find, so even website-only and email-only fragments that share a phone number merge correctly).
2. **Email quality classes** — role account / disposable / free / corporate, deterministic and key-free.
3. **Contact-Confidence Verdict** — don't blast 1,000 rows blindly; send the "green" ones → protect deliverability and sender reputation.
4. **Cleaning & normalization** — phone to E.164, socials stripped of tracking params, lowercased canonical domains → straight into your CRM.

### How to use

1. Collect business listings with a Google Maps scraper (or paste in your own list).
2. Connect the output to this actor as `records` (or pass a `datasetId` / `searchTerms`).
3. **Start** → grab the clean, prioritized contact list from the Dataset tab (use the **Contact Table** view).

### Pricing (Pay-Per-Event)

You only pay for what you use: per run + per 100 records processed + per enriched record produced. The core is LLM-free, so margins stay high and costs stay predictable. No monthly subscription.

# Actor input Schema

## `records` (type: `array`):

Raw business records to clean. Connect any Google Maps scraper's dataset output directly here. Common fields such as name/title, website/url, phone, emails and social are auto-detected.

## `datasetId` (type: `string`):

Instead of `records`: an Apify dataset ID holding the raw records to clean (e.g. the output dataset of a Google Maps scraper run).

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

If you have no dataset yet: we call an upstream Google Maps scraper with these terms (e.g. 'dentist in Berlin'). We leave scraping to the upstream actor; our job is to clean the output.

## `maxPlaces` (type: `integer`):

When searchTerms is provided, the maximum number of places to fetch per search term.

## `liveMxCheck` (type: `boolean`):

When enabled, the domain of each best email is checked for a live MX record (extra quality confirmation). Classification stays fully deterministic when disabled.

## Actor input object example

```json
{
  "records": [
    {
      "title": "Acme Dental Clinic",
      "url": "https://www.acmedental.com?utm=x",
      "phone": "+1 415 555 0142",
      "emails": [
        "info@acmedental.com"
      ],
      "social": [
        "https://facebook.com/acmedental?ref=page_internal"
      ]
    },
    {
      "name": "Acme Dental Clinic Downtown",
      "website": "acmedental.com",
      "phoneNumber": "+1 (415) 555-0142",
      "email": "jane.doe@acmedental.com"
    }
  ],
  "maxPlaces": 50,
  "liveMxCheck": false
}
```

# 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 = {
    "records": [
        {
            "title": "Acme Dental Clinic",
            "url": "https://www.acmedental.com?utm=x",
            "phone": "+1 415 555 0142",
            "emails": [
                "info@acmedental.com"
            ],
            "social": [
                "https://facebook.com/acmedental?ref=page_internal"
            ]
        },
        {
            "name": "Acme Dental Clinic Downtown",
            "website": "acmedental.com",
            "phoneNumber": "+1 (415) 555-0142",
            "email": "jane.doe@acmedental.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("enezli/maps-contact-cleaner").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 = { "records": [
        {
            "title": "Acme Dental Clinic",
            "url": "https://www.acmedental.com?utm=x",
            "phone": "+1 415 555 0142",
            "emails": ["info@acmedental.com"],
            "social": ["https://facebook.com/acmedental?ref=page_internal"],
        },
        {
            "name": "Acme Dental Clinic Downtown",
            "website": "acmedental.com",
            "phoneNumber": "+1 (415) 555-0142",
            "email": "jane.doe@acmedental.com",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("enezli/maps-contact-cleaner").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 '{
  "records": [
    {
      "title": "Acme Dental Clinic",
      "url": "https://www.acmedental.com?utm=x",
      "phone": "+1 415 555 0142",
      "emails": [
        "info@acmedental.com"
      ],
      "social": [
        "https://facebook.com/acmedental?ref=page_internal"
      ]
    },
    {
      "name": "Acme Dental Clinic Downtown",
      "website": "acmedental.com",
      "phoneNumber": "+1 (415) 555-0142",
      "email": "jane.doe@acmedental.com"
    }
  ]
}' |
apify call enezli/maps-contact-cleaner --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/5c22SFcByFq2hXGug/builds/P2DidpsANJQW3fg5H/openapi.json
