Google Maps Places API – Area Coverage
Pricing
from $0.50 / 1,000 places
Google Maps Places API – Area Coverage
Search Google Maps places and businesses in a circle, a polygon or by text. Adaptive grid for dense areas, one record per place, and a coverage report that shows what was searched.
Pricing
from $0.50 / 1,000 places
Rating
0.0
(0)
Developer
DataRelay
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Search Google Maps for places and businesses – in a circle, in any polygon, or by text – and get one clean record per place: name, categories, address, coordinates, phone, website, rating, reviews count, opening hours, accessibility, main photo, booking links, Place ID and CID. Or get the details of places you already know by Place ID, CID or Google Maps URL.
Why this Actor
- Covers the area, not just Google's first list. Google Maps shows at most 100–200 places per search. For a circle or a polygon, the Actor searches an adaptive grid: dense districts are split into smaller cells, empty land stays in large cells. Coffee shops within 1.5 km of Prague's Old Town Square: one search shows 75, the grid finds ~580–600.
- Exact boundaries. Only places inside your circle or polygon (holes respected) are delivered and charged.
- Coverage report. The run summary (
OUTPUT) lists per query the cells searched, cells that were not searched (time limit, blocking) and cells where Google may still know more places – so you know how complete the data is. - One record per place. A place found by several queries or cells is delivered and charged once.
- Filters before charging: closed businesses, minimum rating / reviews, categories, website or phone only.
- Details on demand: rating distribution (1–5 stars), the owner's description, the topics people mention in reviews and the
delivery / pickup services (DoorDash, Wolt, Uber Eats…) or the place's own online shop – for every
search result (
includeDetails) or for a list of known places (detailsmode). - Monitoring (with a ready-made digest for Slack / e-mail and the rating / review history of each place): repeat a search under a sync key and get only new places, or new and changed ones (phone, hours,
status…) with their previous values – places that disappear are reported too. Unchanged places are free. "New"
means first found under the key: Google's lists vary from run to run, so the first runs still add places that
existed before;
firstSeenAtand the review count tell them apart from newly opened ones. - Business status done right: temporarily and permanently closed places are told apart and skipped by default.
- Areas by name:
Praha 2,10115 Berlin,Kraków– boundaries from OpenStreetMap, no drawing needed. - How complete is it? An optional second pass on a shifted grid estimates how many places Google lists in the area (capture–recapture) – the summary says e.g. "584 found, ~620 estimated, 94 %".
- More places with less guessing: query expansion adds the categories the results have (
dentist→,Dental clinicOrthodontist). - Lead tools: exclude places you already have (CRM), filter by signals (popular without a website, unclaimed profile, open late…), phone type (mobile / landline), distance from a point.
- Match your list (
mode: match): find the Google Maps place of each business in your CRM list (name + address, phone or website), with a confidence – unmatched ones are free. - Competitors within a radius of each place: how many of the same type, their average rating, the nearest one.
- Free estimate of places and cost before a big run (
mode: estimate). - Everything in an area (
allPlaces: ~50 broad categories merged) and shops inside malls, airports and stations from their directories (includePlacesInside). - Many areas in one run: a GeoJSON collection of postal codes, districts or circles, each result tagged with its area name, and places per km² for each area.
- Map with the search coverage (where the grid searched, where Google may know more, what was not searched), GeoJSON, and a flat view for CSV / spreadsheets (hours and categories as one line).
- Market summary in the run's OUTPUT: places per km², top categories, rating distribution, chains vs independent places (by shared website, name or business profile owner).
- Resumes after a platform migration without delivering a place twice.
Who uses it
- Sales and lead generation – every business of a kind in a city, district or postal code, with phone, website and signals such as "no website" or "unclaimed profile"; your existing customers excluded.
- Market research and location planning – how many places of a kind per km², ratings, chains vs independents, competitors around each place.
- Data and CRM teams – match your list of businesses to Google Maps (Place ID, phone, website, hours) and refresh known places by Place ID.
- Monitoring – new, changed and closed places in an area every week, as a ready-made Slack / e-mail digest.
- AI agents and automations – a documented input schema, one record per place, statuses for every input and a run summary for decisions.
Quick start
{"searchQueries": ["dentist"],"areaNames": ["Praha 2"]}
More examples:
| Goal | Input |
|---|---|
| A circle | {"searchQueries": ["coffee shop"], "centerLat": 52.52, "centerLng": 13.405, "radiusKm": 2} |
| A quick text search (no area) | {"searchQueries": ["pizza"], "location": "Naples, Italy", "maxPlaces": 50} |
| Several districts, tagged by name | {"searchQueries": ["gym"], "areaNames": ["Praha 2", "Praha 3", "Praha 10"]} |
| Leads without a website | {"searchQueries": ["plumber"], "areaNames": ["Kraków"], "requireSignals": ["no_website"], "onlyWithPhone": true} |
| Everything in a small area | {"allPlaces": true, "centerLat": 50.0755, "centerLng": 14.4426, "radiusKm": 0.3} |
| With details (rating distribution, delivery services) | {"searchQueries": ["restaurant"], "areaNames": ["10115 Berlin"], "includeDetails": true} |
| Shops inside a mall | {"searchQueries": ["Westfield Chodov"], "location": "Prague", "includePlacesInside": true} |
| Known places by Place ID, CID or URL | {"mode": "details", "places": ["ChIJ3XqKYCGVC0cRYE5lAu_5hSY", "https://maps.app.goo.gl/…"]} |
| Match a CRM list | {"mode": "match", "matchPlaces": [{"name": "Café Ebel", "city": "Prague", "id": "crm-1"}]} |
| New places every week | {"searchQueries": ["cafe"], "areaNames": ["Praha 2"], "syncKey": "praha2-cafes", "syncMode": "newOnly"} |
| How many places and what cost, first | {"mode": "estimate", "searchQueries": ["restaurant"], "areaNames": ["Prague"]} |
Measured
| Search | Places | Time |
|---|---|---|
| Coffee shops within 1.5 km of Prague's Old Town Square (one Google Maps search shows 75) | 582 | 4 min |
| Dentists in Praha 2 (district by name, 4.2 km²) | 139 | 1.7 min |
| Car repair shops within 8 km of Kladno (201 km²) | 224 | 1.5 min |
| Restaurants in the whole of Prague (city by name, 495 km²) | 7,673 | 41 min |
Runs of 2026-10-29 and 2026-10-30 on the Apify platform, default settings (256 MB).
Input
| Field | Example | |
|---|---|---|
mode | search | search (default), details, match or estimate. |
searchQueries | ["dentist", "dental clinic"] | What you would type into Google Maps. |
allPlaces, expandQueries | true | ~50 broad categories instead of queries; add the categories found. |
areaNames | ["Praha 2", "10115 Berlin"] | Districts, cities or postal codes; boundaries from OpenStreetMap. |
areas | GeoJSON FeatureCollection | Several named polygons or points with radiusKm. |
centerLat, centerLng, radiusKm | 52.52, 13.405, 2 | A circle (up to 150 km radius, 50,000 km²). |
polygon | GeoJSON Polygon / MultiPolygon | [longitude, latitude]; draw one at geojson.io. |
location | Prague, Czechia | Text search instead of an area: quick, up to 100–200 places per query. |
language, countryCode | de, DE | Language of names, categories, addresses and hours. |
maxPlaces, maxPlacesPerQuery, maxRunSecs | 500 | Limits (0 = none). |
skipClosed, minRating, minReviews, categories, onlyWithWebsite, onlyWithPhone | Filters; filtered places are not charged. | |
requireSignals, excludePlaces, nameMatch, distanceFromLat / Lng | ["no_website"] | Lead filters, your known places, name must contain the query. |
includeDetails, includePlacesInside, competitorRadiusMeters, estimateCompleteness | true, 300 | Details per place, places inside malls, competitors, completeness. |
places (details), matchPlaces (match) | Place IDs / {"name", "city"} | Known places to refresh; a business list to match. |
syncKey, syncMode, syncBaselineRuns, syncReset | "praha2-cafes", newOnly | Monitoring: only new or new + changed places on repeated runs. |
fields | ["phone", "website"] | Deliver only these fields (plus fid, placeId, name). |
Every field is described in the input form.
Output
One dataset item per place:
{"name": "Die Praxis Mitte - Zahnarztpraxis Dr. Christina Erdmann & Dr. Anna Trojan","placeId": "ChIJm7m4g-1PqEcR9qybv-6X6Ps","cid": "18151925349789445366","fid": "0x47a84fed83b8b99b:0xfbe897eebf9bacf6","categories": ["Zahnarzt", "Zahnästhetische Praxis", "Kinderzahnarzt"],"address": "Hinterhaus, Münzstraße 5, 10178 Berlin","street": "Hinterhaus, Münzstraße 5","neighborhood": "Mitte","locality": "Berlin","postalCode": "10178","countryCode": "DE","location": { "lat": 52.5240799, "lng": 13.4086904 },"rating": 4.7,"reviewCount": 152,"website": "https://www.die-praxis.berlin/","phone": "030 40367600","phoneInternational": "+493040367600","openingHours": [{"day": "wednesday","date": "2026-10-28","text": "08:00–20:00","intervals": [{ "open": "08:00", "close": "20:00" }]},{ "day": "saturday", "date": "2026-10-31", "text": "Geschlossen", "intervals": [] }],"timezone": "Europe/Berlin","closed": false,"googleMapsUrl": "https://www.google.com/maps/search/?api=1&query=…&query_place_id=ChIJm7m4g-1PqEcR9qybv-6X6Ps","searchQuery": "dentist","rank": 1,"missingFields": [],"fetchedAt": "2026-10-28T13:17:56.934Z"}
Also in every record: phoneType, leadSignals, distanceMeters (with a circle or a point), reviewHistory (with a
sync key), categoriesText and openingHoursText (one line each, for CSV), openingHoursSpecification
(schema.org), areaName (with areas), businessStatus (OPERATIONAL, CLOSED_TEMPORARILY, CLOSED_PERMANENTLY), googleType
(language-independent: restaurant, dentist, lodging…), hotelStars, claimThisBusiness, openNow, and with
details plusCode. With a sync key: change (new, changed, missing), changedFields, previousValues,
firstSeenAt.
More fields in every record: attributes – accessibility for now (
{ "group": "Accessibility", "key": "has_wheelchair_accessible_entrance", "name": "Wheelchair-accessible entrance", "value": true }imageUrl, reservationLinks
({ "provider": "OpenTable", "url": "…" }) and specialHours (brunch, delivery…). With details:
{"ratingDistribution": { "1": 19, "2": 25, "3": 60, "4": 120, "5": 1129 },"ownerDescription": "The Miners Old Town lies right in the heart of Prague, next to Staroměstské náměstí. …","reviewTopics": ["specialty coffee", "flat white", "outdoor seating"],"photoCount": 1048,"photos": ["https://lh3.googleusercontent.com/…=w1024-k-no"],"orderLinks": [{ "provider": "DoorDash", "url": "https://www.doordash.com/store/…", "services": ["delivery", "pickup"] },{ "provider": "Wolt", "url": "https://wolt.com/…", "services": ["delivery", "pickup"] }]}
In the details mode every input gets a record: status ok (charged), or not_found / invalid_input / failed
(only input and status, not charged).
null means Google shows no value for the place; missingFields lists such key fields. Opening hours are those
Google shows for the coming seven days (holidays included). Large ids are strings.
The key-value store also holds MAP – an HTML map of the places with the search coverage and a density layer –,
DIGEST (with a sync key) and GEOJSON (open both from the run's Output
tab). The run summary (OUTPUT in the key-value store) holds, per query: delivered and found places, cells, pages,
duplicates, places outside the area, saturatedCells and the list of unsearched cells with the reason.
Integrations
API – places as JSON in one call (waits for the run, up to 5 minutes):
curl -X POST "https://api.apify.com/v2/acts/datarelay~google-maps-api/run-sync-get-dataset-items?token=$APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"searchQueries": ["dentist"], "areaNames": ["Praha 2"], "maxPlaces": 200}'
For a spreadsheet-ready CSV add
&format=csv&fields=name,categoriesText,address,phone,website,rating,reviewCount,openingHoursText,googleMapsUrl
(hours and categories as one line each).
Google Sheets – in the Actor's (or a saved task's) Integrations tab add Google Sheets, choose the dataset view Flat (CSV / spreadsheet): every finished run appends or replaces the rows of your sheet.
Weekly monitoring with a Slack message:
- Save a task with your search,
"syncKey": "my-area"and"syncMode": "changes"(the first run only remembers the places). - Schedule the task (e.g. every Monday 7:00) in Schedules.
- In the task's Integrations add Slack (or a webhook to Make / Zapier / n8n) on Run succeeded, with the run's
key-value store record
DIGEST– a ready-made Markdown list of new, changed and missing places:
**my-area**: 3 new, 2 changed, 1 missing*New*• Coffee Bird – Pštrossova 1924/8, 110 00 Nové Město…
CRM enrichment – run "mode": "match" with your list of businesses (matchPlaces, with your ids) and import
the dataset back by inputId: Place ID, phone, website, rating, hours and the match confidence.
Pricing – what a job costs
Pay per event; platform usage and proxies are included (no compute or proxy costs on top).
| Event | Price (FREE / BRONZE) | When |
|---|---|---|
run-start | $0.001 | once per run, together with the first paid result |
place | $1.33 / $1.00 per 1,000 | delivered place: unique, inside the area, passing the filters |
place-details | $0.66 per 1,000 | details delivered (includeDetails, details mode, match with details) |
Higher plans pay less: place $0.66 (SILVER) and $0.50 (GOLD and above) per 1,000; place-details $0.50 and
$0.35. Filters are free.
| Typical job (BRONZE) | Cost |
|---|---|
| All 139 dentists in Prague 2 | $0.14 |
| 582 coffee shops within 1.5 km of central Prague | $0.58 |
| 1,000 places with details | $1.66 |
| 7,673 restaurants in all of Prague (495 km²) | $7.67 |
| Weekly monitor of an area, 5 new places in a week | $0.006 |
You don't pay for places removed by filters or exclusions, duplicates, unchanged places on monitored searches,
inputs that were not found, invalid or failed (details and match modes), the estimate mode, or a run that delivers
nothing (no start fee either). Use mode: estimate for the expected number of places and the cost before a large run.
Reliability (measured)
- Scale: all restaurants in Prague (495 km²): 7,673 places in 41 minutes, 2,488 Google requests, none blocked, on the default 256 MB.
- Proxies: pages go out through Apify's datacenter proxy first and switch to residential only for pages Google blocked twice – in our runs fewer than 1 % of datacenter requests were blocked.
- No duplicates after a restart: when the platform migrates a run, it resumes from its saved state and skips the places already in the dataset (tested: 855 of 855 unique).
- Checked every hour: scheduled control runs and alerts on blocked requests, parser misses and changes of Google's response format.
- If Google blocks every request of a run, the run finishes with
outcome: "no_results"inOUTPUTand nothing is charged.
Limits and good to know
- No reviews, photo galleries, popular times, price level or the full About tab – Google shows them only to signed-in users, and this Actor does not use Google accounts (details include the rating distribution, review topics and a few photos, not the reviews themselves).
- "Complete" means: every place Google lists for the query in the searched cells. Google does not list every business
for every query; use several queries (
dentist,dental clinic,orthodontist) orexpandQueriesfor the best coverage.OUTPUTlists the cells where Google may still know more (saturatedCells). - Google's lists vary a little between runs: two runs of the same search can differ by a few percent.
- A text search (
location) returns at most the 100–200 places Google lists for it – use an area for more. - Area names are resolved by OpenStreetMap (Nominatim); check
OUTPUT.areathat it found the area you meant. - Circles, polygons and area names crossing the 180° meridian (Fiji, Chukotka, the Aleutians) are split at it automatically. Areas over 50,000 km² should be split into several runs.
FAQ
Is it legal to collect this data? The Actor reads what Google Maps shows publicly to anyone without signing in: business names, addresses, opening hours, phone numbers and websites of businesses. It does not collect reviews or reviewers' names. If you process the data of sole traders or people, data protection rules such as GDPR apply to your use of it.
How is it different from other Google Maps scrapers? It covers areas, not single lists: the adaptive grid and exact boundaries find several times more places than one search, and the coverage report shows what was searched. It reads Google's data API directly instead of a browser, so it is fast and inexpensive.
Why are there no reviews? Google shows reviews only to signed-in users; this Actor does not use Google accounts.
How do I get only new places? Use a syncKey with syncMode: "newOnly" (or changes) and schedule the task.
Can I get the data into Google Sheets or my CRM? Yes – see Integrations; the flat dataset view is ready for CSV
and spreadsheets.
Not affiliated with Google
This is an independent Actor by DataRelay, not Google's official Places API. It reads the same data that the public Google Maps website shows.
Usage statistics
The Actor sends anonymous run statistics to the developer (mode and options, numbers of places and statuses, Google request counts, duration, the kind and size of the area and its centre rounded to ~10 km). Search queries, locations and your Apify user id are never sent – only keyed hashes, used to count repeated queries and distinct users. No results, place lists, account details or personal data are collected.
Changelog
- 0.1 – first version.