# Google Maps Lead Scraper (`solutionssmart/google-maps-lead-scraper`) Actor

Turn Google Maps into an automated sales machine. Identify high-value prospects with built-in lead scoring and contact extraction. Our unique 'Monitor' technology ensures you never scrape the same business twice, delivering fresh, high-intent leads directly to your workflow every day.

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

## Pricing

from $3.00 / 1,000 place extracteds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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.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 Lead Scraper

Stop paying Compute Units to rediscover the same businesses.

**Google Maps Lead Scraper** is an Apify Actor built for teams that need **high-value local targets**, not another generic Google Maps export. It uses **Differential Scraping** to track what has already been seen, detect what changed, and surface only the records worth acting on.

The result: lower CU waste, cleaner pipelines, and a lead list your team can actually use.

---

### ❓ Why this Actor exists

Most Google Maps scrapers are designed for one-time extraction. They return everything, every time.

That is expensive for recurring workflows:

- You spend CUs scanning and re-processing the same market repeatedly.
- Your CRM fills with duplicates.
- Your team wastes time sorting old data from genuinely new opportunities.

**Google Maps Lead Scraper** is designed for recurring intelligence workflows. It remembers what has already been collected and highlights what is new, updated, or commercially interesting.

This is the difference between a scraper and a lead system.

---

### 🔄 Differential Scraping: Pay for New Intelligence, Not Duplicate Exports

The core technology behind this Actor is **Differential Scraping**.

Instead of treating every run as a blank slate, the Actor stores state between runs and compares current results against what it has already seen.

#### ✅ What Differential Scraping gives you

- **Fresh mode** creates a baseline for a market.
- **Incremental mode** outputs only **new** or **updated** businesses.
- **Change detection** flags businesses whose rating, website, phone, category, or other key fields changed.
- **Lower CU waste** because your recurring workflow stops revolving around duplicate exports.
- **Cleaner downstream automation** because your CRM, outreach system, or reporting stack receives net-new intelligence instead of repeated rows.

#### ⚖️ Generic scraper vs. Differential Scraping

| Capability | Google Maps Lead Scraper | Generic Google Maps scraper |
| --- | --- | --- |
| Recurring monitoring | Yes | Usually no |
| Duplicate suppression | Built in | Manual cleanup |
| Change detection | Built in | Not standard |
| CU efficiency for ongoing runs | High | Lower |
| CRM / outreach readiness | Strong | Usually raw export only |

If you run local market scans weekly or daily, this distinction matters.

---

### 🎯 Find High-Value Targets, Not Just More Rows

This Actor is built around **lead intelligence**.

It does not stop at collecting Google Maps fields. It enriches each business and adds built-in scoring so you can prioritize accounts by **Service Need**.

#### 📈 Built-in lead scoring

The Actor outputs:

- `leadScore`
- `leadScoreRaw`
- `leadScoreReasons`
- `isHotLead`
- `leadPriority`
- `opportunityScore`
- `opportunityReason`

These fields help you identify which businesses are more likely to need outside help.

#### 🧭 Service Need categorization

The scoring model is designed to surface businesses with stronger commercial signals, such as:

- missing website or weak digital presence
- missing conversion path or contact form
- incomplete contact data
- reputation gaps
- high rating but underdeveloped marketing footprint

In practice, this helps you sort businesses by **Service Need**:

- **High Service Need**: clear digital gaps, weak conversion setup, or incomplete local presence
- **Medium Service Need**: partially optimized businesses with room for improvement
- **Low Service Need**: businesses that already look operationally mature

The post-processing layer also creates a `ranked-leads` dataset sorted by `leadScore` descending, so you can filter `leadScore > 50` to find hot leads immediately.

This is especially useful for agencies and sales teams that need to decide who to contact first.

---

### 📦 What You Get

From Google Maps:

- business name
- address
- category
- rating
- reviews count
- Google Maps URL
- place ID

With detail-page enrichment:

- phone number
- website
- opening hours
- coordinates

With website enrichment:

- public email addresses
- bounded same-domain crawl of contact/about/team/legal pages
- contact pages
- contact-form detection
- social profiles and LinkedIn discovery
- best available contact route

Lead-ready outputs:

- `leadScore`
- `leadScoreRaw`
- `leadScoreReasons`
- `isHotLead`
- `claimedStatus`
- `leadPriority`
- `opportunityScore`
- `opportunityReason`
- `changeType`
- new vs. updated record detection

---

### 🧑‍💼 Best Use Cases

#### 🔎 SEO Agencies

Find businesses with weak websites, incomplete profiles, or poor local conversion setup. Use incremental runs to continuously surface fresh prospects instead of rebuilding the same list every week.

#### ⭐ Reputation Management

Track businesses with weaker review profiles, recent rating changes, or reputation-related signals. Use recurring scans to spot new targets before competitors do.

#### 🤝 Local B2B Sales

Build territory-based outbound pipelines for verticals like dental, legal, medical, home services, hospitality, and retail. Focus reps on businesses showing the strongest Service Need signals.

---

### ⚡ Quickstart

#### 1. 🏁 Baseline run

Use a fresh run to create your first market snapshot.

```json
{
  "searchQueries": ["dentist"],
  "location": "Berlin, Germany",
  "maxPlaces": 50,
  "leadMode": true,
  "runMode": "fresh",
  "resetState": true,
  "useProxy": true
}
````

#### 2. 🔁 Recurring intelligence run

Use incremental mode to output only new or changed businesses.

```json
{
  "searchQueries": ["dentist"],
  "location": "Berlin, Germany",
  "maxPlaces": 200,
  "leadMode": true,
  "runMode": "incremental",
  "detectUpdates": true,
  "useProxy": true
}
```

#### 3. 📋 Review the lead list

Use the `ranked-leads` dataset for a pre-sorted list, or sort the default dataset by:

1. `leadScore`
2. `leadPriority`
3. `opportunityScore`

Then filter by:

- `leadScore > 50`
- `primaryEmail` not empty
- `hasContactForm = true`
- your preferred geography or category

#### 4. 📍 Pinpoint geolocation

Free-text `location` is usually enough. When you need tighter matching, add `geolocation` fields and let OpenStreetMap/Nominatim resolve a more precise point before the Google Maps run starts. You can verify the same combination on the official OpenStreetMap search page if you want to inspect the match manually.

```json
{
  "searchQueries": ["dentist"],
  "location": "New York, NY",
  "geolocation": {
    "country": "United States",
    "state": "New York",
    "county": "New York County",
    "city": "New York",
    "postalCode": "10001"
  },
  "maxPlaces": 50,
  "leadMode": true
}
```

### 💡 Recommended Workflow for Maximum ROI

1. Run a **fresh baseline** for your target market.
2. Schedule the Actor daily or weekly in **incremental mode**.
3. Export only **new** and **updated** businesses.
4. Push results into your CRM, n8n flow, or outreach system.
5. Prioritize by **Service Need** using `leadPriority`, `opportunityScore`, and `opportunityReason`.

This is where the ROI compounds:

- fewer duplicate rows
- less manual cleaning
- less wasted CU spend
- faster time to outreach

***

### 🛠️ Key Inputs That Matter Most

| Input | What it controls | Recommended starting point |
| --- | --- | --- |
| `searchQueries` | What businesses to look for | One vertical at a time |
| `location` | Where to search | City or region |
| `geolocation` | Precise OSM matching fields | Add `country`, `state`, `county`, `city`, `postalCode` when a city name alone is ambiguous |
| `expandAreaWhenResultsLow` | Opt-in fallback to nearby area searches after a sparse first page | `true` only when plain location searches are too thin |
| `leadMode` | Turns on detail + built-in website enrichment | `true` |
| `runMode` | Baseline vs. recurring intelligence | `fresh` first, then `incremental` |
| `maxPlaces` | Output cap | 50-200 |
| `useProxy` | Reliability on Google Maps | `true` |
| `navigationTimeout` | Stability on slower pages | `90` |

***

### 🗂️ Output Datasets

#### 📄 Default dataset

One row per place, optimized for lead review and export.

Recommended columns to pin:

`leadPriority`, `opportunityScore`, `title`, `categoryName`, `rating`, `reviewsCount`, `primaryEmail`, `phone`, `bestContact`, `website`, `city`, `changeType`, `scrapedAt`

#### ➕ Additional views

| Dataset | When it appears | What it contains |
| --- | --- | --- |
| `default` | Always | Main lead list |
| `place-details` | Detail mode | Flattened place details |
| `changes` | Incremental runs | New / updated rows |
| `list-vs-detail-mismatch` | Detail mode | QA view for list/detail differences |
| `reviews` | `includeReviews = true` | Full review rows |
| `reviews-flat` | `includeReviews = true` | Flat review export |

***

### 💸 CU Efficiency and Cost Control

Apify bills for compute, so efficiency matters.

This Actor is designed to reduce unnecessary CU spend in recurring workflows by:

- avoiding duplicate-heavy output
- skipping already-seen businesses in incremental monitoring workflows
- capping detail fetches with `maxDetailsToFetch`
- letting you control throughput with `maxConcurrency`
- keeping reviews off by default unless you need them

#### ✅ Practical advice

- Use **fresh mode** once to create your baseline.
- Use **incremental mode** for all recurring runs.
- Keep `leadMode: true` if you need sales-ready data.
- Leave `includeReviews: false` unless reviews are part of your offer.
- Use realistic `maxPlaces` caps instead of scanning an entire market every run.

***

### 💳 Billing Model

This Actor uses event-based billing aligned with the work actually completed.

- `place-scraped`: charged once per unique place written to the default dataset
- `profile-opened`: charged when a place detail profile is opened in detail mode
- `contact-enriched`: charged when website contact enrichment produces useful contact data
- `apify-actor-start`: platform start event configured in Apify monetization

#### How billing behaves in practice

- In **fast mode**, billing is usually just `place-scraped`.
- In **deep mode**, a run can additionally emit `profile-opened` and `contact-enriched`.
- Duplicate places found from overlapping Google Maps search URLs are suppressed within the same run before write and before `place-scraped` billing.
- In **incremental mode**, previously seen unchanged places are skipped and are not billed again.
- `contact-enriched` is not emitted for a website visit that produces no useful contact data.

#### What counts as a billable result

For most Store users, the main billable unit is a **unique place written to output**.
Deep-mode detail opening and contact enrichment are separate billable actions because they add cost and value beyond a simple list scrape.

***

### 🔗 Automation-Friendly

This Actor works well with:

- **Apify Schedules** for recurring monitoring
- **n8n** for CRM sync, notifications, or outreach routing
- CSV / Excel exports for sales ops
- webhook-driven internal workflows

Typical pattern:

`Schedule -> Run Actor -> Get Dataset Items -> CRM / Slack / Email / Enrichment`

***

### 🔒 Data & Privacy

This Actor may collect data that qualifies as personal data under GDPR and similar laws, including business contact information and, when enabled, review data.

Use it with a legitimate business purpose and in compliance with applicable law, platform terms, and your internal retention policies.

If you enable reviews or contact enrichment, you are increasing the amount of personal data collected.

***

### 🧾 Bottom Line

If you need a one-time dump of Google Maps data, a basic scraper is enough.

If you need **ongoing market intelligence**, **high-value targets**, and **better CU efficiency**, use **Google Maps Lead Scraper**.

# Actor input Schema

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

One Google Maps search term per item, for example dentist or dental clinic.

## `searchQueriesText` (type: `string`):

Optional newline- or comma-separated search queries. The Actor normalizes this into searchQueries before the crawl starts.

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

Enter a city, region, or country. Example: Berlin, Germany. This stays a standard Google Maps text search unless you also provide geolocation fields or a custom geolocation.

## `geolocation` (type: `object`):

Optional OpenStreetMap/Nominatim fields for more precise matching than free-text location alone.

## `expandAreaWhenResultsLow` (type: `boolean`):

Keep the normal text search first, then explore nearby map areas only if the first search page returns a sparse result set.

## `customGeolocation` (type: `object`):

Optional geometry override for direct point or polygon targeting.

## `categories` (type: `array`):

Optional include filter for Google Maps business categories.

## `excludedCategories` (type: `array`):

Optional exclude filter for categories you do not want in the final dataset.

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

Optional minimum Google rating.

## `businessStatus` (type: `string`):

Filter by open or closed status when Google Maps exposes it.

## `targetCategory` (type: `string`):

Optional category hint used to boost opportunity scoring.

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

Stop when this many valid places have been pushed to the dataset.

## `maxProfiles` (type: `integer`):

Hard cap for successfully opened Google Maps profile pages in deep mode.

## `maxEnrichments` (type: `integer`):

Hard cap for website contact-enrichment attempts in deep mode.

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

Optional secondary cap. If both maxPlaces and maxResults are set, the lower limit wins.

## `maxRunTimeSec` (type: `integer`):

Stop the run once this runtime budget is exceeded to prevent excessive cost.

## `maxCrawledPlacesPerSearch` (type: `integer`):

Optional cap per search query before filtering and post-processing.

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

Fast mode is list-only and cheapest. Deep mode allows profile opening and enrichment with strict caps.

## `openProfiles` (type: `boolean`):

Allow profile-page opening in deep mode. Forced off in fast mode.

## `enableEnrichment` (type: `boolean`):

Allow website contact enrichment in deep mode. Forced off in fast mode.

## `leadMode` (type: `boolean`):

Legacy convenience toggle that switches the Actor into deep mode with profiles and enrichment enabled.

## `includePlaceDetails` (type: `boolean`):

Legacy compatibility flag. In production flows, prefer openProfiles plus mode.

## `includeContacts` (type: `boolean`):

Visit each business website and extract public contact details.

## `includeEnrichment` (type: `boolean`):

Add lead-prioritization fields for downstream sales workflows.

## `generateIcebreakers` (type: `boolean`):

Reserved AI-friendly toggle for downstream workflows.

## `includeReviews` (type: `boolean`):

Collect Google reviews for deeper research.

## `includeImages` (type: `boolean`):

Collect place image metadata when available.

## `includeReviewerNames` (type: `boolean`):

When false, review outputs omit reviewer names.

## `minimalLogging` (type: `boolean`):

Reduce place titles, full addresses, and full URLs in logs.

## `useProxy` (type: `boolean`):

Recommended for better reliability on Google Maps.

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

Overall browser concurrency for the crawl.

## `detailsConcurrency` (type: `integer`):

Optional separate concurrency for detail-page work when enableDetailsConcurrencyOverride is true.

## `enableDetailsConcurrencyOverride` (type: `boolean`):

Use detailsConcurrency instead of maxConcurrency for detail pages.

## `contactEnrichmentConcurrency` (type: `integer`):

Optional separate concurrency for website contact enrichment.

## `rateLimit` (type: `string`):

Pick a crawl pacing strategy.

## `navigationTimeout` (type: `integer`):

Increase if Google Maps or target websites are slow.

## `maxDetailsToFetch` (type: `integer`):

Optional cap for detail-page enrichment.

## `runMode` (type: `string`):

Use fresh for a baseline and incremental for new or changed businesses only.

## `detectUpdates` (type: `boolean`):

When incremental mode is enabled, compare current results with saved state.

## `stateKey` (type: `string`):

Key-value store record used for incremental state.

## `resetState` (type: `boolean`):

Delete the saved incremental snapshot before the run starts.

## `dedupeStrategy` (type: `string`):

Choose how recurring runs identify the same business.

## `updateFields` (type: `array`):

Fields compared between runs to detect updates.

## `enableCaching` (type: `boolean`):

Reuse cached place enrichments across runs.

## `incrementalUpdate` (type: `boolean`):

Refresh cached entries as new data arrives.

## `streamResults` (type: `boolean`):

Enable result streaming hooks during the run.

## `cache` (type: `object`):

Optional cache backend tuning.

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

Optional Google Maps place IDs for direct detail scraping.

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

Optional Google Maps place URLs for direct detail scraping.

## `exportFormat` (type: `string`):

Optional downstream export preference used by local helpers.

## `compressOutput` (type: `boolean`):

Optional downstream export flag for local helpers.

## `saveSearchResults` (type: `boolean`):

Save list-view places to the search-results dataset for later direct-detail runs.

## `n8nEvent` (type: `object`):

Optional raw n8n workflow event input.

## `n8nFieldMapping` (type: `object`):

Optional mapping from incoming n8n fields to canonical Actor input fields.

## `n8nPromptMaxBytes` (type: `integer`):

Maximum bytes copied into the synthesized n8n prompt field.

## `n8nLateEventThresholdSeconds` (type: `integer`):

Treat events older than this threshold as late.

## `n8nPromptField` (type: `string`):

Destination field name for the synthesized n8n prompt.

## `openClaw` (type: `object`):

Optional gateway integration for forwarding scraped places.

## Actor input object example

```json
{
  "searchQueries": [
    "dentist"
  ],
  "location": "Berlin, Germany",
  "expandAreaWhenResultsLow": false,
  "businessStatus": "any",
  "maxPlaces": 50,
  "maxProfiles": 30,
  "maxEnrichments": 20,
  "maxResults": 50,
  "maxRunTimeSec": 120,
  "mode": "fast",
  "openProfiles": false,
  "enableEnrichment": false,
  "leadMode": false,
  "includePlaceDetails": false,
  "includeContacts": false,
  "includeEnrichment": false,
  "generateIcebreakers": false,
  "includeReviews": false,
  "includeImages": false,
  "useProxy": true,
  "maxConcurrency": 2,
  "rateLimit": "adaptive",
  "navigationTimeout": 90,
  "runMode": "fresh",
  "detectUpdates": true,
  "stateKey": "places-state",
  "resetState": false
}
```

# Actor output Schema

## `defaultDatasetId` (type: `string`):

No description

## `defaultDatasetUrl` (type: `string`):

No description

## `keyValueStoreId` (type: `string`):

No description

# 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 = {
    "searchQueries": [
        "dentist"
    ],
    "location": "Berlin, Germany"
};

// Run the Actor and wait for it to finish
const run = await client.actor("solutionssmart/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 = {
    "searchQueries": ["dentist"],
    "location": "Berlin, Germany",
}

# Run the Actor and wait for it to finish
run = client.actor("solutionssmart/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 '{
  "searchQueries": [
    "dentist"
  ],
  "location": "Berlin, Germany"
}' |
apify call solutionssmart/google-maps-lead-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Lead Scraper",
        "description": "Turn Google Maps into an automated sales machine. Identify high-value prospects with built-in lead scoring and contact extraction. Our unique 'Monitor' technology ensures you never scrape the same business twice, delivering fresh, high-intent leads directly to your workflow every day.",
        "version": "1.0",
        "x-build-id": "pfgbURja4V2TbPJfV"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/solutionssmart~google-maps-lead-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-solutionssmart-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/solutionssmart~google-maps-lead-scraper/runs": {
            "post": {
                "operationId": "runs-sync-solutionssmart-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/solutionssmart~google-maps-lead-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-solutionssmart-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": {
                    "searchQueries": {
                        "title": "🔎 Search queries",
                        "type": "array",
                        "description": "One Google Maps search term per item, for example dentist or dental clinic.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchQueriesText": {
                        "title": "📝 Bulk search queries text",
                        "type": "string",
                        "description": "Optional newline- or comma-separated search queries. The Actor normalizes this into searchQueries before the crawl starts."
                    },
                    "location": {
                        "title": "📍 Where should we search?",
                        "pattern": "^(?=.*\\S).{2,120}$",
                        "minLength": 2,
                        "maxLength": 120,
                        "type": "string",
                        "description": "Enter a city, region, or country. Example: Berlin, Germany. This stays a standard Google Maps text search unless you also provide geolocation fields or a custom geolocation."
                    },
                    "geolocation": {
                        "title": "🧭 Geolocation parameters",
                        "type": "object",
                        "description": "Optional OpenStreetMap/Nominatim fields for more precise matching than free-text location alone.",
                        "properties": {
                            "country": {
                                "title": "🌍 Country",
                                "type": "string",
                                "description": "Optional country name for OpenStreetMap matching, for example Germany or United States.",
                                "editor": "textfield",
                                "maxLength": 80
                            },
                            "state": {
                                "title": "🧭 State or region",
                                "type": "string",
                                "description": "Optional state, province, or region.",
                                "editor": "textfield",
                                "maxLength": 80
                            },
                            "county": {
                                "title": "📌 County",
                                "type": "string",
                                "description": "Optional county or district name.",
                                "editor": "textfield",
                                "maxLength": 80
                            },
                            "city": {
                                "title": "🏙️ City",
                                "type": "string",
                                "description": "Optional city or municipality name.",
                                "maxLength": 80
                            },
                            "postalCode": {
                                "title": "🏷️ Postal code",
                                "type": "string",
                                "description": "Optional ZIP or postal code for more precise matching.",
                                "editor": "textfield",
                                "maxLength": 20
                            }
                        },
                        "additionalProperties": false
                    },
                    "expandAreaWhenResultsLow": {
                        "title": "🗺️ Expand area when results are low",
                        "type": "boolean",
                        "description": "Keep the normal text search first, then explore nearby map areas only if the first search page returns a sparse result set.",
                        "default": false
                    },
                    "customGeolocation": {
                        "title": "📐 Custom geolocation",
                        "type": "object",
                        "description": "Optional geometry override for direct point or polygon targeting.",
                        "properties": {
                            "type": {
                                "title": "🔷 Geometry type",
                                "type": "string",
                                "description": "GeoJSON geometry type to use for the custom geolocation.",
                                "editor": "select",
                                "enum": [
                                    "Polygon",
                                    "MultiPolygon",
                                    "Point"
                                ]
                            },
                            "coordinates": {
                                "title": "📍 Coordinates",
                                "type": "array",
                                "description": "GeoJSON-style coordinates. Use coordinatesJson when editing raw JSON is easier.",
                                "editor": "json"
                            },
                            "radiusKm": {
                                "title": "📏 Radius in km",
                                "type": "number",
                                "description": "Radius around the point when type is Point.",
                                "minimum": 0
                            },
                            "latitude": {
                                "title": "↕️ Latitude",
                                "type": "number",
                                "description": "Latitude used when passing a point as latitude and longitude instead of coordinates.",
                                "minimum": -90,
                                "maximum": 90
                            },
                            "longitude": {
                                "title": "↔️ Longitude",
                                "type": "number",
                                "description": "Longitude used when passing a point as latitude and longitude instead of coordinates.",
                                "minimum": -180,
                                "maximum": 180
                            },
                            "coordinatesJson": {
                                "title": "🧾 Coordinates JSON",
                                "type": "string",
                                "description": "Raw JSON string for GeoJSON coordinates.",
                                "editor": "textarea"
                            }
                        },
                        "additionalProperties": false
                    },
                    "categories": {
                        "title": "✅ Included categories",
                        "type": "array",
                        "description": "Optional include filter for Google Maps business categories.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "excludedCategories": {
                        "title": "🚫 Excluded categories",
                        "type": "array",
                        "description": "Optional exclude filter for categories you do not want in the final dataset.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "minRating": {
                        "title": "⭐ Minimum rating",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "number",
                        "description": "Optional minimum Google rating."
                    },
                    "businessStatus": {
                        "title": "🏢 Business status",
                        "enum": [
                            "any",
                            "open_now",
                            "exclude_temporarily_closed",
                            "exclude_permanently_closed"
                        ],
                        "type": "string",
                        "description": "Filter by open or closed status when Google Maps exposes it.",
                        "default": "any"
                    },
                    "targetCategory": {
                        "title": "📈 Target category",
                        "minLength": 2,
                        "maxLength": 80,
                        "type": "string",
                        "description": "Optional category hint used to boost opportunity scoring."
                    },
                    "maxPlaces": {
                        "title": "📦 Maximum dataset items",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Stop when this many valid places have been pushed to the dataset.",
                        "default": 50
                    },
                    "maxProfiles": {
                        "title": "👤 Maximum profiles to open",
                        "minimum": 0,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Hard cap for successfully opened Google Maps profile pages in deep mode.",
                        "default": 30
                    },
                    "maxEnrichments": {
                        "title": "💳 Maximum enrichments",
                        "minimum": 0,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Hard cap for website contact-enrichment attempts in deep mode.",
                        "default": 20
                    },
                    "maxResults": {
                        "title": "🛑 Maximum processed results",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Optional secondary cap. If both maxPlaces and maxResults are set, the lower limit wins.",
                        "default": 50
                    },
                    "maxRunTimeSec": {
                        "title": "⏰ Maximum runtime in seconds",
                        "minimum": 1,
                        "maximum": 3600,
                        "type": "integer",
                        "description": "Stop the run once this runtime budget is exceeded to prevent excessive cost.",
                        "default": 120
                    },
                    "maxCrawledPlacesPerSearch": {
                        "title": "🔢 Maximum crawled places per search",
                        "minimum": 1,
                        "maximum": 100000,
                        "type": "integer",
                        "description": "Optional cap per search query before filtering and post-processing."
                    },
                    "mode": {
                        "title": "🏎️ Execution mode",
                        "enum": [
                            "fast",
                            "deep"
                        ],
                        "type": "string",
                        "description": "Fast mode is list-only and cheapest. Deep mode allows profile opening and enrichment with strict caps.",
                        "default": "fast"
                    },
                    "openProfiles": {
                        "title": "🔓 Open profiles",
                        "type": "boolean",
                        "description": "Allow profile-page opening in deep mode. Forced off in fast mode.",
                        "default": false
                    },
                    "enableEnrichment": {
                        "title": "🧪 Enable enrichment",
                        "type": "boolean",
                        "description": "Allow website contact enrichment in deep mode. Forced off in fast mode.",
                        "default": false
                    },
                    "leadMode": {
                        "title": "✨ Lead mode",
                        "type": "boolean",
                        "description": "Legacy convenience toggle that switches the Actor into deep mode with profiles and enrichment enabled.",
                        "default": false
                    },
                    "includePlaceDetails": {
                        "title": "🗂️ Include place details",
                        "type": "boolean",
                        "description": "Legacy compatibility flag. In production flows, prefer openProfiles plus mode.",
                        "default": false
                    },
                    "includeContacts": {
                        "title": "📬 Include contacts",
                        "type": "boolean",
                        "description": "Visit each business website and extract public contact details.",
                        "default": false
                    },
                    "includeEnrichment": {
                        "title": "🧠 Include lead enrichment",
                        "type": "boolean",
                        "description": "Add lead-prioritization fields for downstream sales workflows.",
                        "default": false
                    },
                    "generateIcebreakers": {
                        "title": "💬 Generate icebreakers",
                        "type": "boolean",
                        "description": "Reserved AI-friendly toggle for downstream workflows.",
                        "default": false
                    },
                    "includeReviews": {
                        "title": "📝 Include reviews",
                        "type": "boolean",
                        "description": "Collect Google reviews for deeper research.",
                        "default": false
                    },
                    "includeImages": {
                        "title": "🖼️ Include images",
                        "type": "boolean",
                        "description": "Collect place image metadata when available.",
                        "default": false
                    },
                    "includeReviewerNames": {
                        "title": "🙍 Include reviewer names",
                        "type": "boolean",
                        "description": "When false, review outputs omit reviewer names."
                    },
                    "minimalLogging": {
                        "title": "🤫 Minimal logging",
                        "type": "boolean",
                        "description": "Reduce place titles, full addresses, and full URLs in logs."
                    },
                    "useProxy": {
                        "title": "🛡️ Use Apify Proxy",
                        "type": "boolean",
                        "description": "Recommended for better reliability on Google Maps.",
                        "default": true
                    },
                    "maxConcurrency": {
                        "title": "⚡ Maximum concurrency",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Overall browser concurrency for the crawl.",
                        "default": 2
                    },
                    "detailsConcurrency": {
                        "title": "🧵 Details concurrency override",
                        "minimum": 1,
                        "maximum": 10,
                        "type": "integer",
                        "description": "Optional separate concurrency for detail-page work when enableDetailsConcurrencyOverride is true."
                    },
                    "enableDetailsConcurrencyOverride": {
                        "title": "🎚️ Enable details concurrency override",
                        "type": "boolean",
                        "description": "Use detailsConcurrency instead of maxConcurrency for detail pages."
                    },
                    "contactEnrichmentConcurrency": {
                        "title": "🌐 Contact enrichment concurrency",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Optional separate concurrency for website contact enrichment."
                    },
                    "rateLimit": {
                        "title": "⏱️ Rate limit mode",
                        "enum": [
                            "adaptive",
                            "conservative",
                            "moderate",
                            "aggressive"
                        ],
                        "type": "string",
                        "description": "Pick a crawl pacing strategy.",
                        "default": "adaptive"
                    },
                    "navigationTimeout": {
                        "title": "⏳ Navigation timeout in seconds",
                        "minimum": 10,
                        "maximum": 300,
                        "type": "integer",
                        "description": "Increase if Google Maps or target websites are slow.",
                        "default": 90
                    },
                    "maxDetailsToFetch": {
                        "title": "🚪 Maximum detail pages to open",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Optional cap for detail-page enrichment."
                    },
                    "runMode": {
                        "title": "💾 Run mode",
                        "enum": [
                            "fresh",
                            "incremental"
                        ],
                        "type": "string",
                        "description": "Use fresh for a baseline and incremental for new or changed businesses only.",
                        "default": "fresh"
                    },
                    "detectUpdates": {
                        "title": "🔁 Detect updates",
                        "type": "boolean",
                        "description": "When incremental mode is enabled, compare current results with saved state.",
                        "default": true
                    },
                    "stateKey": {
                        "title": "🗃️ State key",
                        "type": "string",
                        "description": "Key-value store record used for incremental state.",
                        "default": "places-state"
                    },
                    "resetState": {
                        "title": "♻️ Reset saved state",
                        "type": "boolean",
                        "description": "Delete the saved incremental snapshot before the run starts.",
                        "default": false
                    },
                    "dedupeStrategy": {
                        "title": "🧩 Dedupe strategy",
                        "enum": [
                            "placeId",
                            "hash"
                        ],
                        "type": "string",
                        "description": "Choose how recurring runs identify the same business."
                    },
                    "updateFields": {
                        "title": "📋 Tracked update fields",
                        "type": "array",
                        "description": "Fields compared between runs to detect updates.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "enableCaching": {
                        "title": "🚀 Enable caching",
                        "type": "boolean",
                        "description": "Reuse cached place enrichments across runs."
                    },
                    "incrementalUpdate": {
                        "title": "🔄 Incremental cache updates",
                        "type": "boolean",
                        "description": "Refresh cached entries as new data arrives."
                    },
                    "streamResults": {
                        "title": "📡 Stream results",
                        "type": "boolean",
                        "description": "Enable result streaming hooks during the run."
                    },
                    "cache": {
                        "title": "🧰 Cache configuration",
                        "type": "object",
                        "description": "Optional cache backend tuning.",
                        "properties": {
                            "redisUrl": {
                                "title": "🔗 Redis URL",
                                "type": "string",
                                "description": "Optional Redis connection string for persistent cache storage."
                            },
                            "namespace": {
                                "title": "🧱 Namespace",
                                "type": "string",
                                "description": "Namespace prefix for cache keys."
                            },
                            "ttlSeconds": {
                                "title": "⏲️ TTL in seconds",
                                "type": "integer",
                                "description": "Time-to-live for cache entries.",
                                "minimum": 1,
                                "maximum": 604800
                            },
                            "maxKeys": {
                                "title": "🔐 Maximum keys",
                                "type": "integer",
                                "description": "Limit the in-memory cache size.",
                                "minimum": 1,
                                "maximum": 50000
                            }
                        },
                        "additionalProperties": false
                    },
                    "placeIds": {
                        "title": "🆔 Direct place IDs",
                        "type": "array",
                        "description": "Optional Google Maps place IDs for direct detail scraping.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "placeUrls": {
                        "title": "🔗 Direct place URLs",
                        "type": "array",
                        "description": "Optional Google Maps place URLs for direct detail scraping.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "exportFormat": {
                        "title": "📤 Export format hint",
                        "enum": [
                            "json",
                            "csv",
                            "excel"
                        ],
                        "type": "string",
                        "description": "Optional downstream export preference used by local helpers."
                    },
                    "compressOutput": {
                        "title": "🗜️ Compress output",
                        "type": "boolean",
                        "description": "Optional downstream export flag for local helpers."
                    },
                    "saveSearchResults": {
                        "title": "💽 Save search-results dataset",
                        "type": "boolean",
                        "description": "Save list-view places to the search-results dataset for later direct-detail runs."
                    },
                    "n8nEvent": {
                        "title": "🔔 n8n event payload",
                        "type": "object",
                        "description": "Optional raw n8n workflow event input."
                    },
                    "n8nFieldMapping": {
                        "title": "🧭 n8n field mapping",
                        "type": "object",
                        "description": "Optional mapping from incoming n8n fields to canonical Actor input fields."
                    },
                    "n8nPromptMaxBytes": {
                        "title": "📏 n8n prompt max bytes",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum bytes copied into the synthesized n8n prompt field."
                    },
                    "n8nLateEventThresholdSeconds": {
                        "title": "⏰ n8n late-event threshold seconds",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Treat events older than this threshold as late."
                    },
                    "n8nPromptField": {
                        "title": "📝 n8n prompt field",
                        "type": "string",
                        "description": "Destination field name for the synthesized n8n prompt."
                    },
                    "openClaw": {
                        "title": "🦞 OpenClaw integration",
                        "type": "object",
                        "description": "Optional gateway integration for forwarding scraped places.",
                        "properties": {
                            "enabled": {
                                "title": "✅ Enabled",
                                "type": "boolean",
                                "description": "Forward scraped places to the OpenClaw gateway."
                            },
                            "gatewayUrl": {
                                "title": "🌉 Gateway URL",
                                "type": "string",
                                "description": "Base URL of the OpenClaw gateway."
                            },
                            "token": {
                                "title": "🔐 Gateway token",
                                "type": "string",
                                "description": "Optional OpenClaw token. Prefer environment variables or Apify secrets for production runs.",
                                "editor": "textfield"
                            },
                            "agentId": {
                                "title": "🤖 Agent ID",
                                "type": "string",
                                "description": "Agent identifier used by the gateway."
                            },
                            "concurrency": {
                                "title": "⚡ Concurrency",
                                "type": "integer",
                                "description": "Maximum number of in-flight gateway requests.",
                                "minimum": 1,
                                "maximum": 20
                            },
                            "sendMode": {
                                "title": "📨 Send mode",
                                "type": "string",
                                "description": "Send each place immediately or in batches.",
                                "editor": "select",
                                "enum": [
                                    "perPlace",
                                    "batch"
                                ]
                            },
                            "batchSize": {
                                "title": "📦 Batch size",
                                "type": "integer",
                                "description": "Batch size when sendMode is batch.",
                                "minimum": 1
                            },
                            "api": {
                                "title": "🧪 API",
                                "type": "string",
                                "description": "OpenAI-compatible API surface exposed by the gateway.",
                                "editor": "select",
                                "enum": [
                                    "responses",
                                    "chatCompletions"
                                ]
                            }
                        },
                        "additionalProperties": false
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
