# Google Maps Lead Scraper - Verified Emails, Phones & Owners (`doesaiknow/google-maps-lead-scraper`) Actor

Turn any search into a lead list: "dentist Chicago" → CSV with phone (~97% of businesses), SMTP-verified email, owner name, and a 0–1 confidence score. Live from Google Maps, not a recycled database. Monitoring mode returns only NEW businesses. Pay per lead, no subscription.

- **URL**: https://apify.com/doesaiknow/google-maps-lead-scraper.md
- **Developed by:** [David S](https://apify.com/doesaiknow) (community)
- **Categories:** Lead generation, MCP servers, Automation
- **Stats:** 1 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.07 / verified email lead

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 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/docs.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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 Lead Scraper — Verified Emails, Phones & Owner Names

Turn a search intent into a ready-to-use lead list — **no URL lists, no recycled databases.** Enter a niche and a location (e.g. *"roofing contractor, Dallas"*) and get every business with its **phone number, a deliverability-verified email, the owner's name, and a confidence score**, exported to CSV / JSON / Excel. Runs on demand or on a schedule (monitoring mode delivers **only new businesses**), and plugs into **n8n, Make, Zapier, and AI agents (Claude, ChatGPT)** via the API and Apify's MCP server.

Unlike commodity Google Maps email scrapers that dump raw addresses, this actor **verifies every email** (SMTP-checked, catch-all flagged) and classifies it (personal vs role), so your cold outreach doesn't bounce. Phone is captured on **~97% of businesses**, so even in trades where few publish an email, you still get a callable lead.

---

### Why this over a raw Maps scraper

Most Google Maps lead scrapers stop at "we found an address on the website." This one is built around the thing that actually costs you money — **bounces and dead contacts**:

| | Raw Maps scrapers | **This actor** |
|---|---|---|
| Email found | dumps whatever string it sees | extracted **and SMTP-verified** for deliverability |
| Catch-all domains | sold as a normal email | **flagged** `catch_all`, never counted as verified |
| Wrong-business emails | passed through | `email_domain_match` flags emails that don't belong to the site (agency/site-builder artifacts) |
| Dead addresses | billed as a lead | near-undeliverable emails are **dropped to phone-only**, not sold to you |
| Phone | sometimes | **~97% of businesses**, always surfaced |
| Confidence | none | a 0–1 score per lead so you know what to trust before you send |

**Validation ≠ verification.** A quick "syntax valid" check still bounces. This actor does a deep server-side SMTP check that resolves greylisting and catch-all — and when a domain is genuinely unverifiable, it says so instead of faking a green check.

---

### What you get per lead

```jsonc
{
  "company": "DRD Law, LLC",
  "category": "Criminal justice attorney",
  "city": "Chicago", "country": "US",
  "phone": "+13123739467",
  "website": "https://www.drdlawllc.com/",
  "email": "david@drdlawllc.com",
  "email_source": "jsonld",           // mailto | jsonld | html | render | none
  "email_status": "verified",         // verified | catch_all | unverified | rejected | none
  "email_type": "personal",           // personal | role | generic
  "is_free_email": false,             // gmail/yahoo/… vs business domain
  "email_domain_match": true,         // email belongs to the business website
  "confidence": 0.98,                 // 0–1
  "lead_type": "verified_email_lead", // verified_email_lead | email_lead | phone_only_lead | no_contact
  "rating": 4.8, "reviews": 148,
  "place_id": "ChIJ…", "scanned_at": "2026-07-17T…"
}
````

### How to use

1. **Search terms** — one or more niches: `dentist`, `roofing contractor`, `plumber`.
2. **Country** — pick from the dropdown (most popular markets first).
3. **Cities** — one per line (English names, diacritics OK — *"Kraków"* matches *"Krakow"*). An entry with its own country (*"Berlin, DE"*, *"Paris, France"*) overrides the dropdown, so **one run can span several countries**. Leave Cities empty to search the whole country.
4. Run → download the dataset as CSV / JSON / Excel, or pull it via the API.

**Bring your own list (Mode B):** skip Maps and pass `startUrls` (business websites) or `placeIds` to go straight to email extraction + verification.

#### Useful options

- **Verify emails** — on by default (the premium layer). Turn off for a faster, cheaper phone + raw-email pull.
- **Bring your own key** — use your own [Reoon](https://emailverifier.reoon.com/) API key instead of the bundled verification.
- **Min results (stop-loss)** — if Maps finds fewer businesses than this, the run stops **before** any extraction or verification and **nothing is charged**.
- **Email types** — keep `personal` / `role`, drop `generic` (`noreply@`).
- **JS rendering** — `auto` renders in a real browser only for sites that block plain requests.

### Pricing (pay per event)

You pay for what a run actually produces — no subscription:

| Event | When it fires | Price |
|---|---|---|
| Business scanned | every business processed | $0.002 |
| Phone lead | phone, no usable email | $0.015 |
| Email lead | email found, not verified | $0.03 |
| **Verified email lead** | SMTP-verified, deliverable email | **$0.10** |
| Lead enriched *(opt-in)* | owner name and/or social + booking signals found | $0.05 |
| **Verified personal email** *(opt-in)* | owner's personal email SMTP-verified | **$0.35** |

You never pay the verified price for a catch-all or an unverifiable address, and failed personal-email guesses cost nothing. The two enrichment events fire only when the **Enrich leads** / **Find & verify personal email** toggles are on.

**Start free:** a new Apify account comes with **$5 of free platform credit** — enough to scan ~2,000 businesses and collect your first verified leads before spending anything. The **Min results stop-loss** additionally guarantees that a search which finds too few businesses charges **nothing at all**.

### Decision-ready: WHO to contact, not just an inbox

Turn on **Enrich leads** to go past a generic `info@` address and get the person to actually write to — pulled live from the business's own website, not a recycled B2B database:

- **Owner / decision-maker name** — from the Impressum (DE/AT legal disclosure), team/about pages, and JSON-LD `Person` data. Deterministic parsing, no AI guessing.
- **Social + booking signals** — Facebook / Instagram / LinkedIn-company links and booking platforms (Booksy, Doctolib, Fresha, Treatwell, Calendly, Zocdoc…) detected on the site.
- **`outreach_hint`** per lead — `email_personal` › `email_direct` › `platform_first` › `phone_first` › `low_signal` — tells you the best channel at a glance.

Turn on **Find & verify personal email** to generate the owner's likely address patterns (`anna@`, `a.kowalska@`, `anna.kowalska@`, `kowalska@`, diacritics folded) and **SMTP-verify** them. Only a **verified** hit is returned and charged (`personal_email_verified`) — failed guesses cost nothing, and catch-all domains are skipped.

Both are **opt-in** and priced as separate events (`lead_enriched`, `personal_email_verified`); with them off, output and billing are unchanged (the new columns are simply empty).

**Owner-name coverage is highest in DE/AT/NL** (Impressum / KvK legal-disclosure culture) and lower in US/UK — roughly the *inverse* of verified-email coverage, so the two tiers complement each other geographically.

**Legal note:** owner names come exclusively from legally mandated or voluntarily published business pages (Impressum, team/about) — B2B legitimate interest. No LinkedIn scraping, no people-search registries, no private data.

### Monitoring mode — pay only for NEW businesses

Set **Run mode** to `incremental` and schedule the run (weekly / monthly): the actor remembers what it already delivered for that search and each new run returns — and charges — **only newly-appeared businesses**. Point it at *"dentist, Austin"* once a month and you get just the new openings, verified and dedicated to outreach while they're still setting up their vendor stack. Use the optional **monitor label** to keep several independent monitors on the same niche. Repeated runs also reuse the built-in caches (Maps 24 h, verification 30 days), so a monitor stays cheap even in `full` mode.

### Use with AI agents & LLM workflows

The dataset is built to drop straight into automation and LLM pipelines:

- **n8n / Make / Zapier** — trigger a run, wait for finish, pull the dataset as JSON and route verified leads into your CRM or outreach tool. The `lead_type` and `outreach_hint` fields let a flow branch (email sequence vs call list vs platform DM) without any parsing.
- **AI agents (Claude, ChatGPT)** — call this actor through Apify's MCP server integration and let the agent fetch fresh, verified leads mid-conversation ("find 50 dentists in Austin with verified emails").
- **LLM personalization** — feed `company`, `category`, `owner_name`, `rating`, and `reviews` to ChatGPT/Claude (or a LangChain pipeline) to generate personalized first lines at scale; `email_type` + `confidence` tell the model which leads deserve the effort.
- **API** — standard Apify runs + datasets endpoints; see the API tab for ready code in JavaScript, Python, and cURL.

### Coverage — honest scope

Phone is captured on **~97% of businesses**. **Email coverage varies by market** — highest in Ireland / Netherlands / Australia / Germany (~60–86%), lower in France / Italy / US (~35%) — and by niche (professional > trades > booking-platform consumer). **"Verified"** means SMTP-deliverability-checked; **catch-all domains are flagged as unverifiable and never counted as verified.** Businesses without a website come back as **phone-only leads**, clearly bucketed. We'd rather show you an honest phone-only lead than a fake verified email.

### Legal & GDPR

This actor returns **B2B business contact data from public sources** (Google Maps listings and public business websites). It does not scrape login-walled sources. **You are solely responsible for lawful use** of the returned data under GDPR, CAN-SPAM, PECR, and applicable local law — including lawful basis, opt-out handling, and marketing-consent rules in your jurisdiction.

### FAQ

**Does it find emails or just Maps data?** Both — phone from Maps (~97%), email extracted from the business website and verified for deliverability.

**What if a business has no website?** You still get a phone-only lead (separate bucket), flagged honestly.

**Are the emails really verified?** Yes — a deep SMTP deliverability check. Catch-all domains are flagged as unverifiable, never faked as verified.

**Which markets have the best email coverage?** Ireland, Netherlands, Australia, Germany are highest; phone coverage is ~97% everywhere.

**How is it different from Apollo / ZoomInfo?** Live from Google Maps (current data), not a recycled database — and every email is verified before it reaches you.

**Can I use my own verification credits?** Yes — set the provider to "bring your own key" and paste a Reoon API key.

**Can I monitor a niche instead of re-scraping it?** Yes — run mode `incremental` returns and charges only businesses that appeared since your last run. Schedule it monthly and you get just the new openings.

**Does it work with n8n / Make / AI agents?** Yes — standard Apify API + MCP server, so n8n/Make/Zapier flows and agents like Claude or ChatGPT can trigger runs and read the dataset directly.

***

*Part of the `doesaiknow/*` Apify actor suite.*

# Actor input Schema

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

Business niches to search on Google Maps, e.g. "dentist", "plumber". Required unless you provide Start URLs or Place IDs.

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

Default country for bare city names below (most popular first). Leave Cities empty for a country-wide search. Entries like "Berlin, DE" override it per city.

## `cities` (type: `array`):

City names, one per line. A bare name ("Warsaw", "Kraków" — English names, diacritics OK) is looked up in the selected Country. Add a country to an entry to mix countries in one run: "Berlin, DE", "Paris, France", a full location name, or "lat,lng,zoom" coordinates. Unknown names are skipped with a did-you-mean suggestion in the log. Leave empty to search the whole selected country.

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

Language of Google Maps results (most popular first).

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

Maximum businesses fetched per search term × location (capped at 5000).

## `minResults` (type: `integer`):

Stop the run BEFORE email extraction & verification if Google Maps finds fewer businesses than this — nothing gets charged. 0 = disabled.

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

Bring your own list of business websites — skips Google Maps and goes straight to email extraction.

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

Bring your own list of Google Maps place IDs.

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

How many pages to check per website when hunting for an email, in order: home, /contact, /kontakt, /contact-us, /about, /impressum, /kontakt.html.

## `renderJs` (type: `string`):

"never" (default) is fastest and cheapest — plain HTTP extraction, no browser. "auto" renders in a real browser (via residential proxy) only for sites that block plain requests; it recovers a few extra emails but costs noticeably more, so turn it on only when you want maximum email coverage. "always" renders every site (slowest, most expensive).

## `includeNoWebsite` (type: `boolean`):

Businesses with no website become phone-only leads instead of being dropped.

## `verifyEmails` (type: `boolean`):

Verify each found email for deliverability. Off = faster and cheaper; emails are returned as "unverified".

## `verifyProvider` (type: `string`):

"bundled" uses our verification service — no setup, verification is included in the per-lead price. "byo" uses YOUR OWN Reoon Email Verifier API key (emailverifier.reoon.com → API) — you pay Reoon directly for credits (~$0.0012/verify) instead of us.

## `verifyApiKey` (type: `string`):

Reoon Email Verifier API key (create one at emailverifier.reoon.com → API). Required only when the verification provider is "byo"; ignored otherwise.

## `emailTypes` (type: `array`):

Which email types to include in results: personal (john@…), role (info@, office@…), generic (noreply@, postmaster@…).

## `enrichLeads` (type: `boolean`):

Find the owner/decision-maker name (Impressum, team pages, JSON-LD Person), social profile links and booking-platform signals from the business website. Adds the lead\_enriched event ($). No extra page fetches for most sites - reuses pages already downloaded.

## `guessPersonalEmails` (type: `boolean`):

When an owner name is found and the domain is not catch-all, generate common patterns (anna@, a.kowalska@, anna.kowalska@, kowalska@) and SMTP-verify them. Only VERIFIED hits are charged (personal\_email\_verified event). Requires enrichLeads and verifyEmails.

## `dedupeBy` (type: `string`):

How to deduplicate businesses across searches.

## `freshData` (type: `boolean`):

By default, repeated runs of the same search reuse cached Google Maps results (24 h) and email verifications (30 days) — cheaper and stable. Turn this on to force a fresh live pull.

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

"full" returns every matching business each run. "incremental" remembers what it already delivered for this search and returns ONLY newly-appeared businesses on later runs — and charges only for those. Ideal for monitoring: run monthly for a niche+city and get just the new openings.

## `runTag` (type: `string`):

Optional label that keys the incremental state, so you can keep several independent monitors. Leave empty to key by the search itself (search terms + locations).

## Actor input object example

```json
{
  "searchTerms": [
    "dentist"
  ],
  "country": "United States",
  "cities": [
    "Chicago"
  ],
  "language": "en",
  "maxResults": 25,
  "minResults": 0,
  "maxPagesPerSite": 5,
  "renderJs": "never",
  "includeNoWebsite": true,
  "verifyEmails": true,
  "verifyProvider": "bundled",
  "emailTypes": [
    "personal",
    "role"
  ],
  "enrichLeads": false,
  "guessPersonalEmails": false,
  "dedupeBy": "domain",
  "freshData": false,
  "mode": "full"
}
```

# Actor output Schema

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

Default dataset link — one row per business with phone, verified email, and confidence.

# 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 = {
    "searchTerms": [
        "dentist"
    ],
    "country": "United States",
    "cities": [
        "Chicago"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("doesaiknow/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 = {
    "searchTerms": ["dentist"],
    "country": "United States",
    "cities": ["Chicago"],
}

# Run the Actor and wait for it to finish
run = client.actor("doesaiknow/google-maps-lead-scraper").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 '{
  "searchTerms": [
    "dentist"
  ],
  "country": "United States",
  "cities": [
    "Chicago"
  ]
}' |
apify call doesaiknow/google-maps-lead-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Lead Scraper - Verified Emails, Phones & Owners",
        "description": "Turn any search into a lead list: \"dentist Chicago\" → CSV with phone (~97% of businesses), SMTP-verified email, owner name, and a 0–1 confidence score. Live from Google Maps, not a recycled database. Monitoring mode returns only NEW businesses. Pay per lead, no subscription.",
        "version": "0.1",
        "x-build-id": "pb11jirB6GbLOaLb1"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/doesaiknow~google-maps-lead-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-doesaiknow-google-maps-lead-scraper",
                "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/doesaiknow~google-maps-lead-scraper/runs": {
            "post": {
                "operationId": "runs-sync-doesaiknow-google-maps-lead-scraper",
                "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/doesaiknow~google-maps-lead-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-doesaiknow-google-maps-lead-scraper",
                "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",
                "properties": {
                    "searchTerms": {
                        "title": "Search terms (niche)",
                        "type": "array",
                        "description": "Business niches to search on Google Maps, e.g. \"dentist\", \"plumber\". Required unless you provide Start URLs or Place IDs.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "country": {
                        "title": "Country",
                        "enum": [
                            "United States",
                            "United Kingdom",
                            "Germany",
                            "Canada",
                            "Australia",
                            "France",
                            "Netherlands",
                            "Spain",
                            "Italy",
                            "Poland",
                            "Czechia",
                            "Austria",
                            "Switzerland",
                            "Belgium",
                            "Ireland",
                            "Sweden",
                            "Afghanistan",
                            "Albania",
                            "Algeria",
                            "American Samoa",
                            "Andorra",
                            "Angola",
                            "Antarctica",
                            "Antigua and Barbuda",
                            "Argentina",
                            "Armenia",
                            "Azerbaijan",
                            "Bahrain",
                            "Bangladesh",
                            "Barbados",
                            "Belize",
                            "Benin",
                            "Bhutan",
                            "Bolivia",
                            "Bosnia and Herzegovina",
                            "Botswana",
                            "Brazil",
                            "Brunei",
                            "Bulgaria",
                            "Burkina Faso",
                            "Burundi",
                            "Cabo Verde",
                            "Cambodia",
                            "Cameroon",
                            "Caribbean Netherlands",
                            "Central African Republic",
                            "Chad",
                            "Chile",
                            "China",
                            "Christmas Island",
                            "Cocos (Keeling) Islands",
                            "Colombia",
                            "Comoros",
                            "Cook Islands",
                            "Costa Rica",
                            "Cote d'Ivoire",
                            "Croatia",
                            "Curacao",
                            "Cyprus",
                            "Democratic Republic of the Congo",
                            "Denmark",
                            "Djibouti",
                            "Dominica",
                            "Dominican Republic",
                            "Ecuador",
                            "Egypt",
                            "El Salvador",
                            "Equatorial Guinea",
                            "Eritrea",
                            "Estonia",
                            "Eswatini",
                            "Ethiopia",
                            "Fiji",
                            "Finland",
                            "French Polynesia",
                            "French Southern and Antarctic Lands",
                            "Gabon",
                            "Georgia",
                            "Ghana",
                            "Greece",
                            "Grenada",
                            "Guam",
                            "Guatemala",
                            "Guernsey",
                            "Guinea",
                            "Guinea-Bissau",
                            "Guyana",
                            "Haiti",
                            "Heard Island and McDonald Islands",
                            "Honduras",
                            "Hungary",
                            "Iceland",
                            "India",
                            "Indonesia",
                            "Iraq",
                            "Isle of Man",
                            "Israel",
                            "Jamaica",
                            "Japan",
                            "Jersey",
                            "Jordan",
                            "Kazakhstan",
                            "Kenya",
                            "Kiribati",
                            "Kuwait",
                            "Kyrgyzstan",
                            "Laos",
                            "Latvia",
                            "Lebanon",
                            "Lesotho",
                            "Liberia",
                            "Libya",
                            "Liechtenstein",
                            "Lithuania",
                            "Luxembourg",
                            "Madagascar",
                            "Malawi",
                            "Malaysia",
                            "Maldives",
                            "Mali",
                            "Malta",
                            "Marshall Islands",
                            "Mauritania",
                            "Mauritius",
                            "Mexico",
                            "Micronesia",
                            "Moldova",
                            "Monaco",
                            "Mongolia",
                            "Montenegro",
                            "Morocco",
                            "Mozambique",
                            "Myanmar (Burma)",
                            "Namibia",
                            "Nauru",
                            "Nepal",
                            "New Caledonia",
                            "New Zealand",
                            "Nicaragua",
                            "Niger",
                            "Nigeria",
                            "Niue",
                            "Norfolk Island",
                            "North Macedonia",
                            "Northern Mariana Islands",
                            "Norway",
                            "Oman",
                            "Pakistan",
                            "Palau",
                            "Panama",
                            "Papua New Guinea",
                            "Paraguay",
                            "Peru",
                            "Philippines",
                            "Pitcairn Islands",
                            "Portugal",
                            "Qatar",
                            "Republic of the Congo",
                            "Romania",
                            "Rwanda",
                            "Saint Helena, Ascension and Tristan da Cunha",
                            "Saint Kitts and Nevis",
                            "Saint Lucia",
                            "Saint Martin",
                            "Saint Pierre and Miquelon",
                            "Saint Vincent and the Grenadines",
                            "Samoa",
                            "San Marino",
                            "Sao Tome and Principe",
                            "Saudi Arabia",
                            "Senegal",
                            "Serbia",
                            "Seychelles",
                            "Sierra Leone",
                            "Singapore",
                            "Sint Maarten",
                            "Slovakia",
                            "Slovenia",
                            "Solomon Islands",
                            "Somalia",
                            "South Africa",
                            "South Georgia and the South Sandwich Islands",
                            "South Korea",
                            "Sri Lanka",
                            "Suriname",
                            "Tajikistan",
                            "Tanzania",
                            "Thailand",
                            "The Bahamas",
                            "The Gambia",
                            "Timor-Leste",
                            "Togo",
                            "Tokelau",
                            "Tonga",
                            "Trinidad and Tobago",
                            "Tunisia",
                            "Turkiye",
                            "Turkmenistan",
                            "Tuvalu",
                            "Uganda",
                            "Ukraine",
                            "United Arab Emirates",
                            "United States Minor Outlying Islands",
                            "Uruguay",
                            "Uzbekistan",
                            "Vanuatu",
                            "Vatican City",
                            "Venezuela",
                            "Vietnam",
                            "Wallis and Futuna",
                            "Yemen",
                            "Zambia",
                            "Zimbabwe"
                        ],
                        "type": "string",
                        "description": "Default country for bare city names below (most popular first). Leave Cities empty for a country-wide search. Entries like \"Berlin, DE\" override it per city."
                    },
                    "cities": {
                        "title": "Cities",
                        "type": "array",
                        "description": "City names, one per line. A bare name (\"Warsaw\", \"Kraków\" — English names, diacritics OK) is looked up in the selected Country. Add a country to an entry to mix countries in one run: \"Berlin, DE\", \"Paris, France\", a full location name, or \"lat,lng,zoom\" coordinates. Unknown names are skipped with a did-you-mean suggestion in the log. Leave empty to search the whole selected country.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "language": {
                        "title": "Language",
                        "enum": [
                            "en",
                            "es",
                            "de",
                            "fr",
                            "pl",
                            "nl",
                            "it",
                            "pt",
                            "cs",
                            "sv",
                            "af",
                            "ak",
                            "sq",
                            "am",
                            "ar",
                            "hy",
                            "az",
                            "ban",
                            "eu",
                            "be",
                            "bn",
                            "bs",
                            "bg",
                            "my",
                            "ca",
                            "ceb",
                            "ny",
                            "zh-CN",
                            "zh-TW",
                            "hr",
                            "da",
                            "es-419",
                            "et",
                            "ee",
                            "fo",
                            "fa",
                            "fil",
                            "fi",
                            "fy",
                            "gaa",
                            "gl",
                            "lg",
                            "ka",
                            "el",
                            "gu",
                            "ht",
                            "ha",
                            "he",
                            "iw",
                            "hi",
                            "hu",
                            "is",
                            "bem",
                            "ig",
                            "id",
                            "ga",
                            "ja",
                            "kn",
                            "kk",
                            "km",
                            "rw",
                            "rn",
                            "kg",
                            "ko",
                            "crs",
                            "mfe",
                            "kri",
                            "ckb",
                            "ky",
                            "lo",
                            "lv",
                            "ln",
                            "lt",
                            "ach",
                            "mk",
                            "mg",
                            "ms",
                            "ml",
                            "mt",
                            "mi",
                            "mr",
                            "mn",
                            "sr-ME",
                            "ne",
                            "nso",
                            "no",
                            "nyn",
                            "om",
                            "ps",
                            "pcm",
                            "pt-BR",
                            "pt-PT",
                            "pa",
                            "qu",
                            "ro",
                            "rm",
                            "ru",
                            "sr",
                            "sr-Latn",
                            "st",
                            "sn",
                            "loz",
                            "sd",
                            "si",
                            "sk",
                            "sl",
                            "so",
                            "sw",
                            "tl",
                            "tg",
                            "ta",
                            "te",
                            "th",
                            "ti",
                            "to",
                            "lua",
                            "tn",
                            "tum",
                            "tr",
                            "tk",
                            "uk",
                            "ur",
                            "uz",
                            "vi",
                            "cy",
                            "wo",
                            "xh",
                            "yo",
                            "zu"
                        ],
                        "type": "string",
                        "description": "Language of Google Maps results (most popular first).",
                        "default": "en"
                    },
                    "maxResults": {
                        "title": "Max results per search",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum businesses fetched per search term × location (capped at 5000).",
                        "default": 25
                    },
                    "minResults": {
                        "title": "Min results (stop-loss)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Stop the run BEFORE email extraction & verification if Google Maps finds fewer businesses than this — nothing gets charged. 0 = disabled.",
                        "default": 0
                    },
                    "startUrls": {
                        "title": "Start URLs / domains",
                        "type": "array",
                        "description": "Bring your own list of business websites — skips Google Maps and goes straight to email extraction.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "placeIds": {
                        "title": "Google Place IDs",
                        "type": "array",
                        "description": "Bring your own list of Google Maps place IDs.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxPagesPerSite": {
                        "title": "Max pages per site",
                        "minimum": 1,
                        "maximum": 7,
                        "type": "integer",
                        "description": "How many pages to check per website when hunting for an email, in order: home, /contact, /kontakt, /contact-us, /about, /impressum, /kontakt.html.",
                        "default": 5
                    },
                    "renderJs": {
                        "title": "JavaScript rendering",
                        "enum": [
                            "auto",
                            "always",
                            "never"
                        ],
                        "type": "string",
                        "description": "\"never\" (default) is fastest and cheapest — plain HTTP extraction, no browser. \"auto\" renders in a real browser (via residential proxy) only for sites that block plain requests; it recovers a few extra emails but costs noticeably more, so turn it on only when you want maximum email coverage. \"always\" renders every site (slowest, most expensive).",
                        "default": "never"
                    },
                    "includeNoWebsite": {
                        "title": "Include businesses without a website",
                        "type": "boolean",
                        "description": "Businesses with no website become phone-only leads instead of being dropped.",
                        "default": true
                    },
                    "verifyEmails": {
                        "title": "Verify emails (SMTP deliverability)",
                        "type": "boolean",
                        "description": "Verify each found email for deliverability. Off = faster and cheaper; emails are returned as \"unverified\".",
                        "default": true
                    },
                    "verifyProvider": {
                        "title": "Verification provider",
                        "enum": [
                            "bundled",
                            "byo"
                        ],
                        "type": "string",
                        "description": "\"bundled\" uses our verification service — no setup, verification is included in the per-lead price. \"byo\" uses YOUR OWN Reoon Email Verifier API key (emailverifier.reoon.com → API) — you pay Reoon directly for credits (~$0.0012/verify) instead of us.",
                        "default": "bundled"
                    },
                    "verifyApiKey": {
                        "title": "Your Reoon API key",
                        "type": "string",
                        "description": "Reoon Email Verifier API key (create one at emailverifier.reoon.com → API). Required only when the verification provider is \"byo\"; ignored otherwise."
                    },
                    "emailTypes": {
                        "title": "Email types to keep",
                        "type": "array",
                        "description": "Which email types to include in results: personal (john@…), role (info@, office@…), generic (noreply@, postmaster@…).",
                        "items": {
                            "type": "string",
                            "enum": [
                                "personal",
                                "role",
                                "generic"
                            ],
                            "enumTitles": [
                                "Personal",
                                "Role",
                                "Generic"
                            ]
                        },
                        "default": [
                            "personal",
                            "role"
                        ]
                    },
                    "enrichLeads": {
                        "title": "Enrich leads (owner name, socials, booking platforms)",
                        "type": "boolean",
                        "description": "Find the owner/decision-maker name (Impressum, team pages, JSON-LD Person), social profile links and booking-platform signals from the business website. Adds the lead_enriched event ($). No extra page fetches for most sites - reuses pages already downloaded.",
                        "default": false
                    },
                    "guessPersonalEmails": {
                        "title": "Find & verify personal email of the owner",
                        "type": "boolean",
                        "description": "When an owner name is found and the domain is not catch-all, generate common patterns (anna@, a.kowalska@, anna.kowalska@, kowalska@) and SMTP-verify them. Only VERIFIED hits are charged (personal_email_verified event). Requires enrichLeads and verifyEmails.",
                        "default": false
                    },
                    "dedupeBy": {
                        "title": "Dedupe by",
                        "enum": [
                            "domain",
                            "company",
                            "none"
                        ],
                        "type": "string",
                        "description": "How to deduplicate businesses across searches.",
                        "default": "domain"
                    },
                    "freshData": {
                        "title": "Fresh data (bypass cache)",
                        "type": "boolean",
                        "description": "By default, repeated runs of the same search reuse cached Google Maps results (24 h) and email verifications (30 days) — cheaper and stable. Turn this on to force a fresh live pull.",
                        "default": false
                    },
                    "mode": {
                        "title": "Run mode",
                        "enum": [
                            "full",
                            "incremental"
                        ],
                        "type": "string",
                        "description": "\"full\" returns every matching business each run. \"incremental\" remembers what it already delivered for this search and returns ONLY newly-appeared businesses on later runs — and charges only for those. Ideal for monitoring: run monthly for a niche+city and get just the new openings.",
                        "default": "full"
                    },
                    "runTag": {
                        "title": "Monitor tag",
                        "type": "string",
                        "description": "Optional label that keys the incremental state, so you can keep several independent monitors. Leave empty to key by the search itself (search terms + locations)."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
