# Changelog of Google Maps Scraper (`get-leads/google-maps-scraper---best-value-for-money`) Actor

- **URL**: https://apify.com/get-leads/google-maps-scraper---best-value-for-money/changelog.md
- **Full Actor documentation**: https://apify.com/get-leads/google-maps-scraper---best-value-for-money.md

## Changelog

All notable changes to the Google Maps Scraper. Versions match Apify build numbers.

Format follows [Keep a Changelog](https://keepachangelog.com/) conventions adapted to
Apify's build-number versioning (e.g. `1.0.111` = build major.minor.patch).

***

### \[1.0.121] — 2026-06-02

#### Fixed

- **Evomi 407 at startup now triggers direct-AWS-exit fallback instead of zero-item runs.**
  Previously a misconfigured Evomi proxy meant every run produced 0 items (the
  startup Exit-IP probe failed non-blocking; every subsequent fetch hit the
  same 407; build 1.0.119 made the retry fast-fail). Now the startup probe's
  407 flips the session pool to direct AWS exit (`enableDirectExitFallback`),
  giving the run a chance at items via Google's tolerance of low-volume
  US-AWS traffic. The CRITICAL operator-action log still fires loudly. New
  `TieredSessionPool` field `directExitFallbackActive` surfaces in stats so the
  daily-test orchestrator can distinguish "broken proxy" runs from healthy
  ones. 4 new unit tests lock in the override path (`ScrapingSession`'s new
  `overrideProxyUrl` constructor arg, `SessionPool.setOverrideProxyUrl`,
  `TieredSessionPool.enableDirectExitFallback`).

***

### \[1.0.127] — 2026-06-04

#### Reverted

- **Direct place-id lookup (builds 1.0.124–1.0.126) rolled back.** The intended feature —
  customer-supplied `placeIds[]` / `placeUrls[]` inputs that skip the search step — does not
  work with Google's public HTTP-only endpoints: the `tbm=map` JSON endpoint does NOT
  interpret `place_id:ChIJ...` as a query operator (it treats it as a literal search string
  and returns zero results, just echoing the query back in a 770-byte response), and the
  `/maps/preview/place?...!1s<placeId>...` XHR endpoint requires session context from a
  prior search to return populated data — calling it stand-alone yields empty bodies.
  Compass + lukaskrivka achieve this feature via browser-based scraping (Puppeteer /
  Playwright), which is incompatible with our 128 MB HTTP-only architecture. The right
  v2 path requires either (a) parsing the HTML response from `https://www.google.com/maps/place/?q=place_id:ChIJ...`
  (heavy, brittle, ~1-2 days of work), or (b) a different design that doesn't promise
  search-skip semantics. Reverted clean — input schema, output schema, README, and main.js
  back to 1.0.123 state; the experimental code in `src/utils/place-url-parser.js` +
  `tests/place-url-parser.test.js` + the `scrapeByPlaceIds` function were removed to avoid
  dead-code rot.

***

### \[1.0.119] — 2026-06-02

#### Fixed

- **Evomi `ProxyAuthRequired` (HTTP 407) no longer triggers 3 wasted retries.**
  When the Evomi residential proxy rejects auth (rotated base password, expired
  pre-registered hardsession, malformed `RESIDENTIAL_PROXY_URL`), `retryWithBackoff`
  now short-circuits on the first failure and emits a single `[CRITICAL]` log line
  with the operator-actionable fix instructions, instead of burning ~33s of wall
  - \~$0.001 of compute across 4 attempts that can never succeed. Behaviour is
    unchanged for all other error types (transient network errors, Google 429s,
    HTTP 5xx, parse failures still retry as before). Locked in by 3 new unit tests.

***

### \[1.0.111] — 2026-05-11

#### Fixed

- **Customer overcharge eliminated.** Previous builds emitted internal telemetry rows
  (`learning-loop-digest`, `bandwidth_report`) into the default Apify dataset, which
  caused customers to be charged for 2 extra `apify-default-dataset-item` events per
  run (~$0.006/run on top of the genuine result charges). Telemetry now lives in
  named KV records (`learning-loop-digest-latest`, `bandwidth-report-latest`)
  visible only to the actor owner. **Net effect**: a typical 5-item search now
  charges exactly 5 events ($0.025), not 7 ($0.031).

#### Added

- All 8 `outputFormat` values fully verified end-to-end with unit tests +
  production smoke runs: `default`, `hubspot`, `salesforce`, `fullcontact`,
  `pipedrive`, `zoho`, `airtable`, `csvflat`. 43 new unit tests added.

#### Improved

- "Delivered items" log line now reads the count from the in-process write path
  instead of racing against Apify's eventually-consistent `dsInfo.itemCount`
  read-back — runs that pushed N items now log `delivered: N`, not `delivered: 0`.

***

### \[1.0.110] — 2026-05-06

#### Improved

- 100% accuracy + 92.4% margin on Day-7 production daily-tests. The
  corpus-health watchdog (separate scheduled monitor; not part of the actor
  build) and the dev-script smoke-test extensions shipped around this date
  but live outside the actor — they are operator-side tooling, not
  customer-visible features.

***

### \[1.0.109] — 2026-05-03

#### Added

- **Learning-loop architecture v3.1** — 4-stage portfolio-standard feedback loop
  (capture / store / analyze / enforce). Threshold values for anti-ban behavior
  now live in a single source of truth (`src/lib/policy.js`) with `_basedOn` +
  `_rationale` provenance per threshold. Future tuning is data-driven.
- Emergency knob: `GMAPS_RATE_LIMIT_MULTIPLIER` env var compounds with existing
  pacing — set to `0.3` for immediate 3× stricter, `3` for looser, default `1`.

#### Improved

- 98.8% margin on the latest accuracy-tested workload (architect Milan, 5 places).

***

### \[1.0.94+] — 2026-04-26

#### Added

- **v4 anti-ban baseline** — per-domain skip-list, residential-IP coordination
  with Evomi sticky sessions, adaptive pacing with Box-Muller jitter.
- **Cost + margin estimate** log line at every run end — operators see
  estimated Apify cost, revenue, and margin percentage at a glance.

#### Improved

- Bumped default memory from 256MB to 512MB to handle larger result sets +
  enrichment without container-restart pauses.

***

### \[1.0.67] — 2026-04-21

#### Added

- **Day-1 + Day-2 + Day-2.5 cumulative state** — initial production-grade
  release. 8 supported outputFormat values, 64 supported business niches with
  per-niche search-term + enrichment-page configuration.
- 5-layer email discovery pipeline (JSON-LD → company website → search-engine
  pattern → MX-validated guessing → optional Hunter.io).
- HTTP-only architecture via Impit (Chrome TLS fingerprinting) for low-memory
  scraping without Playwright.

***

### Cost + reliability commitments

The scraper aims for **≥50% margin** and **≥95% field-presence accuracy** as
SLA gates. Both have held on every day with a successful daily-test run since
2026-04-26. Two days (2026-05-08, 2026-05-09) had 0-item runs due to upstream
proxy provider outage (Evomi HTTP 407 cascade — out of the scraper's control);
accuracy gates can't apply to 0-item runs and margin doesn't apply when revenue
is $0. The customer-facing PPE is `$0.005/item` (one charged event per place
returned).

### Reporting issues

If a run returns fewer items than expected, includes incorrect field values,
or charges more events than items returned, please open an issue on the
Apify Store listing. Each run produces a `bandwidth-report-latest` KV record
visible to you (the actor owner) that may help diagnosis.
