- First public release.
- The Google Maps stage no longer drives a headless browser: it reads Google's own search response over plain HTTP. Measured on an 8-term / 40-business benchmark, this cut the Maps stage from about 300 seconds to about 5 and made a whole run roughly 66% faster and 57% cheaper per result, with equal or better contact coverage. A browser is still used automatically when the fast path cannot answer, so no coverage is traded away.
- Pricing simplified to a single flat
business-processed event at $3.00 per 1,000 businesses, replacing the previous two-event model.
- Tuned for large runs. A 1,000-business run at the previous default memory throttled itself: browser renders competed with the crawler for half a CPU core and the pool fell from 15 concurrent requests to 5. Three changes fixed it — the default memory is now 4 GB (a full core), browser renders are budgeted per run rather than only per site, and the two stages no longer overlap (there is nothing left to overlap now that Google Maps answers in seconds).
- Measured after the change: 1,019 businesses in 30 minutes, 982 of them with contact details, 2,481 of 2,564 website requests successful.
- Both stages now start at a useful concurrency instead of ramping up from a single request, which was costing a noticeable part of every short run.
- Tighter, evidence-based timeouts on the website stage, and a single attempt for the per-place fallback navigation (retrying one is more expensive than losing it).
- The website stage now overlaps the Google Maps stage automatically when a run has enough memory (4 GB or more, which is where Apify grants a full CPU core). Measured on the same benchmark, that combination finished in less than half the time of a 2 GB run and at a lower cost per result; below 4 GB the stages still run one after the other, which measured faster there.
- The website stage runs after the Google Maps stage again. Overlapping the two was measured to be slower on the default memory allocation, where both stages compete for the same CPU share; the overlapping mode is kept behind an environment switch for runs with more memory.
- Fewer browser round trips per business while walking the results list.
- The sequential website stage hands its full list to the crawler and lets it decide when the stage is complete, instead of tracking completion separately.
- Search results are now opened by matching the result itself rather than the position it held when the list was read, so businesses are no longer missed when Google re-orders the results feed. Far fewer businesses need an expensive fallback page load.
- The website stage now runs alongside the Google Maps stage: each business site starts being crawled as soon as it is discovered, instead of waiting for the whole search to finish. Each stage uses its own run-scoped request queue.
- Concurrency in both stages now scales with the memory (and therefore CPU) allocated to the run, instead of a fixed value that throttled large runs and overloaded small ones.
- Promoted (ad) results no longer produce a record named after the ad badge: the badge glyph is stripped from headings and the business name from the results list is used instead.
- Websites that answer with a rate limit or a temporary error get another attempt, so a busy site no longer costs all of its contacts. Permanent failures still fail fast.
Throughput and efficiency release — same output schema and scope, faster runs at lower compute.
- Each business is now read from the Maps panel in a single browser round trip instead of a dozen separate DOM queries.
- Result panels are matched against the search result's own label, so far fewer businesses fall back to an expensive full page load, and hydration waits are bounded by measured timings instead of worst-case guesses.
- Concurrency caps raised (Maps and website stages) so large multi-term runs use the resources the run actually has, instead of being pinned to a fixed low value.
- The website stage no longer parses each page's HTML twice, and skips entity-decoding and de-obfuscation passes on pages that contain no encoded or obfuscated contacts.
- Results are delivered and charged in batched calls rather than one API round trip per record, which removes a per-record delay at the end of large runs.
- Browser-side callbacks avoid named inner functions, which previously broke Maps extraction under the local development runner.
Cost optimization release — same output schema and scope, substantially lower run cost.
- Google Maps stage now walks search results inside a single page session (SPA clicks) instead of a full page load per business, so Google's heavy bootstrap bundle is downloaded once per search term. Places that cannot be read from the panel automatically fall back to direct navigation, so coverage is preserved.
- Map tiles, photos, fonts, media, and telemetry requests are blocked at the network layer during the Maps stage; the browser also disables image loading and remote fonts entirely.
- The website stage no longer consumes per-GB residential proxy bandwidth: when RESIDENTIAL groups are selected, they stay active for Google Maps only, and business websites are crawled through the standard Apify proxy.
- Browser-render fallback for websites blocks images/media/fonts/stylesheets and waits on network idle instead of a fixed delay.
- Fixed-interval waits replaced with condition-based waits; permanent website errors (DNS, TLS, 400/401/404/410) are no longer retried.
- Default run memory reduced to 2,048 MB.
- The default proxy is now the automatic (datacenter) Apify Proxy, which is significantly cheaper and works for Google Maps in most regions. RESIDENTIAL remains available for cases where the default gets blocked. Measured end-to-end cost on a sample search dropped from ~$21.8 to ~$2.0 per 1,000 businesses with the default proxy.
- Pay-per-event billing:
place-processed is charged once per unique business in the results; contact-found is charged additionally for businesses where at least one reliable (high/medium confidence) contact was found. When a run's charge limit is reached, remaining records are still delivered without further charges.
- Store listing polish: new title, description, and restructured README.
Initial release of Google Maps Contact Scraper.
- Google Maps stage: collects business name, Google Maps URL, website, phone, short address, and social buttons for each search term and location.
- Website stage: Cheerio-first crawl of each business website, staying on the same registrable domain and visiting only contact-relevant priority pages, with a per-site page budget.
- On-demand headless-browser escalation when a page is thin, client-side rendered (SPA), or protected by a bot challenge.
- Contact extraction via mailto:/tel: links, JSON-LD, schema.org microdata, HTML meta tags, obfuscation ("at/dot") reversal, HTML entity decoding, plain-text regex, and website social anchors.
- Per-contact provenance in
contactSources with source, extraction method, source domain, and confidence.
- Third-party / agency heuristics that separate a business's own contacts from agency, platform, and generic-mailbox addresses.
- Business-level deduplication by Google place ID, or by normalized name plus coordinate proximity, merging matched search terms.
- Run-scoped errors dataset for websites that could not be crawled.