# Google Maps Results Processor — clean, filtered outreach leads (`vasram/google-maps-results-converter`) Actor

Turn raw Google Maps Scraper (compass/crawler-google-places) output into clean, flat, filtered, outreach-ready files: CSV, Excel, Instantly, Smartlead, GoHighLevel, HubSpot and dialer formats.

- **URL**: https://apify.com/vasram/google-maps-results-converter.md
- **Developed by:** [Vasram Sonagara](https://apify.com/vasram) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 records processeds

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Google Maps Results Converter — Clean, Filter, Score & Export Google Maps Scraper Results to CSV, Excel, GoHighLevel, Instantly & HubSpot

> **Turn raw [Google Maps Scraper](https://apify.com/compass/crawler-google-places) output into clean, deduplicated, scored outreach leads in seconds — then slice it into EVERY lead list you sell from a single scrape.** Flattens 80+ nested fields into spreadsheet-ready columns, normalizes phone numbers to international E.164 format, removes closed businesses and duplicates, scores every lead 0–100, detects what changed since last week's scrape, and exports ready-to-import CSV files for **GoHighLevel (GHL), Instantly, Smartlead, HubSpot, Excel, and dialers** — no coding required.

***

### What is this Google Maps results converter?

[Google Maps Scraper by compass](https://apify.com/compass/crawler-google-places) returns deeply nested JSON: opening hours arrays, review distributions, category lists, split review records for popular venues. If you export that raw dataset directly to CSV, your spreadsheet breaks, phone numbers arrive in inconsistent local formats, the same business appears once per search-grid cell, and finding real prospects takes hours of manual work in Excel.

**This converter actor fixes all of that in one run:**

1. **Flattens 80+ fields** into one clean row per business — zero nested arrays, import-ready for any CRM or database.
2. **Deduplicates places** that appear in multiple overlapping search areas, and stitches review-split records for venues with more than 5,000 reviews.
3. **Removes permanently & temporarily closed businesses** so your lead list only contains active companies.
4. **Normalizes phone numbers to E.164** (`+15551234567`) using full international phone parsing — US, UK, EU and worldwide formats, dialer-safe.
5. **Filters leads** by rating, review count, website presence, phone/email availability, claimed profile status, category, and city.
6. **Scores every lead 0–100** with a deterministic algorithm — no AI costs, no API keys needed.
7. **Exports CSV, Excel (.xlsx), JSON** plus CRM-specific files for **GoHighLevel, Instantly, Smartlead, HubSpot, and phone dialers**.

***

### Quick start (3 steps)

#### Step 1 — Scrape your Google Maps data

Run [Google Maps Scraper (`compass/crawler-google-places`)](https://apify.com/compass/crawler-google-places). When it finishes, copy the **Dataset ID** from the run page (Storage tab).

#### Step 2 — Configure this actor

1. **Data source:** paste the Dataset ID into *Dataset ID (from Google Maps Scraper)* — or paste a raw JSON array instead. **If both are provided, the Dataset ID takes priority.** Multiple cities? Paste several IDs into *multiple Dataset IDs* to merge them.
2. **Lead type:** pick a ready-made preset (see the [preset table](#column-presets--lead-types)) — each preset also **enforces the filters its title promises**. Need every list at once? Select two or more in *Multiple lead types in ONE run*.
3. **Filters (optional):** min rating, min reviews, website presence, phone/email, claimed status, categories, cities.
4. **Export format:** `csv`, `excel`, `gohighlevel`, `instantly`, `smartlead`, `hubspot`, `json` — any combination.
5. **File name (optional):** your downloads are named after it, e.g. `austin-leads.csv`, `austin-leads.instantly.csv`.
6. **Weekly scraping? (optional)** set *Baseline Dataset ID* to last week's run for [delta detection](#master-list--delta-detection-see-what-changed-since-last-scrape).

#### Step 3 — Run and download

Click **Start**. Within seconds open the **Storage → Key-Value Store** tab and download your cleaned lead files.

***

### Top use cases (one click each)

#### 🌐 Web design & SEO leads — businesses WITHOUT a website

Local businesses with no website are the highest-intent prospects for web design, funnels, and local SEO services.

- **Preset:** `web-design-prospects` — automatically keeps only **active businesses with no website and a valid phone number** (the preset enforces these filters for you).
- **Manual route:** set *Website status* → `Only WITHOUT a website`.

#### ⭐ Reputation management leads — low-rated businesses

Businesses losing customers to unanswered negative reviews need review software and response automation.

- **Preset:** `reputation-prospects` — automatically keeps **active businesses rated below 4.0 stars**.
- **Manual route:** set the API-only `filters_ratingBelow` field to `4.0`, or *Minimum rating* plus a review on unanswered negatives.

#### 📍 Unclaimed Google Business Profiles (GMB/GMP optimization leads)

Unclaimed listings rank worse and can be hijacked — perfect for GBP verification and optimization services.

- Set *Google Profile claimed status* → `Only UNCLAIMED profiles`.

#### 📞 Cold calling lists — dialer-ready phone numbers

- **Preset:** `cold-calling` — keeps only places with a phone number, normalized to E.164 (`+1…`, `+44…`), with hours and full address columns.
- Dialer export: add `dialer` to export formats (API) for a power-dialer friendly file.

#### ✉️ Cold email lists — Instantly & Smartlead campaign CSVs

- **Preset:** `cold-email` — contact names, emails, and personalization columns.
- Select `instantly` or `smartlead` in **Export formats** for campaign files with custom variables (`{{leadScore}}`, `{{categoryName}}`, `{{city}}`) already mapped.
- ⚠️ Emails require the upstream scraper run to have **`scrapeContacts`** enabled (see [FAQ](#faq)).

#### 🚀 One-click GoHighLevel (GHL) contact import

Select `gohighlevel` in export formats: first/last names derived from the business title, E.164 phones, no-contact rows excluded, ready for the GHL contacts CSV importer.

***

### One run, every lead list (multi-segment export)

Most agencies sell several services — websites, reputation, cold calling, cold email — but a scraper gives you one raw dump and changing filters there means **paying for a full re-scrape and waiting again**.

Fill **Multiple lead types in ONE run** (`fields_presets`) with two or more presets and this actor produces **a complete file-set per lead type from the same scrape**, each with its promised filters enforced:

- `leads.web-design-prospects.csv` — active businesses with no website + phone
- `leads.reputation-prospects.csv` — rated below 4.0
- `leads.cold-calling.csv` / `leads.cold-email.instantly.csv` / … — every format you selected, per segment
- `leads.segments.csv` — one overview table: records, with-phone, with-email, without-website, average lead score per segment (also added as a Segments sheet inside every Excel file)

One scrape in → every campaign list out. Leave the field empty and behavior is exactly the classic single-list flow.

### Master list & delta detection (see what changed since last scrape)

Scrape the same city every week? Point **Baseline Dataset ID** (`delta_baselineDatasetId`) at last week's scraper run and this actor diffs the two scrapes by Google's own place IDs, reporting:

- 🆕 **new businesses** — exported as `{fileName}.new.csv` (in every selected format) so you call them first
- 🚫 **closed since last run** and 🔁 **reopened** places
- 📍 **claimed-status changes** — now-unclaimed profiles are fresh GBP-optimization leads; now-claimed means your client (or a competitor) acted
- 👻 **missing from this scrape** — places that vanished from this week's results

All counts land in the run summary and the Excel Summary sheet. API users can also pass a previous JSON export via `delta_baselineJson`. Comparisons use dedup-time place keys, so overlapping search grids and split review records never skew the diff.

### Stop paying for scraper filters

The Google Maps Scraper charges **~$0.001 per place, per filter, per run** for rating/website/closed filters — and every changed mind is another paid re-scrape:

| | Scraper filter add-ons | This actor |
|---|---|---|
| Cost | ~$0.001 × places × filters, **every run** | Included — you already own the data |
| Changing your mind | Full re-scrape (minutes + cost) | Instant re-slice of the same dataset |
| 10,000 places × 3 filters | **~$30 extra per run** | **$0 extra** (Apify compute only) |

Scrape **broad once** (no filter add-ons, keep `skipClosedPlaces` off), then slice, filter, score and export unlimited lists here. The run log even detects when your upstream scrape already paid for a skip-closed filter and tells you how to avoid it next time.

### Merge multiple scraper runs into one master list

Agencies scrape city by city. Paste several Dataset IDs into **…or multiple Dataset IDs** (`source_datasetIds`) and every run is merged into one deduplicated master list — the same business found in two city datasets is kept once (best copy wins, reviews stitched). Combine with any filters, presets and export formats. Perfect for territory rollups and weekly master-list refreshes.

### Forward compatible — compass output changes can't break your runs

When the upstream scraper adds new fields tomorrow, this actor keeps working: unknown scalar fields are detected, logged once, and passed through to the dataset untouched (see the `compatibility` section of the run summary), and a single malformed record is skipped with a traceable issue instead of failing the run. Structured arrays from new fields are simply ignored rather than crashing the export.

***

### Column presets & lead types

Presets select the best columns **and** enforce the filters promised in their name (enforced values override manually set conflicting filters — the run log states every enforcement).

| Preset | Best for | Columns included | Filters enforced |
|---|---|---|---|
| `simple-leads` | Clean general lead lists | Name, category, phone (E.164), website, address, city, state, rating, reviews, Maps link, claimed flag | — |
| `lead-scoring` | Prioritized agency prospecting | Everything in simple leads + lead score, lead type, Bayesian rating, completeness % | — |
| `web-design-prospects` | Web design / dev agencies | Name, website flag, phone, rating, reviews, city, Maps link | no website, has phone, closed removed |
| `reputation-prospects` | Reputation software & services | Name, phone, rating, reviews, negative %, unanswered negatives, latest review, city | rating below 4.0, closed removed |
| `cold-calling` | Call centers & phone outreach | Name, E.164 phone, phone-valid flag, hours, address, rating, Maps link | has phone, closed removed |
| `cold-email` | Instantly / Smartlead campaigns | Email, contact names, phone, website, category, city, AI opener (optional), Maps link, claimed flag | has email, closed removed |
| `full-flat` | Analysts & data warehouses | **All 80+ flattened columns**, nothing omitted | — |
| `custom` | Power users (API) | Any subset via `fields_customColumns` | — |

***

### Filters reference

| Filter | Field | Values / meaning |
|---|---|---|
| Website status | `filters_websitePresence` | `any`, `withWebsite`, `withoutWebsite` |
| Minimum rating | `filters_minRating` | 1.0–5.0, keeps `totalScore ≥` value; records with no rating only pass when no threshold is set |
| Minimum reviews | `filters_minReviews` | keeps `reviewsCount ≥` value |
| Has phone | `filters_hasPhone` | `true` = only places with a valid phone |
| Has email | `filters_hasEmail` | `true` = only places with an email (needs `scrapeContacts`) — auto-skipped with a warning if the source data contains no emails |
| Claimed status | `filters_claimed` | `any`, `claimed`, `unclaimed` |
| Categories | `filters_categoriesInclude` | keep only these categories (case-insensitive) |
| Cities | `filters_cities` | smart matching: exact match, diacritics ignored, `"New York City"` also matches `"New York"` |

**Additional filters (API only):** `filters_maxRating`, `filters_maxReviews`, `filters_ratingBelow`, `filters_categoriesExclude`, `filters_categoryMatch`, `filters_states`, `filters_postalCodes`, `filters_excludeAds`, `filters_excludeChains`, `filters_minUnansweredNegatives`, `filters_latestReviewWithinDays`, `filters_hasSocialProfiles`, `filters_externalPlaces`, `filters_openAtScrapeTime`.

***

### Cleaning & deduplication

| Setting | Default | What it does |
|---|---|---|
| `dedup_enabled` | `true` | Merges duplicate places across overlapping search grids. Key chain: `placeId → cid → fid → externalId → title+address` (directory children are never merged into their parent). |
| `dedup_keep` (API) | `first` | `first`, `last`, or `best` (most reviews → best rank → non-closed copy). A closed copy never wins when an open duplicate exists. |
| `dedup_mergeReviews` (API) | `true` | Stitches review-split records (venues with >5,000 reviews are exported by the scraper as multiple rows). |
| `clean_removeClosed` | `true` | Drops permanently/temporarily closed businesses (handles both boolean and string flags). |
| `clean_normalizePhones` | `true` | E.164 via full international parsing using the record's `countryCode` — handles UK/EU trunk prefixes, US formats, extensions. |
| `clean_removeNoContact` (API) | `false` | Drops records with neither phone, email, nor website. |
| `clean_splitAddresses` (API) | `true` | Splits the raw address into street, city, state, ZIP columns. |

**Scale:** up to 100,000 records per run. For large jobs always use the Dataset ID — data streams through in two passes instead of being pasted into the input.

***

### Algorithmic lead scoring (no AI, no extra cost)

Every record is scored 0–100 by a deterministic engine — the same list always produces the same scores:

**Base signals (every record):**

| Signal | Points | Why it matters |
|---|---|---|
| Valid phone (E.164) | +15 | Reachable lead |
| Has website | +10 | Online presence |
| Has email | +10 | Direct outreach channel |
| 100+ reviews | +15 | Established business |
| 50–99 reviews | +10 | Growing business |
| Rating ≥ 4.8 | +10 | Top performer |
| Rating ≥ 4.0 | +5 | Good reputation |

**Agency opportunity gaps (awarded only when the business is reachable — has phone, email, or 5+ reviews):**

| Signal | Points | Why it matters |
|---|---|---|
| No website | +30 | High-ticket web design / funnel prospect |
| Unclaimed listing | +25 | GBP optimization candidate |
| Rating < 4.0 with 20+ reviews | +20 | Reputation management prospect |
| Rating ≥ 4.5 with < 15 reviews | +15 | Great service, needs review generation |
| Fewer than 5 photos | +10 | Incomplete profile — SEO/photography services |
| Missing opening hours | +10 | Poor profile hygiene |

Built-in analytics: **Bayesian weighted rating** (a 4.8★ with 800 reviews properly outranks a 5.0★ with 1), **profile completeness %**, **owner response rate on negative reviews**, and a **review polarization index**. Configure via API fields `scoring_enabled` and `scoring_enableResponseRate`.

***

### AI enhancements (optional, off by default)

Set `ai.provider` to `openai` (your `ai.openaiApiKey` or the `OPENAI_API_KEY` env var) or `apify-openai` (billed via Apify) to generate pain-point summaries, praise points, personalized cold-email opening lines, and business summaries. Deterministic output is always kept as a fallback — an AI outage never breaks your export. `ai.maxRecords` caps billed calls; `0` disables AI entirely.

***

### Export formats & file names

| Format | Key in Key-Value Store | Notes |
|---|---|---|
| `csv` | `<fileName>.csv` | UTF-8 with BOM — opens perfectly in Excel with emojis & accents |
| `excel` | `<fileName>.xlsx` | Styled header, frozen top row, Summary sheet, formula-injection-safe cells |
| `json` | `<fileName>.json` | Full flat records |
| `gohighlevel` | `<fileName>.gohighlevel.csv` | GHL contacts importer mapping, no-contact rows excluded |
| `instantly` | `<fileName>.instantly.csv` | Instantly campaign upload with custom variables |
| `smartlead` | `<fileName>.smartlead.csv` | Smartlead campaign upload |
| `hubspot` | `<fileName>.hubspot.csv` | HubSpot contact import — rows without an email are excluded |
| `dialer` | `<fileName>.dialer.csv` | Power-dialer friendly (API) |

`fileName` comes from `output_fileName` (invalid characters are stripped, e.g. `austin leads!` → `austin-leads.csv`). All CSV/Excel cells are sanitized against spreadsheet formula injection, and E.164 phone numbers stay import-clean.

> **📌 Where to find your files:** CRM-specific exports (`.gohighlevel.csv`, `.instantly.csv`, etc.), the styled Excel workbook, and BOM-encoded CSV are in **Storage → Key-Value Store**. The default **Output tab** in Apify Console shows the raw flat dataset — use the built-in views (`Cleaned leads`, `Reputation & reviews`, `Full detail`, `Lead scoring`) to browse it interactively.

Every run also writes **`run-summary`** (counts, filter breakdown, timings, issues) and **`issues.json`** to the Key-Value Store, pushes all flat records to the **dataset**, and persists a failure summary even if the run aborts midway.

***

### Input parameters guide

#### 1. Data source (`source_*`)

- `source_datasetId` — Dataset ID of a Google Maps Scraper run (recommended).
- `source_datasetIds` — SEVERAL Dataset IDs merged + deduplicated into one master list (takes priority over the single ID).
- `source_scrapedDataJson` — paste a raw JSON array, a single place object, or a wrapper (`{"items": [...]}`).
- `source_datasetUrl` — full dataset items URL (API).
- Precedence: **Dataset IDs > pasted JSON > Dataset URL.**

#### 2. Lead type

- `fields_preset` — one of the [presets above](#column-presets--lead-types) (default `simple-leads`).
- `fields_presets` — TWO OR MORE presets → one file-set per lead type + `segments` summary (multi-segment export).
- `fields_customColumns` / `fields_rename` — custom column selection & renaming (API).

#### 3. Cleaning & deduplication

- `dedup_enabled`, `dedup_keep`, `dedup_mergeReviews`, `dedup_againstDatasetId` (API).
- `clean_removeClosed`, `clean_removeNoContact`, `clean_normalizePhones`, `clean_splitAddresses`.

#### 4. Filters — see the [filters reference](#filters-reference).

#### 5. Scoring — `scoring_enabled` (default `true`), `scoring_enableResponseRate`.

#### 6. AI — `ai.provider`, `ai.openaiApiKey`, `ai.model`, `ai.maxRecords`, plus feature toggles `ai.generatePainPoints`, `ai.generatePraisePoints`, `ai.generateOpeningLine`, `ai.generateOwnerName`, `ai.generateSummary` (flat or nested under `ai`) — see section above.

#### 7. Output — `output_formats`, `output_fileName`, plus API options `output_delimiter`, `output_quoteAll`, `output_includeSummarySheet`, `output_ghlRequireContact`, `output_instantlyExtraVariables`.

#### 8. Delta detection — `delta_baselineDatasetId` (previous scrape's Dataset ID) or API-only `delta_baselineJson` (pasted previous JSON). Produces change counts + `{fileName}.new` exports.

***

### Why use this instead of a spreadsheet?

- **No broken CSVs** — nested arrays, hours, and review distributions are flattened into real columns, not smashed into one cell.
- **No duplicate rows** — grid searches overlap; dedup collapses them by Google's own place IDs (and merges multiple scraper runs into one master list).
- **No dead leads** — closed businesses and no-contact records are dropped before you pay for outreach.
- **No manual scoring** — the 0–100 score and Bayesian rating tell you who to call first.
- **No import errors** — CRM-specific files ship with the exact column names GoHighLevel, Instantly, Smartlead, and HubSpot expect, phones in E.164, and Excel-safe encoding.
- **No wasted scraper spend** — filter add-ons cost ~$0.001/place/filter per run on the scraper; here every filter, re-slice and new list is free and instant.

***

### FAQ

#### Does this actor scrape Google Maps?

No — and that's the point. This Apify actor processes data already scraped by [Google Maps Scraper](https://apify.com/compass/crawler-google-places). No browser, no Google blocking, no proxy costs: runs finish in seconds and cost pennies.

#### How much does it cost to run?

You pay Apify platform usage for the short run (it's CPU-light) plus this actor's own pricing model (see the **Pricing** tab on Apify Store). There are no per-lead AI costs unless you explicitly enable `ai.provider`.

#### How many records can it process?

Up to 100,000 records per run. Use the Dataset ID input for anything large — pasting JSON is meant for quick, small jobs.

#### Why are emails missing from my output?

Google Maps doesn't expose emails directly. Enable **`scrapeContacts`** on the upstream Google Maps Scraper run, then emails flow through automatically. This actor warns you when your source data contains no email fields at all instead of silently returning zero rows.

#### What happens if I leave both the Dataset ID and pasted JSON filled?

The Dataset ID wins and the pasted JSON is ignored (logged clearly). This protects you from the leftover sample row in the input editor.

#### Are non-US phone numbers supported?

Yes. Phone numbers are parsed with full international rules using each record's country code — UK `020 7946 0958` becomes `+442079460958`, German and EU trunk prefixes are handled, and invalid numbers are flagged instead of silently exported.

#### Can it run automatically after my scraper finishes?

Yes — chain it with Apify **webhooks** or the **Integrations** tab so every scraper run is converted without manual steps.

#### Can I get multiple lead lists from one scrape?

Yes — that's the [multi-segment export](#one-run-every-lead-list-multi-segment-export). Set `fields_presets` to two or more presets and you get a separate file-set per lead type (web-design, reputation, cold-calling, cold-email…) plus a `segments` summary, all from the same dataset — no re-scraping, no extra scraper cost.

#### How do I track new businesses week over week?

Set `delta_baselineDatasetId` to the previous week's scraper run. Every run then reports new businesses, closures, reopenings and claimed-status changes against that baseline, and exports the new businesses as `{fileName}.new.csv`. Chain it with a weekly schedule and you have a hands-off lead-refresh pipeline.

#### Which preset should I choose?

Start with `simple-leads`. If you sell websites pick `web-design-prospects`, if you sell review/reputation services pick `reputation-prospects`, for phone outreach pick `cold-calling`, for email campaigns pick `cold-email`, and use `full-flat` when you want every column for analysis.

***

### Related actors

- [Google Maps Scraper (compass/crawler-google-places)](https://apify.com/compass/crawler-google-places) — the upstream extractor this actor is built for.

### Support & feedback

Found a bug or need a new CRM format? Open an issue on the **Issues** tab of this actor — requests for new export formats and filter ideas are welcome!

# Actor input Schema

## `source_datasetId` (type: `string`):

What it does: Connects your scraping run to this converter. What to enter: Copy and paste the Dataset ID from your Google Maps Scraper run page (Storage tab). Example: AbCdEf123456

## `source_datasetIds` (type: `array`):

What it does: Merges multiple scrapes into one deduplicated master list. What to enter: A list of multiple Dataset IDs.

## `source_scrapedDataJson` (type: `string,array`):

What it does: Allows you to process a raw JSON array directly. What to enter: A valid JSON array of scraped places.

## `fields_preset` (type: `string`):

What it does: Automatically picks the right columns and filters for your campaign. What to select: Choose the preset that best fits your outreach strategy.

## `fields_presets` (type: `array`):

What it does: Generates several lead lists from one scrape. What to enter: Multiple preset names to get separate files for each.

## `dedup_enabled` (type: `boolean`):

What it does: Merges duplicate places that appear in overlapping search grids. What to enter: Check the box to enable (recommended).

## `clean_removeClosed` (type: `boolean`):

What it does: Drops permanently and temporarily closed businesses. What to enter: Check the box to keep only active companies.

## `clean_normalizePhones` (type: `boolean`):

What it does: Converts local formats like '(512) 555-0199' into international '+15125550199'. What to enter: Check the box for CRM and dialer compatibility.

## `filters_websitePresence` (type: `string`):

What it does: Filters businesses based on their website presence. What to select: Choose 'Only WITHOUT a website' to find businesses needing web development.

## `filters_minRating` (type: `number`):

What it does: Keeps only places rated at or above this value. What to enter: A number between 1.0 and 5.0.

## `filters_minReviews` (type: `integer`):

What it does: Keeps only places with at least this many reviews. What to enter: A whole number (0 or higher).

## `filters_hasPhone` (type: `boolean`):

What it does: Keeps only businesses that have a valid phone number. What to enter: Check the box to ensure all leads are callable.

## `filters_hasEmail` (type: `boolean`):

What it does: Keeps only businesses with an email address. What to enter: Check the box to filter leads for email campaigns.

## `filters_claimed` (type: `string`):

What it does: Filters by whether the business has claimed its Google profile. What to select: Choose 'Only UNCLAIMED' for optimization leads.

## `filters_categoriesInclude` (type: `array`):

What it does: Keeps only businesses in the specified categories. What to enter: A list of business types. Leave empty for all.

## `filters_cities` (type: `array`):

What it does: Keeps only places in the specified cities (smart matching ignores diacritics). What to enter: A list of city names. Leave empty for all.

## `output_formats` (type: `array`):

What it does: Selects which file formats to generate. What to enter: File types like csv, excel, json, gohighlevel, instantly, etc.

## `output_fileName` (type: `string`):

What it does: Sets the base name for your exported files. What to enter: A custom file name. Example: 'austin-plumbers'

## `delta_baselineDatasetId` (type: `string`):

What it does: Reports new, closed, or changed businesses versus a previous run. What to enter: The Dataset ID of your PREVIOUS Google Maps Scraper run.

## Actor input object example

```json
{
  "source_datasetId": "AbCdEf123456",
  "source_datasetIds": [
    "AbCdEf123456",
    "XyZwVu654321"
  ],
  "source_scrapedDataJson": [
    {
      "title": "Sample Pizza Place",
      "categoryName": "Pizza restaurant",
      "totalScore": 4.2,
      "reviewsCount": 127,
      "phone": "+1-512-555-0199",
      "website": "https://example.com",
      "address": "456 Congress Ave, Austin, TX 78701",
      "placeId": "ChIJExample123"
    }
  ],
  "fields_preset": "simple-leads",
  "fields_presets": [
    "web-design-prospects",
    "cold-calling"
  ],
  "dedup_enabled": true,
  "clean_removeClosed": true,
  "clean_normalizePhones": true,
  "filters_websitePresence": "any",
  "filters_minRating": 4,
  "filters_hasPhone": false,
  "filters_hasEmail": false,
  "filters_claimed": "any",
  "filters_categoriesInclude": [
    "Restaurant",
    "Plumber",
    "Dentist",
    "Auto repair"
  ],
  "filters_cities": [
    "Austin",
    "Dallas",
    "Houston",
    "San Antonio"
  ],
  "output_formats": [
    "csv",
    "excel",
    "json"
  ],
  "output_fileName": "google-maps-leads",
  "delta_baselineDatasetId": "AbCdEf123456"
}
```

# Actor output Schema

## `dataset` (type: `string`):

Interactive table of cleaned, deduplicated, and scored leads

## `files` (type: `string`):

Download formatted CSV, Excel, and CRM files from the Key-Value Store

## `runSummary` (type: `string`):

Detailed metrics on cleaning, deduplication, filters, and contactability

## `issues` (type: `string`):

Warnings and issues encountered during processing

# 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 = {
    "source_datasetIds": [],
    "source_scrapedDataJson": [
        {
            "title": "Sample Pizza Place",
            "categoryName": "Pizza restaurant",
            "totalScore": 4.2,
            "reviewsCount": 127,
            "phone": "+1-512-555-0199",
            "website": "https://example.com",
            "address": "456 Congress Ave, Austin, TX 78701",
            "placeId": "ChIJExample123"
        }
    ],
    "fields_presets": [],
    "filters_minReviews": 0,
    "filters_categoriesInclude": [],
    "filters_cities": [],
    "output_formats": [
        "csv"
    ],
    "output_fileName": "google-maps-leads",
    "delta_baselineDatasetId": ""
};

// Run the Actor and wait for it to finish
const run = await client.actor("vasram/google-maps-results-converter").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 = {
    "source_datasetIds": [],
    "source_scrapedDataJson": [{
            "title": "Sample Pizza Place",
            "categoryName": "Pizza restaurant",
            "totalScore": 4.2,
            "reviewsCount": 127,
            "phone": "+1-512-555-0199",
            "website": "https://example.com",
            "address": "456 Congress Ave, Austin, TX 78701",
            "placeId": "ChIJExample123",
        }],
    "fields_presets": [],
    "filters_minReviews": 0,
    "filters_categoriesInclude": [],
    "filters_cities": [],
    "output_formats": ["csv"],
    "output_fileName": "google-maps-leads",
    "delta_baselineDatasetId": "",
}

# Run the Actor and wait for it to finish
run = client.actor("vasram/google-maps-results-converter").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "source_datasetIds": [],
  "source_scrapedDataJson": [
    {
      "title": "Sample Pizza Place",
      "categoryName": "Pizza restaurant",
      "totalScore": 4.2,
      "reviewsCount": 127,
      "phone": "+1-512-555-0199",
      "website": "https://example.com",
      "address": "456 Congress Ave, Austin, TX 78701",
      "placeId": "ChIJExample123"
    }
  ],
  "fields_presets": [],
  "filters_minReviews": 0,
  "filters_categoriesInclude": [],
  "filters_cities": [],
  "output_formats": [
    "csv"
  ],
  "output_fileName": "google-maps-leads",
  "delta_baselineDatasetId": ""
}' |
apify call vasram/google-maps-results-converter --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vasram/google-maps-results-converter"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/1wPRjV4dYL9fmboAD/builds/iaBTKolzZZt8Ggm43/openapi.json
