Google Maps Business Scraper — Country-Scale avatar

Google Maps Business Scraper — Country-Scale

Pricing

Pay per event

Go to Apify Store
Google Maps Business Scraper — Country-Scale

Google Maps Business Scraper — Country-Scale

Extracts every business Google Maps publishes inside a bounding box, by recursive geographic tiling. No login, no browser, no cookies.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Oswaldo Carabano

Oswaldo Carabano

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Extracts every business Google Maps publishes inside an area — not the first 200. No API key, no login, no cookies, no browser.

Google caps any single Maps query at about 200 results. So "all the restaurants in Miami" is not one big query: it is a tiling problem. This Actor splits the map into tiles, and splits again wherever a tile comes back full, until every tile returns under the cap. Then it tells you honestly whether it finished.


Quick start

  1. Pick a country and one or more search terms in that country's language (English in the US and Canada, Spanish elsewhere).
  2. Optionally give a bounding box to scrape a single city instead of a whole country.
  3. Set Maximum places if you want a hard cap on what the run costs.
{
"country": "US",
"categories": ["restaurant"],
"bbox": { "lat_min": 25.70, "lng_min": -80.32, "lat_max": 25.85, "lng_max": -80.13 },
"maxPlaces": 1000
}

That is Miami restaurants, capped at 1,000 businesses.


How it works — two passes

Pass 1 — census. One request per 1-degree cell. It classifies every cell as dense, border, foreign, exhausted or empty. This is the planning tool: Venezuela is 180 cells and was classified in 172 requests, about 20 seconds, showing that only 11.7% of the country needed any deeper work. Run it alone with Census only to learn what an area costs before spending anything.

Pass 2 — quadtree. Only the saturated cells get split into four and retried, level by level, until they come back under the threshold. Cells that turned out to belong to a neighbouring country are dropped instead of split — on Venezuela that alone saved about 682 wasted requests.


What you get

One row per business, deduplicated by feature_id, Google's own stable identifier, so the same place never appears twice — not even across separate runs.

place_id is the same identifier the official Places API uses, so this dataset joins to anything you already have from Google without extra work.

Fill rates — measured, and they depend on the market

Two independent measurements, both on 3 Sep 2026: 12,693 businesses across 10 regions and 12 verticals in a Latin American market, and 4,032 businesses across 8 cities in the US, Canada, Mexico, Colombia, Peru, Chile and Argentina.

FieldTorontoMiamiMexico CityRemote regions
name, address, latitude, longitude, place_id100%100%100%100%
phone_e16496.7%77.7%68.2%41.4%
opening_hours96.1%74.3%81.9%48.9%
rating97.5%77.0%92.0%55.5%
website87.4%74.0%40.0%5.7%
reviews_count0.4%11.6%0.0%0.3%

Coverage is a property of the market, not of the tool. The same field runs from 96.7% in Toronto to 41.4% in a remote region. Those numbers are here so you can decide before you buy, not after.

By vertical, measured: dentists return a phone on 99.5% of rows and law firms on 100%; gyms on only 28.0%, because many publish a booking site instead.

What this Actor does not give you

  • A review count you can rely on. Google serves it only in some responses: reviews_count came back on 8.5% of rows. It is delivered when present and it is never promised. If you need it on every row, this is not the tool.
  • Review text. Out of scope: it is writing by identifiable people.
  • Email addresses. Google Maps does not publish them. Measured: zero email strings in 498 records across three verticals, and none on the place page either. Any tool promising emails is getting them from somewhere else.
  • A postal code field. It is embedded inside address and its format varies by region; parsing it out would be guesswork, so it is left where Google put it.
  • Individual place pages. Phone, hours and website already come in the search response, so fetching each place would multiply the cost by about 200 for nothing.

Pricing — one price, no add-ons

Charged per business delivered, with a lower price on every Apify plan tier:

Your planPer place
Free$0.0010
Bronze$0.0008
Silver$0.0006
Gold and above$0.0005

Phone, opening hours, website, rating, categories and coordinates are included at that price. There are no add-on charges for applying a filter or for pulling place details — a habit in this category that can double the real cost per row.

Rows served from cache are charged the same and always declare their age through from_cache and data_age_hours. Failed tiles are never charged, and the tiling overhead — the many requests it takes to break the 200-result cap — is absorbed by the Actor, not billed to you.


Reading the run summary

RUN_SUMMARY in the key-value store is part of the output, not telemetry:

FieldWhat it means
census_completefalse means pass 1 did not finish. What you got is the corner of the grid the sweep started from, not a census of the area
tiles_unresolvedabove zero means this census has gaps, and the log says so
max_depth_reached vs max_depth_limitequal means the census is truncated — raise the depth or split the area
stop_reasonmax_places, request_budget or timeout — which brake stopped the run
places_from_cachehow many rows were served without touching Google

A census with gaps is legitimate. A census with gaps that does not say so is not, and this Actor will always say so.


Large areas: use batches

A big country does not fit in one run — not because of cost but because of the run time limit. Run pass 1 first, then run pass 2 in batches with a requestBudget and a bbox per batch.

Batches are independent, resumable and free to retry: tiles already exhausted are skipped, so re-running a finished batch spends no requests at all. Measured: a second run of the same Venezuelan census needed 8 requests instead of 180.


Country scope

The Actor is global by construction — it takes a bounding box, not a country — but it ships with a catalogue of 24 countries and refuses to run on 8 of them: Spain, Portugal, France, Germany, Italy and the United Kingdom (GDPR / UK GDPR), Brazil (LGPD) and Cuba (regime not reviewed).

This is a deliberate limit enforced in code, not an oversight. Aggregating name, phone and coordinates for hundreds of thousands of small businesses produces a personal-data file, and those regimes require a legal basis this Actor does not document.

Whoever runs this Actor is the data controller for the output. Removal requests: privacy@actorstack.dev.


Notes

Language changes the data, not the interface. The language comes from the country and sets the language of categories and opening_hours, so two runs of the same area in different languages produce different rows. The language used is in every row as language.

Place names are kept exactly as Google publishes them, in their own alphabet and with their own accents. Mérida is not Merida and Kraków is not Krakow.

Where it runs from. The Actor routes through a residential proxy. This is not an optimisation: Google returns HTTP 302 to Apify's own IP ranges, measured on 3 Sep 2026, so a direct run from the platform returns nothing at all.