Building a Maps scraper in Python
A respectable weekend project that becomes an unrespectable maintenance schedule. Here is the honest engineering picture, so you decide with the real costs on the table.
Last reviewed
The standard architecture
Every DIY Maps scraper converges on the same shape: a browser-automation layer (Playwright is the current default, Selenium the veteran) drives real Maps sessions, a parser reads listing data out of the rendered page, and orchestration code walks searches across an area. Plain HTTP-request scraping does not survive contact with Maps, which is an application rather than a document; the browser layer is non-negotiable, and it is also why DIY scrapers are heavier to run than they look.
The five hard parts, none of which are fetching
- Grid coverage. One search caps around 120 results, so the orchestrator must subdivide territory, and cell sizing with adaptive splitting is the difference between a dataset and a sample. This is the actual engineering core.
- De-duplication. Overlapping cells duplicate 15-30% of rows by design; key the merge on the place identifier, which means reliably capturing it per row.
- Pacing. Request cadence that looks like a person browsing survives; cadence that looks like a loop gets throttled. Randomised human-scale delays cost wall-clock time, which is why metro sweeps take hours by construction.
- Resume state. Hours-long jobs meet dropped connections and sleeping laptops; checkpoint per cell or lose whole runs.
- Silent-breakage detection. The failure mode is not exceptions but quiet degradation after markup changes. Validate output shape (rows per cell, field fill-rates) against expectations every run.
The build-vs-buy arithmetic, honestly
Build when extraction feeds a product or pipeline with custom requirements, you already own browser-automation expertise, and ongoing maintenance hours have an obvious home. A bespoke scraper you control is genuinely valuable in that setting, and for official routes the Places API comparison should be read first.
Buy when the deliverable is lead lists in CSV. The five hard parts above are precisely what mature tools already solved, the maintenance tax lands on the vendor, and the arithmetic is stark: a flat-licence desktop tool costs about what two hours of developer time costs per year. DIY for list-building is a hobby subsidised by unbilled maintenance, which is fine when it is knowingly a hobby.
The hybrid worth knowing: plenty of technical teams run a bought extractor for collection and spend their Python where it differentiates: cleaning, enrichment, refresh diffs and CRM integration downstream of the CSV, per the workflow guide. Collection is commodity; what you do after it is not.
If you do build: practices that keep it defensible
- Pace like a person and run from your own connection; volume discipline is also block avoidance.
- Collect business-directory fields, not everything the page happens to render.
- Respect the legal frame: ToS as contract, outreach law on use.
- Version your parser and alert on fill-rate drops, because the interface will change before your next sprint does.