# Google Maps Lead Enricher: Website Audit + AI Facts (`emulative_capeskin/google-maps-lead-enricher`) Actor

signals (booking_platform, chat_widget, ad_tags), pitch_gaps, ai (services, price_points, financing, emergency_24_7, hiring) with quotes for each business on a Google Maps list. $0.002 per site scanned, $0.01 with AI facts; the free plan gets AI facts for up to 3 businesses per run without a key.

- **URL**: https://apify.com/emulative_capeskin/google-maps-lead-enricher.md
- **Developed by:** [Sniper Search](https://apify.com/emulative_capeskin) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 ai-enriched businesses

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 Lead Enricher: Website Audit + AI Facts

signals (booking_platform, chat_widget, ad_tags), pitch_gaps, ai (services, price_points, financing, emergency_24_7, hiring) with quotes for each business on a Google Maps list. $0.002 per site scanned, $0.01 with AI facts; the free plan gets AI facts for up to 3 businesses per run without a key. Those are the first 3 businesses of a run that reach the AI step (a failed AI call uses up a slot); the AI runs on the Actor's key and each one is charged $0.01 like any other AI-enriched business. The rest are scanned only ($0.002 each); add your own Anthropic key for AI facts on all of them.

Give it businesses (a Google Maps search, the dataset of a Google Maps Scraper run, or your own list) and it reads each business's own website. You get one row per business with two kinds of answers:

- **Website signals**, found by rules on the pages, no AI: does the site take online bookings and with which tool (Housecall Pro, ServiceTitan, Jobber, Vagaro, Calendly and about 20 more), is there a chat widget (Podium, Tidio, Intercom, ...), does it run Meta, Google Ads, TikTok or Microsoft ads pixels, is it on HTTPS with a certificate a browser accepts, is it mobile-ready, which copyright year is in the footer, what is it built with. Each gap comes back as a ready-made `pitch_gaps` code such as `no_booking_seen`.
- **AI facts**, read by Claude from the site's own text, each with a verbatim quote and the page it came from: what the business does, services and service area, prices it states, financing and named providers, free estimates, emergency or 24/7 service, licensed or insured, years in business, guarantees, languages, and whether it is hiring.

Businesses with no website, or with a site that cannot be read, come back as free rows. The Actor collects facts about businesses, not about people (see Privacy).

### Who uses it

Filter the rows on the gap you sell, and turn the AI on only for the prospects that have it. `aiOnlyForGaps` makes the Actor spend the $0.01 AI step only on businesses whose scan shows one of the gaps you list; the others cost $0.002.

| You sell | Look for | Input to save money |
| --- | --- | --- |
| **Websites and redesigns** (web designers) | `copyright_2023_or_older`, `no_https`, `not_mobile_ready`, `signals.site_builder`, and the `no_website` rows: businesses on Google Maps without a site, free | `"aiFacts": false` for the scan alone, or `"aiOnlyForGaps": ["copyright_2023_or_older", "no_https", "not_mobile_ready"]` |
| **Booking and field-service software** (Housecall Pro, Jobber, Vagaro, Calendly resellers) | `no_booking_seen` for prospects, and `signals.booking_platform` to see which tool the competition already uses | `"aiOnlyForGaps": ["no_booking_seen"]` |
| **Chat and review widgets** (Podium, Tidio, Birdeye resellers) | `no_chat_seen`; `signals.chat_widget` names the vendor a business already has. It is `unknown`, never `none`, when Google Tag Manager is on the page, because the tag can load a widget later | `"aiOnlyForGaps": ["no_chat_seen"]` |
| **Ad agencies** | `no_ad_tags_seen`: no Meta, Google Ads, TikTok or Microsoft Ads pixel seen. `ai.financing`, `ai.free_estimates` and `ai.price_points` show the offer you can advertise | `"aiOnlyForGaps": ["no_ad_tags_seen"]` |
| **Cold email and outreach writers** | `ai.services`, `ai.service_area` and `ai.evidence`: a quote from the business's own site to open an email with. Emails from Google Maps Scraper's contacts option pass through in `input_extra` | `"aiFacts": true` on the businesses you will write to |

### Example output

One business (a made-up plumber; `meta` is shortened):

```json
{
  "name": "Acme Plumbing",
  "website": "https://acmeplumbing.example/",
  "place_id": "ChIJ-acme",
  "category": "Plumber",
  "city": "Seattle",
  "state": "Washington",
  "phone": "(206) 555-0100",
  "rating": 4.8,
  "reviews_count": 412,
  "status": "enriched",
  "charged_event": "business-enriched",
  "pitch_gaps": ["no_chat_seen", "copyright_2023_or_older"],
  "signals": {
    "https": true,
    "mobile_ready": true,
    "copyright_year": 2022,
    "site_builder": "WordPress",
    "gtm_present": false,
    "chat_widget": "none",
    "booking_platform": "Housecall Pro",
    "booking_url": "https://book.housecallpro.com/book/acme-plumbing",
    "ad_tags": { "meta_pixel": "yes", "google_ads": "no", "ga4": "unknown", "tiktok": "no", "microsoft_ads": "no" },
    "contact_form": true,
    "social_links": ["https://www.facebook.com/acmeplumbing"]
  },
  "ai": {
    "summary": "Acme Plumbing is a Seattle plumber for water heaters, drains and sewer lines.",
    "services": ["Water heater repair", "Drain cleaning", "Sewer line replacement"],
    "service_area": "Seattle, Bellevue and Renton",
    "emergency_24_7": "yes",
    "free_estimates": "yes",
    "financing": "yes",
    "financing_providers": ["Synchrony"],
    "price_points": ["$89 diagnostic fee"],
    "online_booking": "yes",
    "booking_url": "https://book.housecallpro.com/book/acme-plumbing",
    "licensed_insured": "yes",
    "founded_year": 1995,
    "guarantees": ["One-year workmanship warranty"],
    "languages": ["Spanish"],
    "hiring": "yes",
    "careers_url": "https://acmeplumbing.example/careers",
    "evidence": [
      { "field": "emergency_24_7", "quote": "24/7 emergency plumbing, nights and weekends", "url": "https://acmeplumbing.example/" },
      { "field": "financing", "quote": "Financing available through Synchrony", "url": "https://acmeplumbing.example/financing" }
    ],
    "confidence": "high"
  },
  "error": null,
  "input_extra": null,
  "meta": { "index": 0, "source": "list", "final_url": "https://acmeplumbing.example/", "pages_read": ["https://acmeplumbing.example/", "https://acmeplumbing.example/financing"] }
}
```

Every AI fact is `unknown`, `null` or empty when the site does not say. Nothing is guessed. In the Apify Console the dataset has two table views: Overview (status, gaps and website signals) and AI facts (services, prices, financing, quotes).

### Six real results

From the October 2026 test sites, one business per trade in Seattle, names left out. The website columns were read with the current version, the last column is what the AI read in the October test. `?` means unknown (Google Tag Manager on the page).

| Trade | Online booking | Chat | Ad pixels seen | Copyright | Pitch gaps | Emergency / financing / hiring |
| --- | --- | --- | --- | --- | --- | --- |
| Plumber | none | Tidio | Google Ads (others ?) | 2023 | `no_booking_seen`, `copyright_2023_or_older` | yes / unknown / unknown |
| HVAC | own form or page | Podium | none | not found | `no_ad_tags_seen` | unknown / yes / unknown |
| Roofer | none | ? | Google Ads (others ?) | 2026 | `no_booking_seen` | yes / yes / unknown |
| Electrician | none | none | none | 2018 | `no_booking_seen`, `no_chat_seen`, `no_ad_tags_seen`, `no_https`, `copyright_2023_or_older` | unknown / unknown / unknown |
| Hair salon | Schedulicity | none | none | 2026 | `no_chat_seen`, `no_ad_tags_seen` | unknown / unknown / yes |
| Auto repair | own form or page | none | Google Ads | 2026 | `no_chat_seen` | unknown / yes / unknown |

### Three ways to give it businesses

Use any one, or all three in one run. All of them produce the same rows.

1. **Search.** `searchTerms` (for example `["plumber", "hvac contractor"]`), `location` (for example `Seattle, WA, USA`) and `maxBusinessesPerSearch` (default 50, up to 500). The Actor runs [Google Maps Scraper](https://apify.com/compass/crawler-google-places) in your own Apify account and reads the websites of the places it finds. Closed places are left out. Google Maps Scraper bills you for the search, and your maximum cost per run does not cover it, see Pricing.
2. **After Google Maps Scraper** (or Facebook Pages Scraper, or Instagram Profile Scraper). Pick its dataset in `mapsDatasetId`, or add this Actor as an integration of that Actor (its Integrations tab, Add integration, then this Actor, with `mapsDatasetId` set to `{{resource.defaultDatasetId}}`) so every run is enriched as it finishes. Left empty, `mapsDatasetId` falls back to the dataset of the run that triggered the integration. The rows work as they are.
3. **Your own list.** `businesses`: items with a `name` or a `website`, and optionally `city`, `state`, `phone`, `address` and `placeId`. Rows exported from Google Maps Scraper or another tool work as they are.

```json
{
  "searchTerms": ["plumber", "hvac contractor"],
  "location": "Seattle, WA, USA",
  "maxBusinessesPerSearch": 25,
  "aiOnlyForGaps": ["no_booking_seen"]
}
```

```json
{
  "businesses": [
    { "name": "Acme Plumbing", "website": "https://acmeplumbing.example/", "city": "Seattle", "state": "WA" }
  ]
}
```

The same place twice (same Google place ID) is one business, and so is the same website listed for several businesses: it is read once, every business gets the result, and you pay once.

### Input

- `searchTerms`, `location`, `maxBusinessesPerSearch`: the Google Maps search (see above).
- `mapsDatasetId`: the dataset of a Google Maps Scraper, Facebook Pages Scraper or Instagram Profile Scraper run. Each row is read on its own, so one dataset can mix them (see Chain it after another actor, below).
- `businesses`: your own list.
- `maxBusinesses` (default 500, up to 5000): a hard cap for the whole run. Businesses past it get no row.
- `aiFacts` (default on): add the AI facts. Off: website signals only, $0.002 per site.
- `aiOnlyForGaps`: run the AI only on businesses that show one of these gaps: `no_booking_seen`, `no_chat_seen`, `no_ad_tags_seen`, `no_https`, `not_mobile_ready`, `copyright_2023_or_older`, `no_contact_form_seen`.
- `anthropicApiKey`: your own Anthropic API key, billed to you by Anthropic. Leave it empty on paid plans: the Actor's own key gives AI facts to the first 1,000 businesses of a run and scans the rest. On the free Apify plan the Actor's own key gives AI facts to the first 3 businesses of a run and scans the rest, so add your own key for AI facts on all of them. Your key is also needed for Sonnet or Opus and for more than 5 pages per site. It is stored as a secret and is never logged or written to the output.
- `model`: `claude-haiku-5-5` (default), `claude-sonnet-5-5` or `claude-opus-5-5`. Sonnet and Opus run only with your own key; without one the Actor uses Haiku.
- `maxPagesPerSite` (default 5): pages read per site, homepage included. At most 5 without your own key, 8 with it. The Actor reads the homepage and the subpages most likely to hold the answers: contact, services, booking, pricing, financing, careers, about.
- `concurrency` (default 3), `proxyConfiguration`.

#### Chain it after another actor

`mapsDatasetId` takes the dataset of a run of any of three Actors, and one dataset can hold rows of all three. The Actor tells them apart row by row, from the columns each row has, reads the business's website from the column named below, and returns a row that has none as `no_website`, free. The other columns of a row stay in `input_extra`, except the ones listed under Privacy.

Connected as an integration of one of these Actors (its Integrations tab, Add integration), the Actor reads the dataset of the run that triggered it automatically, so the Actor input can stay empty. If a run reports that it cannot read that dataset, set `mapsDatasetId` to `{{resource.defaultDatasetId}}`.

- **[Google Maps Scraper](https://apify.com/compass/crawler-google-places):** the website is `website`, the name is `title`, and `meta.source` is `dataset`. Rows work as they always did. A row `{"title": "Acme Plumbing", "placeId": "ChIJ-acme", "website": "https://acmeplumbing.example/"}` comes out as `{"name": "Acme Plumbing", "website": "https://acmeplumbing.example/", "meta": {"source": "dataset"}}`.
- **[Facebook Pages Scraper](https://apify.com/apify/facebook-pages-scraper):** the website is `website` (Facebook writes a bare domain such as `acmeplumbing.example`), else the first entry of `websites` that is not a Google Maps link. The name is `title`, the category is the first of `categories` after `Page`, and the link to the page (`pageUrl`) goes to `input_extra.source_url`. `meta.source` is `facebook`. A row `{"title": "Acme Plumbing", "pageUrl": "https://www.facebook.com/acmeplumbing", "categories": ["Page", "Plumber"], "website": "acmeplumbing.example"}` comes out as `{"name": "Acme Plumbing", "website": "acmeplumbing.example", "category": "Plumber", "input_extra": {"source_url": "https://www.facebook.com/acmeplumbing"}, "meta": {"source": "facebook"}}`.
- **[Instagram Profile Scraper](https://apify.com/apify/instagram-profile-scraper):** the website is `externalUrl`, the link in the bio, else the first usable link of `externalUrls`. The name is `fullName`, the category is `businessCategoryName`, and the profile link (`url`) goes to `input_extra.source_url`. `meta.source` is `instagram`. When `fullName` reads like a person's name ("Jane Smith"), it is not used: the business is named by its `username`. A row `{"username": "acmeplumbing", "url": "https://www.instagram.com/acmeplumbing", "fullName": "Acme Plumbing", "externalUrl": "https://acmeplumbing.example/", "businessCategoryName": "Plumber"}` comes out as `{"name": "Acme Plumbing", "website": "https://acmeplumbing.example/", "category": "Plumber", "input_extra": {"source_url": "https://www.instagram.com/acmeplumbing"}, "meta": {"source": "instagram"}}`.

`maps_url` is filled for Google Maps rows only. A link that cannot be a business's own site (Google Maps, a directory, a social network, Linktree and other link-in-bio pages, WhatsApp) is passed over when another column has a better one; when it is the only one, the row comes back as `not_own_site`, free. A Facebook row that carries a personal profile is a person, not a page: its title is not used as the name. The posts, related accounts and personal profiles these Actors write are not passed on (see Privacy). Rows pasted into `businesses` are read as plain items: use `mapsDatasetId` for the datasets of these Actors.

### Output

One row per business in the default dataset.

- **From Google Maps or your input:** `name`, `website`, `place_id`, `maps_url`, `category`, `address`, `city`, `state`, `phone`, `rating`, `reviews_count`. Any other column you gave comes back unchanged under `input_extra` (for example `emails` from Google Maps Scraper's contacts option). A Facebook or Instagram row also gets `input_extra.source_url`, the link to its page or profile.
- **`signals`:** `https`, `mobile_ready`, `copyright_year`, `site_builder`, `booking_platform` and `booking_url`, `chat_widget`, `ad_tags` (`meta_pixel`, `google_ads`, `ga4`, `tiktok`, `microsoft_ads`), `gtm_present`, `contact_form`, `social_links` (the business's own pages only).
- **`pitch_gaps`:** the gap codes above that apply to the site.
- **`ai`:** the AI facts, with `evidence` quotes and a `confidence`.
- **`status`** and **`charged_event`**:

| `status` | Meaning | Charged |
| --- | --- | --- |
| `enriched` | Website scanned and AI facts added | `business-enriched` $0.01 |
| `scanned` | Website scanned, no AI facts (`meta.ai_skipped` says why: AI off, free plan after the first 3 businesses of a run, no matching gap, spending limit, the 1,000-business AI limit of the Actor's key, ...) | `business-scanned` $0.002 |
| `ai_unavailable` | Website scanned, but the AI facts could not be added (the AI call failed, or no key works); `error` says why | `business-scanned` $0.002 |
| `no_website` | No usable website | free |
| `unreadable` | The site could not be read: bot check, a page built only in JavaScript, a dead domain | free |
| `not_own_site` | The website is a directory, a social network, a marketplace page, or another business | free |
| `skipped_free_plan` | Past the 100 businesses a free-plan run processes | free |
| `error` | An item that is not a business, or an unexpected failure | free |

**How to read the signals.** "Seen" means seen in the pages the Actor read. A tag manager can load chat widgets and ad pixels later, so when Google Tag Manager is on the page they come back as `unknown`, never as absent. GA4 is also `unknown` on WordPress and on hosted site builders (Squarespace, Wix, GoDaddy, Duda, Weebly, Shopify, Webflow), where it is added in a way a plain page request cannot see. `contact_form` is `null`, not `false`, on Squarespace, Wix, GoDaddy, Duda and Weebly sites where no form was seen, because those builders often draw their forms with JavaScript. `https` is `true` when the final address is HTTPS and a browser would accept its certificate. It is `false` for plain HTTP and for an expired, self-signed or wrong-host certificate, which browsers show as "Not secure" (`meta.certificate_error` names the problem), and `null` when the certificate check could not settle (a timeout, an incomplete certificate chain). A pitch gap is only reported on a clear "no". `copyright_year` is empty when the footer is written by JavaScript.

### Pricing

Pay per event, no start fee.

| Event | Price | When |
| --- | --- | --- |
| Scanned business (`business-scanned`) | **$0.002** | The site was read and the website signals came back |
| AI-enriched business (`business-enriched`) | **$0.01** | The site was read and AI facts were added. Charged instead of the scan, never on top of it |

Free: businesses with no website, sites that cannot be read, sites that are not the business's own, businesses skipped on the free plan, errors, and every business that shares a website with one already processed in the same run. If the AI step fails for a business you still get the scan and pay the scan price (`ai_unavailable`). Your own Anthropic key costs the same.

For 100 businesses: about $0.20 for scans only, about $1.00 with AI facts, and less with `aiOnlyForGaps`. Set a maximum cost per run in the run options: the Actor stops cleanly at the limit and never charges past it for its own events, and the businesses after it have no row.

**The Google Maps search is billed by Google Maps Scraper, on top of this Actor's price,** to your account: up to $0.004 per place on the free plan (less on paid plans). The Actor sets none of its paid add-ons or filters, so a search of 100 places costs at most about $0.40. Using an existing dataset or your own list costs nothing extra.

**Your maximum cost per run does not cover the Google Maps search,** only this Actor's own events. To keep the two in step, the search asks for no more places than your maximum cost can pay for: at $0.01 each when every business gets AI facts, at $0.002 each when AI facts are off or limited by `aiOnlyForGaps`, and on a free-plan trial 3 at $0.01 and the rest at $0.002. Businesses without a website or with an unreadable site are free, so a run usually has money left over; set `maxBusinessesPerSearch` if you want a fixed number.

For comparison, Google Maps Scraper's own AI add-on costs $0.025 per place on the free plan, and Apify's AI Web Scraper costs $0.03 per page. This Actor reads up to five pages of a site by default and returns structured facts with quotes for $0.01.

### How accurate is it?

Tested in October 2026 on 56 trade and salon businesses in Seattle (plumbers, HVAC, roofers, electricians, hair salons, auto repair shops). The test read up to 5 pages per site, the Actor's default.

- **AI facts:** 98.8% of the key-field answers were right (339 of 343, blind re-check against the pages). By field: own website 100%, services 100%, emergency or 24/7 100%, free estimates 98%, financing 100%, online booking 96%, licensed or insured 100%, hiring 98%.
- **Website signals** matched what a real browser shows on 18 of 20 sites. The 2 misses were GA4 reported as absent on sites where a site builder or plugin adds it; GA4 is now reported as `unknown` there.
- **Readable:** 50 or 51 of the 56 sites (about 9 in 10) could be read without a browser. The others were bot checks, pages built only in JavaScript, or a dead domain; they come back as `unreadable` and are free.

Quotes come from the visible text of the business's own pages, so you can check any fact.

### Free plan

On the free Apify plan a run processes up to 100 businesses (within your spending limit) and returns the rest as free `skipped_free_plan` rows. Without your own Anthropic key, the free Apify plan gets AI facts for 3 businesses per run: the first 3 businesses get them on the Actor's key (Haiku, at most 5 pages per site) and are charged `business-enriched`, $0.01 each, like any other AI-enriched business. The rest are scanned only (charged `business-scanned`, $0.002 each; `meta.ai_skipped` is `free_plan`). With your own key in `anthropicApiKey`, every business of the run gets AI facts. Paid plans have no cap on businesses and need no key for AI facts, with one limit: on the Actor's own key a run gives AI facts to at most 1,000 businesses, and the rest are scanned only (`meta.ai_skipped` is `run_ai_cap`). Add `anthropicApiKey` to get AI facts for every business of a larger run.

### Privacy

The Actor returns facts about businesses. It does not collect the names of owners, staff or reviewers, personal emails or personal phone numbers, and it asks the AI to leave them out of every field. Reviews, lead enrichment (named contacts), image authors, owner posts, an Instagram profile's latest posts and related accounts, a Facebook page's posts and personal profile, LinkedIn profile links and any column of your input whose name contains owner, staff, reviewer or personal are dropped, not passed on. Social links are the business's own pages only. Every other column of your input rows comes back unchanged under `input_extra`, so if a column of your own holds a person's name or email, leave it out of the input when you do not want it in the output. The one exception is an Instagram profile's `fullName`: it becomes the business name only when it reads like a business, and is never passed on. A name like "Jane Smith" is replaced by the `username`. If you need business emails, turn on the contacts option of Google Maps Scraper: its `emails` column passes through under `input_extra` as it is.

### Good to know

- It reads public pages of the business's own site, a handful per site.
- Sites that need a full browser (built entirely in JavaScript, or behind a bot check) are `unreadable`.
- The AI facts are only as good as the site: the `evidence` quotes show where each key fact came from.
- Directory, social network and marketplace links (Yelp, Facebook, HomeAdvisor, Vagaro profiles, ...) are never read as the business's own site.

Looking for dental, veterinary, chiropractic, therapy or other clinics, with insurance and new-patient facts? See [Dental & Clinic Enricher](https://apify.com/emulative_capeskin/dental-practice-enricher).

# Actor input Schema

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

Each term is one Google Maps search, for example "plumber" or "hair salon". Together with Location, the Actor runs Google Maps Scraper in your Apify account (billed by that Actor, up to $0.004 per place, on top of this Actor's price; your maximum cost per run does not cover it, but it limits how many places are asked for: what that cost can pay to enrich with AI facts, or to scan when AI facts are off). Leave empty to use an existing dataset or your own list.

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

Where to search, for example "Seattle, WA, USA". Leave empty if your search terms already name the place, like "plumbers in Seattle".

## `maxBusinessesPerSearch` (type: `integer`):

Most places Google Maps Scraper returns for each search term. Each place is billed by that Actor at up to $0.004.

## `mapsDatasetId` (type: `string`):

The dataset of a finished run of Google Maps Scraper, Facebook Pages Scraper or Instagram Profile Scraper; one dataset can mix them. Each row is read on its own: the website comes from website, websites or externalUrl, and a row without one comes back as no_website, free. To enrich every run automatically, add this Actor as an integration of that Actor with the run's default dataset.

## `businesses` (type: `array`):

Your own list. Each item needs a name or a website. Rows from Google Maps Scraper work as they are; title, website, phone, address, city, state, placeId, categoryName, totalScore and reviewsCount are mapped. Other columns are passed through in input_extra.

## `maxBusinesses` (type: `integer`):

A hard cap for the whole run, whichever sources you use. Businesses beyond it get no row and cost nothing.

## `aiFacts` (type: `boolean`):

Add AI-read facts (services, prices, financing, emergency service, hiring), each with a quote from the site: $0.01 per business instead of $0.002 for the website scan alone. Off: website signals only.

## `aiOnlyForGaps` (type: `array`):

Run the AI only on businesses whose website scan shows at least one of these gaps (for example no online booking); the others are scanned only, at $0.002. Leave empty to run the AI on every business.

## `anthropicApiKey` (type: `string`):

Leave empty on paid plans. On the free Apify plan the first 3 businesses of a run get AI facts on the Actor's key and the rest are scanned only, so add your own key (billed to you by Anthropic) for AI facts on all of them. Your key is also needed for Sonnet or Opus and more than 5 pages per site. The Actor's key uses Haiku, at most 5 pages, and AI facts for at most 1,000 businesses per run.

## `model` (type: `string`):

Model used for the AI facts. Haiku is the default and the cheapest. Sonnet and Opus run only with your own key in anthropicApiKey; without one the Actor uses Haiku.

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

Pages read per site, homepage included: the homepage plus the most relevant subpages (contact, services, booking, pricing, financing, careers). Capped at 5 without your own Anthropic key, 8 with it.

## `concurrency` (type: `integer`):

Businesses processed in parallel.

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

Proxies used to fetch business websites. Residential proxies are not available on the Actor plan: RESIDENTIAL is removed from the proxy groups and Apify Proxy uses its datacenter groups instead. Your own proxy URLs are used as given.

## Actor input object example

```json
{
  "maxBusinessesPerSearch": 50,
  "businesses": [
    {
      "name": "Evergreen Home Heating and Energy",
      "website": "http://www.evergreenhomeheatingandenergy.com/",
      "city": "Seattle",
      "state": "WA",
      "phone": "(206) 565-1455"
    },
    {
      "name": "Linh's Hair Salon",
      "website": "http://linhshairsalon.weebly.com/",
      "city": "Seattle",
      "state": "WA",
      "phone": "(206) 760-2996"
    }
  ],
  "maxBusinesses": 500,
  "aiFacts": true,
  "aiOnlyForGaps": [],
  "model": "claude-haiku-5-5",
  "maxPagesPerSite": 5,
  "concurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All rows in the default dataset, one per business.

# 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 = {
    "businesses": [
        {
            "name": "Evergreen Home Heating and Energy",
            "website": "http://www.evergreenhomeheatingandenergy.com/",
            "city": "Seattle",
            "state": "WA",
            "phone": "(206) 565-1455"
        },
        {
            "name": "Linh's Hair Salon",
            "website": "http://linhshairsalon.weebly.com/",
            "city": "Seattle",
            "state": "WA",
            "phone": "(206) 760-2996"
        }
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("emulative_capeskin/google-maps-lead-enricher").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 = {
    "businesses": [
        {
            "name": "Evergreen Home Heating and Energy",
            "website": "http://www.evergreenhomeheatingandenergy.com/",
            "city": "Seattle",
            "state": "WA",
            "phone": "(206) 565-1455",
        },
        {
            "name": "Linh's Hair Salon",
            "website": "http://linhshairsalon.weebly.com/",
            "city": "Seattle",
            "state": "WA",
            "phone": "(206) 760-2996",
        },
    ],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("emulative_capeskin/google-maps-lead-enricher").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 '{
  "businesses": [
    {
      "name": "Evergreen Home Heating and Energy",
      "website": "http://www.evergreenhomeheatingandenergy.com/",
      "city": "Seattle",
      "state": "WA",
      "phone": "(206) 565-1455"
    },
    {
      "name": "Linh'\''s Hair Salon",
      "website": "http://linhshairsalon.weebly.com/",
      "city": "Seattle",
      "state": "WA",
      "phone": "(206) 760-2996"
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call emulative_capeskin/google-maps-lead-enricher --silent --output-dataset

```

## MCP server setup

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

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/BvoG8vIDq61QWDroX/builds/q7uuF3z16cmR75lFs/openapi.json
