Overview
MapHealer is a Python CLI tool that scrapes Google Maps for business leads and turns them into sales-ready Excel files. Unlike brittle Playwright or Selenium scripts that break every time Google changes a CSS class, it uses Scrapling's adaptive selectors that remember the structural fingerprint of each element and auto-heal when the layout shifts.
The Problem
Scraping Google Maps is painful on four fronts. Traditional scrapers break overnight because Google constantly rotates its HTML class names. Most tools only grab what is visible in the sidebar list and miss the high-value fields — phone, website, opening hours — because clicking into each detail page is detection-prone. The output is usually a messy CSV that a sales team has to clean by hand. And Google aggressively blocks automated requests with CAPTCHAs.
What Was Built
A CLI tool (Typer + Rich) with a deep extraction pipeline:
- — Self-healing selectors — Scrapling adaptive matching finds elements by structure, so the scraper survives Google's class-name changes without code changes
- — Deep extraction — navigates into each business detail page for phone, website, per-day opening hours (Senin–Minggu), Plus Code address, and review count
- — Batch keyword processing — single keyword, comma-separated list, or a
.txtfile with hundreds of queries - — Sales-ready Excel — cleaned phone numbers, 1-click
wa.meWhatsApp links, clickable website and Maps URLs, per-day hour columns - — Interactive HTML map — self-contained Leaflet.js file with color-coded markers (green = complete, orange = no website, red = no phone), searchable table, and filter dropdown
- — Stealth + resume — Camoufox stealth sessions bypass bot detection, and interrupted runs resume from checkpoint, skipping already-scraped businesses
Benchmark
Quick mode run: 6 keywords across the Tangerang area, 20 results per keyword (120 businesses). Phone extracted at 79%, website at 50%, summary hours at 85%, and review count at 99%. 120 businesses in 17m 54s — roughly 6.7 businesses per minute at 4.2s average detail fetch.
Technical Notes
- — Stack — Python 3.10+, Scrapling (fetchers + adaptive selectors), Typer, Rich, OpenPyXL, Leaflet.js + OpenStreetMap for the HTML map
- — Anti-bot — Scrapling
AsyncStealthySessionpowered by Camoufox, with retry logic (2 attempts, 5s backoff) on fetch failure - — Resilience — checkpoint-based resume, deduplication by Maps URL (name + address fallback), and auto-saved DOM snapshots when extraction fails for offline debugging
- — Geocoding — coordinates parsed from Maps URLs (
!3d/!4dand@lat,lng), Plus Codes resolved via Nominatim as fallback