# Changelog of Lead Finder for Google Maps (`entranced_gelato/google-maps-lead-engine`) Actor

- **URL**: https://apify.com/entranced_gelato/google-maps-lead-engine/changelog.md
- **Full Actor documentation**: https://apify.com/entranced_gelato/google-maps-lead-engine.md

## Changelog

### 2026-10-31: Faster, more reliable builds

- Playwright 1.64.1 (was 1.61.1), with the matching base image `apify/actor-node-playwright-chrome:22-1.64.1`. The image already contains the right Chromium, so the build no longer downloads a browser (that step stalled on Apify). The build now checks that the browser is there and stops with a clear message if not.
- **Shorter runs:** each robots.txt request now gives up after 21 seconds at most. Before, a business website that the proxy couldn't reach held the whole run for about two minutes (127 s in a test run on 31 Oct), because the request time limit didn't cover the proxy's connection step for https sites. The outcome is unchanged (the site counts as disallowed for the run), but runs that hit such a site finish sooner and use less platform time.
- No change to inputs, output or pricing.

### 2026-10-31: Pricing text matches Console

- Users pay Apify platform usage on top of the $0.005 lead price ("Pay per event + usage"), because running the Actor currently costs more per lead than the lead price. The README, Store text and `.actor/pay_per_event.json` now say so.
- The README no longer describes the Apify AI gateway event as starting soon: it isn't priced, so the gateway option uses the free built-in rules.

### 2026-10-17: Compliance update

Prices unchanged: $0.005 per lead on the Free plan ($0.0045 Bronze, $0.004 Silver, $0.0035 Gold and above), platform usage included.

#### Google Maps

- **Google robots guard:** before the browser opens any Google Maps URL (search URLs, start URLs and every place URL found in the results), it is checked against `https://www.google.com/robots.txt`. That file is read once per run through the run's proxy as `AIDevsBot`; the `AIDevsBot` group applies if it has one, otherwise `*`.
  - A disallowed URL is skipped. The first skip sets a status message, and the final status and `RUN_SUMMARY.googleUrlsSkippedByRobotsTxt` give the count.
  - If robots.txt can't be read (429, server error, network error, timeout, or a block or consent page instead of the file), the Maps search doesn't start: there is a clear status message and nothing is charged (`googleBlockReason: "robots-txt-unreachable"`). The same happens when it disallows every URL of the run or answers 401/403 (`"robots-txt-disallowed"`).
- **`startUrls`** accepts only Google Maps search and place URLs (`https://www.google.<tld>/maps/search/...` or `/maps/place/...`). Other URLs are ignored, with a note in the final status (`RUN_SUMMARY.startUrlsIgnored`). If no search terms and no valid start URLs are left, the input is rejected with a clear message.
- The browser that opens Google Maps keeps its own User-Agent.

#### Business websites

- **Honest identification:** every request (pages and robots.txt) sends `Mozilla/5.0 (compatible; AIDevsBot/1.0; +https://apify.com/entranced_gelato/google-maps-lead-engine)` and no generated browser header set (before: crawlee's generated browser headers). Some sites may now refuse the crawl; it is skipped as before.
- **robots.txt** (with `respectRobotsTxt`, default on):
  - The `AIDevsBot` group applies if the site has one (case-insensitive), otherwise `*`; the longest match wins.
  - robots.txt is now fetched through the run's proxy, once per site per run.
  - HTTP 401/403 counts as disallow-all, other 4xx as no restrictions, and 429, server errors, network errors and timeouts disallow the site for the run. Before, crawlee's built-in check read only `*` and allowed everything when robots.txt couldn't be read.
  - `website.blockReason` now also says why a site was skipped for robots.txt: `robots-txt-disallowed`, `robots-txt-forbidden` or `robots-txt-unreachable`. The status message lists unreadable robots.txt files separately.

#### AI

- Apify AI gateway: only `openai/...` and `anthropic/...` models, never `:free` or stealth variants. Any other `aiModel` falls back to `openai/gpt-4o-mini` with a status message. Gateway requests include `"provider": { "data_collection": "deny" }`. Own-key providers keep their model handling.
- Email addresses and phone numbers are masked before any text is sent to an AI model, unless `includePersonalData` is on.
- AI labels: `aiNotice` now reads "AI-generated; may contain errors. Check facts before relying on them." Two new fields: `aiGeneratedAt` (ISO 8601, UTC) and `aiDigitalSourceType` (IPTC `trainedAlgorithmicMedia`). The built-in rules carry both as `null`. The AI summary view shows `aiGeneratedAt`.
- The README and AI input descriptions explain where the text goes, that Apify may bill gateway model usage separately, the model terms, own-key advice and the EU AI Act labels. The Anthropic option is labelled "Anthropic Console API key (not a Claude.ai login)".

#### Security, licence and build

- `webhookUrl` is now a secret input (stored encrypted). Existing values keep working.
- Closed source: `LICENSE` is an all-rights-reserved notice (was MIT), and `package.json` declares `"license": "UNLICENSED"` and `"private": true`.
- Dependencies: `@crawlee/playwright` + `@crawlee/http` (3.17) instead of the `crawlee` meta-package. This removes the GPL-3.0 package `idcac-playwright` and 136 other unused packages.
- Docker: `apify/actor-node-playwright-chrome:22` (Node 20 is end-of-life). The build installs the Chromium version that the locked Playwright expects, and the Maps search launches that browser.

#### README and listing

- "Is it legal?" rewritten: what the Actor returns, named people off by default, sole traders, lawful basis, and Google's Terms of Service and Google Maps Additional Terms.
- Not-affiliated line, robots.txt and start-URL answers, "Wrong charge?", data protection, and a new "AI and your data" section.
- The Store description says "Not affiliated with, endorsed by or sponsored by Google."

### 1.1.1 - 2026-10-11

#### Proxies: Apify's standard proxies only (owner decision)

- Residential proxy groups and the `GOOGLE_SERP` group are dropped from the proxy settings and custom proxy URLs are ignored. If nothing usable is left, the run uses Apify Proxy in automatic mode (datacenter proxies). When settings are dropped the run logs a warning and sets a status message, once, and it never fails because of it. Clean proxy settings, including "no proxy", behave as before.
- The proxy field no longer recommends residential proxies.

### 1.1 - 2026-10-10

New Store name: **Lead Finder for Google Maps**.

#### Billing (pricing unchanged: $0.005 per lead on the Free plan, $0.0045 Bronze, $0.004 Silver, $0.0035 Gold and above)

- The run summary is no longer written to the dataset, so runs no longer bill one extra "lead". It is saved as `RUN_SUMMARY` in the key-value store (linked from the Output tab).
- The run stops as soon as your maximum total charge is reached; it also opens no more Google Maps places than your budget can pay for.
- Duplicates (same place from several search terms) are pushed once. Places that fail your filters are never pushed or charged.
- The filters `minRating`, `minReviews`, `skipClosed`, `categoryFilters`, `excludeCategories`, `excludeDomains`, `requireWebsite`, `requireEmailOrForm` and `minLeadQualityScore` now work (they were ignored). `maxPlaces` now caps unique places across all search terms.

#### Personal data (GDPR)

- New input `includePersonalData` (default off). By default you get company contacts: role-based emails (info@, sales@, kontakt@ and similar in many languages), phones, contact forms and company social profiles. Personal-looking emails, named people (team/imprint pages, structured data) and personal LinkedIn profiles are returned only when you switch it on.
- Each lead has `contactStats` (company vs personal email counts, named people, whether personal data is included) and `contacts.primaryEmail`.
- Team/staff pages are not crawled while personal data is off. Raw page text (`website.pageSamples`) is returned only with `includeRawHtml`, as that input always described.

#### Access rules

- Google's cookie consent is declined ("Reject all"); if it cannot be declined, the Maps search stops instead.
- Google "unusual traffic"/CAPTCHA pages stop the Maps search with a clear status message; places found before are still delivered. No CAPTCHA solving, no proxy/session rotation, no fingerprint spoofing (Crawlee's fingerprint injection and the automation-hiding browser flag were removed).
- New input `respectRobotsTxt` (default on) for business websites. Websites that show a CAPTCHA, login wall or block page are skipped (`website.crawlStatus`).

#### Speed and cost

- Google Maps pages load without images, fonts, media, map tiles or photos, and each place is read in one pass.
- Business websites are fetched over plain HTTP with one parse per page; the per-site page budget is enforced before fetching. `maxWebsitePages` default changed from 8 to 4.
- Leads are processed in parallel; one email-domain lookup per run. Default memory 2 GB.

#### AI

- Every enrichment is labelled `aiGenerated`, `aiModel` and `aiNotice` ("AI-generated; may contain errors."); the free built-in rules are labelled as rule-based.
- `maxAiEnrichments` is enforced. A rejected API key stops further AI calls for the run.
- New optional `aiProvider` "apify" (Apify AI gateway, no API key). It is used only once this Actor's pricing includes the AI event; until then the Actor says so and uses the built-in rules.

#### Fixes

- Emails were sometimes glued to the text before them ("Call us" + "info@…" became "usinfo@…").
- `discoverEmails`, `extractSocialLinks` and `extractContactForms` were ignored.
- Branches of a chain with different Google place IDs are no longer merged into one lead.
- Unexpected errors now fail the run with a message instead of ending as "succeeded".
