Google Maps Places Scraper: Google Places API, Phones, Hours avatar

Google Maps Places Scraper: Google Places API, Phones, Hours

Pricing

from $1.50 / 1,000 places

Go to Apify Store
Google Maps Places Scraper: Google Places API, Phones, Hours

Google Maps Places Scraper: Google Places API, Phones, Hours

Scrape Google Maps places by search term and location, area, Maps link, place ID or shared list. Every place inside your area: phone, website, rating, review count and stars, opening hours, address, plus code, coordinates. No login, no API key; only delivered places are charged. Misses free.

Pricing

from $1.50 / 1,000 places

Rating

0.0

(0)

Developer

Hyperbach

Hyperbach

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

a day ago

Last modified

Share

Google Maps places as data, logged out: search terms with a location (words, country / state / city / postal code fields, or your own GeoJSON area), Maps search links, place links, place IDs, CIDs or shared lists in — one row per place out. Each row has the name and categories, the full address and its parts, coordinates and plus code, phone, website, the rating, the review count and the 1–5-star review distribution, the opening hours with today's open status, the permanently-closed flag, the main image and photo count, the description and the attribute groups, reservation and order links, the owner, and every Google id (place ID, feature ID, CID, kgmid). Only places inside the area you asked for are delivered, each place once, and every search gets a free summary row with its verdict. No login, no API key, proxies handled for you.

$4.00 per 1,000 place rows on the Free plan, $3.00 on Starter. A run start is $0.0036. The default input returns about 50 rows for about $0.2036. A value that names nothing is a free row that says why.

Tested head-to-head on 2026-11-01

The job: one search (restaurant, New York, USA), 50 places. Every Actor ran on it the same day from the same harness; a rival's cost is what a buyer account paid, this Actor's is its list price on the Free plan. Fields counts the filled fields of a typical row. the lane is not in cand; the leader is bead 4's (compass), the second the next maps actor by users/30d in the census copy (lukaskrivka, 2,418); compass and clockworks (tiktok-search) take no run under a $0.50 cap, so theirs is $0.50. Re-measured monthly.

ActorRowsFirst rowRun timeCostFieldsFailures
this Actor505.3 s6.0 s$0.1549none
compass/crawler-google-places508.1 s13 s$0.1538none
lukaskrivka/google-maps-with-contact-details5015 s212 s$0.2841none

Why this Google Maps scraper

  • Only places inside your area. Google Maps answers a screen's list with places outside it (73 of 241 places of a New York screen in our tests; a few-match search on a Denver screen answered places 3.5 half-screens away). Every place is tested against the area you asked for — the city's or region's boundary from OpenStreetMap, your polygon or radius, the link's screen, or the postal code on the place's own address — and the places outside it are dropped free and counted on the search row.
  • The whole area, not one screen. One Maps screen lists a few hundred places at most (103 to 313 in our tests), so a dense area hides places. A screen whose list is full is split into four smaller screens, again and again (the four quarters of a New York screen held 369 places its own list did not), and each search row says COMPLETE, CAPPED or TRUNCATED with the screens it read.
  • The review distribution on every row, in the same call. The count of 1-, 2-, 3-, 4- and 5-star reviews comes with each place of the list (on 2,641 of 2,644 rated places in our tests, summing to the review count on all of them) — no add-on and no second call per place.
  • Your limit holds. A search asks Google for no more places than it still has room for, and each place is claimed once for the whole run, so a search delivers at most maxCrawledPlacesPerSearch places and a run at most maxItems — a place found by two searches is one row and one charge.
  • Fast and plain. No browser and no scrolling: one call reads a whole screen's list. The common job (50 restaurants in New York) is one call, its first row a few seconds after the start (2.6 to 5.5 seconds on 10 of 11 runs of builds 0.1.5 to 0.1.8; one waited 21 seconds); a place ID is one call of about 5 KB.
  • Every input answers. A search with no result, a location nobody can place, a place ID Google does not know (checked on a second connection) and a value that names nothing each get a free row that says which. A run never ends green and silent.

Who it's for

  • Lead generation and sales — every business of a category in a city or a postal code, with phone, website and address parts, filtered by rating, review count or website, each place once.
  • Local SEO and market research — ratings, review distributions and categories of every competitor in an area, the rank each one holds in Google's own list, the claimed flag.
  • Analysts and data teams — typed rows keyed by the place ID with coordinates and plus codes for mapping, a summary row per search with its verdict, and the lane leader's column names in snake_case.
  • Monitoring new openings — a scheduled run with onlyNew that delivers only the places an area did not have before.

Quick start

Restaurants in a city (the common job)

{
"searchStringsArray": [
"restaurant"
],
"locationQuery": "New York, USA",
"maxCrawledPlacesPerSearch": 50
}

Several terms in several cities

{
"searchStringsArray": [
"dentist",
"orthodontist"
],
"locationQuery": "Austin, Texas",
"locationQueries": [
"Dallas, Texas"
],
"maxCrawledPlacesPerSearch": 100
}

Every coffee shop in a postal code

{
"searchStringsArray": [
"coffee"
],
"postalCode": "10001",
"countryCode": "us"
}

A 2-km radius around a point, 4 stars or more, with a website

{
"searchStringsArray": [
"pizza"
],
"customGeolocation": {
"type": "Point",
"coordinates": [
-73.9857,
40.7484
],
"radiusKm": 2
},
"placeMinimumStars": "four",
"website": "withWebsite"
}

Place IDs and Maps links

{
"placeIds": [
"ChIJA4JRKzCLwokRHBTppuJxhpg"
],
"startUrls": [
"https://www.google.com/maps/search/restaurant/@40.801,-73.843,13z"
]
}

Switching from compass/crawler-google-places?

Your input works as it is. Each name in the left column is read as this Actor's own field and the run log says so (read <theirs> as <ours>); a name marked not read is ignored with a note. A value in the other Actor's shape, an object list or its own date form, is read too.

compass/crawler-google-placesthis Actorwhat to know
searchStringsArraysearchStringsArrayThe same name (searchString and searchStrings are read too).
locationQuerylocationQueryThe same name; locationQueries adds more locations in one run.
maxCrawledPlacesPerSearchmaxCrawledPlacesPerSearchThe same name; 0 = every place of the area.
languagelanguageThe same name.
startUrlsstartUrlsThe same name and shape.
placeIdsplaceIdsThe same name; feature ids and CIDs too.
categoryFilterWordscategoryFilterWordsThe same name.
placeMinimumStarsplaceMinimumStarsThe same name; placeMaximumStars and minimumReviews are extra here.
websitewebsiteThe same name and values.
skipClosedPlacesskipClosedPlacesThe same name.
countryCodecountryCodeThe same name, with state, county, city, postalCode and customGeolocation.
maxReviewsnot readNot read: reviews are not a row of this Actor.
maxImagesnot readNot read: images are not read.
scrapePlaceDetailPagenot readNot read: the record is read from Google's place data, no detail page.
scrapeContactsnot readNot read: no website enrichment here (maximumLeadsEnrichmentRecords, scrapeSocialMediaProfiles likewise).
searchMatchingnot readNot read: every place of the search is delivered; filter by categoryFilterWords.
allPlacesNoSearchActionnot readNot read: a search link's screen or a GeoJSON area reads an area whole.

What differs:

  • The search inputs carry the same names (searchStringsArray, locationQuery, maxCrawledPlacesPerSearch, language, the country, state, county, city and postal code fields, customGeolocation, startUrls, placeIds, categoryFilterWords, placeMinimumStars, website, skipClosedPlaces), so a saved input runs as it is.
  • This Actor delivers the place record (phone, website, rating, review count and stars, hours, address, coordinates); the leader's add-ons (reviews, images, questions, contacts enrichment, leads, competitor analysis, directories, the detail page) are not read, and the price is the place.
  • startUrls takes strings or {"url": …} items; a shared list link and a ?cid= link work too.

Output

One row per place (charged), and one free summary row per search term × location, link or place ID:

fieldmeaning
record_typeplace on a place row (charged); search on a search term × location's free summary row; target on the free summary row of a link or a place ID.
statusok, or why an input gave no place: no_results, outside_area_only (every place Google answered lay outside the area), not_found (a place ID or link Google does not know, two connections agreeing), location_not_found, invalid_input, failed, not_read (a limit or the time limit stopped the run first).
inputThe value you gave that this row answers (the search term, the link, the place ID).
search_stringThe search term that found the place (search rows and the places they delivered).
search_areaThe place the location resolved to (New York, United States), the link's screen, or your custom area.
rankThe place's position among the places its search delivered, in the order Google answered them, from 1.
titleThe place's name.
category_nameThe place's main Google category.
categoriesEvery Google category of the place, the main one first.
addressThe full address as Google shows it.
streetThe street address.
cityThe city.
postal_codeThe postal code.
stateThe state or region.
country_codeThe place's country, two letters (US).
neighborhoodThe neighbourhood Google names for the place.
locationThe coordinates: {lat, lng}.
located_inThe place it sits in, as Google's "Located in" names it (a mall, a hotel, a pier): {name, fid}.
floorThe floor Google gives in the address (Floor 1).
plus_codeThe global plus code (Open Location Code) of the place's coordinates (87G8R5JF+J3).
plus_code_compoundThe local plus code with its town (R5JF+J3 Bronx, New York), on rows read by place ID, link or list.
phoneThe phone number as Google shows it.
phone_unformattedThe phone number in international form (+17182395362).
websiteThe place's own website; null when Google shows none.
website_domainThe website's host, www. removed.
total_scoreThe average rating, 1 to 5; null for a place with no rating.
reviews_countHow many reviews the place has.
reviews_distributionThe review count by star: {one_star, two_star, three_star, four_star, five_star}, summing to reviews_count.
reviews_urlGoogle's page of the place's reviews.
opening_hoursThe week's hours, Monday first: [{day, hours}] in the run's language (Open 24 hours, Closed, split hours with a comma).
additional_opening_hoursOther hour sets Google lists (brunch, delivery, pickup, happy hours): [{name, hours: [{day, hours}]}].
open_nowOpen at the time of the run, by the weekly hours in the place's timezone; null without hours or for a closed place.
timezoneThe place's timezone (America/New_York).
permanently_closedtrue when Google marks the place permanently closed.
temporarily_closedtrue when Google marks the place temporarily closed (a seasonal place out of season, a closure Google was told of); open_now is then null.
place_idGoogle's place ID (ChIJ…): the key to join on.
fidGoogle Maps' feature ID (0x…:0x…): each place is delivered once a run by it.
cidThe place's CID (the number in maps.google.com/?cid=).
kgmidThe Knowledge Graph id (/g/…).
business_profile_idThe id of the place's Google Business Profile, when it has one.
urlThe place on Google Maps (…/maps/search/?api=1&query=…&query_place_id=…).
search_page_urlThe Google Maps search (the screen) that returned the place.
image_urlThe place's main photo.
images_countHow many photos the place has on Google Maps.
descriptionGoogle's own short description of the place, when it has one.
owner_descriptionThe description the business wrote itself ("From the business"), when Google serves it: mostly on a place ID or place link input.
additional_infoThe attribute groups Google shows (Accessibility, Service options, Amenities…, and Highlights such as LGBTQ+ friendly): `{group: [{attribute: true
reserve_table_urlsTable reservation links: [{url, source}].
order_urlsOnline order links: [{url, source}] (a delivery service, or Google's own order page).
claimedfalse when Google shows 'Claim this business' on the place (the owner has not claimed it).
owner_nameThe owner's name as Google shows it for the business.
owner_idGoogle's id of the owner account.
is_advertisementtrue for an ad; the signed-out lists carry none (always false).
languageThe language of the run (language).
verdictOn a summary row: COMPLETE (read to the end), CAPPED (a limit stopped it), TRUNCATED (a screen was still full at the smallest size: note says), PARTIAL (the run stopped first).
rows_deliveredOn a summary row: the places it delivered.
tiles_readOn a search row: the map screens the search read.
outside_areaOn a search row: the places Google answered that lay outside the area (dropped, free).
filtered_outOn a summary row: the places your filters left out (free).
noteWhy a summary row has its status or verdict: the screens and calls read, places outside the area, repeats, filters.
scraped_atWhen this row was read (UTC).

Example record:

{
"record_type": "place",
"status": "ok",
"input": "restaurant",
"search_string": "restaurant",
"search_area": "New York, United States",
"rank": 4,
"title": "Superfine",
"category_name": "Restaurant",
"categories": [
"Restaurant",
"Bar",
"Brunch restaurant",
"Live music venue",
"Organic restaurant"
],
"address": "126 Front St, Brooklyn, NY 11201",
"street": "126 Front St",
"city": "Brooklyn",
"postal_code": "11201",
"state": "New York",
"country_code": "US",
"neighborhood": "Dumbo",
"location": {
"lat": 40.7023726,
"lng": -73.9875072
},
"located_in": null,
"floor": null,
"plus_code": "87G8P226+WX",
"plus_code_compound": null,
"phone": "(718) 243-9005",
"phone_unformatted": "+17182439005",
"website": "https://www.superfine.nyc/",
"website_domain": "superfine.nyc",
"total_score": 4.4,
"reviews_count": 1436,
"reviews_distribution": {
"one_star": 58,
"two_star": 34,
"three_star": 113,
"four_star": 345,
"five_star": 886
},
"reviews_url": "https://search.google.com/local/reviews?placeid=ChIJYSFd6zNawokRpLteYhPEu_A&q=restaurant&authuser=0&hl=en&gl=US",
"opening_hours": [
{
"day": "Monday",
"hours": "Closed"
},
{
"day": "Tuesday",
"hours": "2 PM–1 AM"
},
{
"day": "Wednesday",
"hours": "12 PM–1 AM"
},
{
"day": "Thursday",
"hours": "12 PM–2 AM"
},
{
"day": "Friday",
"hours": "12 PM–2 AM"
},
{
"day": "Saturday",
"hours": "12 PM–2 AM"
},
{
"day": "Sunday",
"hours": "11 AM–1 AM"
}
],
"additional_opening_hours": [
{
"name": "Kitchen",
"hours": [
{
"day": "Monday",
"hours": "Closed"
},
{
"day": "Tuesday",
"hours": "2–10 PM"
},
{
"day": "Wednesday",
"hours": "12–10 PM"
},
{
"day": "Thursday",
"hours": "12–11 PM"
},
{
"day": "Friday",
"hours": "12–11 PM"
},
{
"day": "Saturday",
"hours": "12–11 PM"
},
{
"day": "Sunday",
"hours": "11 AM–10 PM"
}
]
}
],
"open_now": true,
"timezone": "America/New_York",
"permanently_closed": false,
"temporarily_closed": null,
"place_id": "ChIJYSFd6zNawokRpLteYhPEu_A",
"fid": "0x89c25a33eb5d2161:0xf0bbc413625ebba4",
"cid": "17346673977281395620",
"kgmid": "/g/1vfp93pt",
"business_profile_id": null,
"url": "https://www.google.com/maps/search/?api=1&query=Superfine&query_place_id=ChIJYSFd6zNawokRpLteYhPEu_A",
"search_page_url": "https://www.google.com/maps/search/restaurant/@40.6971040,-73.9795380,10.8z",
"image_url": "https://lh3.googleusercontent.com/grass-cs/AABkmLefeNNqWvqBqBN14GrnX6AF-gZH2o6LCiZ0ZAcNgOaVx9SADOOUeeQ3vYlUDTrTbZzAkOb_i3nr8KL_FluAg2nsPeExxjKVQuyR1DOFwjNPTkbJ1mqiBQzO65piLDSk6Eqvbv2O=w122-h92-k-no",
"images_count": 1120,
"description": "Local, seasonal Mediterranean fare is offered in a converted warehouse space with an open kitchen.",
"owner_description": null,
"additional_info": {
"Accessibility": [
{
"Wheelchair accessible entrance": true
},
{
"Wheelchair accessible restroom": true
},
{
"Wheelchair accessible seating": true
},
{
"Wheelchair accessible parking lot": true
}
]
},
"reserve_table_urls": [
{
"url": "https://www.opentable.com/restaurant/profile/109453?ref=1068",
"source": "opentable.com"
}
],
"order_urls": [
{
"url": "https://www.google.com/searchviewer/42?cvd=CLw_EiUKI-ICIDIeEhciFdLX29IPDwoLL2cvMXZmcDkzcHQYADoDCPAN&hl=en-US&gl=us&fo_m=MfohQo559jFvMUOzJVpjPL1YMfZ3bInYwBDuMfaXTPp5KXh-&utm_source=tactile&gei=mXPhatrlIbf8ptQP_PSdcA&ei=mXPhatrlIbf8ptQP_PSdcA&fo_s=OA,SOE&opi=79508299&ebb=1&cs=0&foub=mcpp",
"source": "Google"
}
],
"claimed": true,
"owner_name": "Superfine",
"owner_id": "100943994162160384374",
"is_advertisement": false,
"language": "en",
"verdict": null,
"rows_delivered": null,
"tiles_read": null,
"outside_area": null,
"filtered_out": null,
"note": null,
"scraped_at": "2026-10-28T04:01:30Z"
}

Pricing

Pay for the places a run delivers, plus one run start; no platform usage is billed to you. The place price falls with your Apify plan.

eventunitFreeStarterScaleBusiness
Place (place)per 1,000$4.00$3.00$2.00$1.50
Run start (start)per run$0.0036$0.0036$0.0036$0.0036

A place is $4.00 per 1,000 on the Free plan ($0.004 a row) and $3.00 on Starter, whatever found it (a search, a link, a place ID or a shared list) and whatever it carries: the review distribution, the hours, the photo count, the attributes and every id are inside the row's price, with no add-on. Each run that delivers a place also pays the run start, $0.0036 once; a run that delivers none pays nothing at all. So one place costs $0.0076 on the Free plan and $0.0066 on Starter; 50 places $0.2036 and $0.1536; 1,000 places $4.0036 and $3.0036; every search and link of a run shares one start. Free: every search's summary row, a place outside your area, a place a filter, excludePlaceIds or onlyNew leaves out, a place another search of the run already delivered (one row, one charge), a place ID Google does not know, a location nobody can place, a value that names nothing, and a search left unread at maxItems or the time limit. A run that stops early (a timeout, an abort) is charged for the places it delivered. maxItems counts the charged places.

Before the first request the log names the price of a place at your plan, the run start and the most the run can cost: each place ID or place link is one place, each search, search link or shared list maxCrawledPlacesPerSearch, and maxItems over the whole run. A search with no cap has no bound but your charge limit: Google shows no count, and the search ends where Google's list of the area ends. In our uncapped tests one term in one city gave 22 and 23 places (bakeries in Hoboken, two runs, 23–24 s), 358 (hair salons in Boise, 91 s), 688 (dentists in Austin, 229 s) and 753 (coffee shops in Portland, 286 s). A whole state or country takes longer: a state outside the US is read layer by layer, and Queensland's first row came after 112 s, so leave such a run its default timeout (one hour), not a short one. Set maxItems, maxCrawledPlacesPerSearch or a charge limit for a lower maximum. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.

Usage patterns

  • Search terms and locations — searchStringsArray holds what you would type into Google Maps (restaurant, dentist, a business name). Each term is searched in each location: locationQuery and locationQueries in words (a city, county, state, country or neighbourhood: the boundary comes from OpenStreetMap), or the fields countryCode, state, county, city, postalCode, or customGeolocation (a GeoJSON Polygon, MultiPolygon, or a Point with radiusKm). A term with no location reads Google's own answer to the words. The row's search_area names the place each location resolved to.
  • Links and place IDs — startUrls takes Google Maps links: a search link with its @lat,lng,zoom (its screen is the area, walked in full), a place link, a ?cid= link, a shared list (/maps/placelists/list/…) or a maps.app.goo.gl short link. placeIds takes place IDs (ChIJ…), feature IDs (0x…:0x…) or CIDs. A place link or ID gives one row with the whole place; a list gives a row per place on it.
  • Depth and limits — A search walks its area until Google's lists end: a screen whose list is full is split into four, down to about 0.3 km wide; maxCrawledPlacesPerSearch stops each search earlier and maxItems stops the run. The search row's verdict says COMPLETE (the area was read to the end), CAPPED (a limit stopped it) or TRUNCATED (a screen was still full at the smallest size, or the search read 1,500 screens), with the screens read in tiles_read.
  • Filters — categoryFilterWords, placeMinimumStars, placeMaximumStars, minimumReviews, website (with or without), skipClosedPlaces and excludePlaceIds are applied to each place's own fields. A place a filter leaves out is not delivered and not charged; the search row and the run summary count them by filter. The filters apply to searches and lists; of them only excludePlaceIds applies to a place ID you named (the exclude list wins), and a CID in it matches the place's other ID forms.
  • Language — language is Google's language code (en, de, fr, pt-BR…): categories, day names and the hours text come in it, as Google Maps shows them in that language.

Input configuration

fieldtypedefaultwhat it does
searchStringsArrayarray[]What to look for, as you would type it into Google Maps: restaurant, dentist, coffee shop, a business name. Each term is searched in each location below. Give a location for an area walk; a term with no location reads Google's own answer to the words.
locationQuerystring""Where to search, in words: a city, county, state, country or neighbourhood (New York, USA, Berlin, Germany, Queensland, Australia). The place's boundary comes from OpenStreetMap, and only places inside it are delivered.
locationQueriesarray[]More locations in words, one a line: every search term is searched in each of them (and in Location).
maxCrawledPlacesPerSearchinteger0The most places one search term in one location (or one search link, one shared list) delivers. 0 = every place the area holds. A search asks Google for no more than this.
languagestring"en"Google's language code for the results (en, de, fr, es, pt-BR, ja…): categories, day names and hours come in it.
countryCodestring""Instead of Location: the country as a two-letter code (us, gb, de). Combine it with state, county, city or postal code.
statestring""A state or region (California).
countystring""A county (Kings County).
citystring""A city (Austin).
postalCodestring""A postal code with its country (10001 and country code us): only places whose own address carries this postal code are delivered.
customGeolocationobject{}An exact area instead of a location: a GeoJSON Polygon or MultiPolygon (longitude first, as GeoJSON writes it), or a Point with radiusKm, e.g. {"type": "Point", "coordinates": [-73.98, 40.75], "radiusKm": 2}. Only places inside it are delivered.
startUrlsarray[]Google Maps links: a search link (google.com/maps/search/pizza/@40.75,-73.99,14z: its screen is the area), a place link, a ?cid= link, a shared list or a maps.app.goo.gl short link. A search link's screen is walked in full; a place link gives that place; a list gives every place on it.
placeIdsarray[]Google place IDs (ChIJ…), feature IDs (0x89c28b302b518203:0x988671e2a6e9141c) or CIDs (10990597158921114652): one row each with the whole place.
categoryFilterWordsarray[]Keep a place only when one of its Google categories contains one of these words (pizza, italian). A place left out is not charged.
placeMinimumStars`` / two / twoAndHalf / three / threeAndHalf / four / fourAndHalf""Keep places rated at least this (an unrated place is left out).
placeMaximumStars`` / two / twoAndHalf / three / threeAndHalf / four / fourAndHalf""Keep places rated at most this (an unrated place is kept).
minimumReviewsinteger0Keep places with at least this many reviews; 0 = any.
websiteallPlaces / withWebsite / withoutWebsite"allPlaces"Keep every place, only places with a website, or only places without one.
skipClosedPlacesbooleanfalseLeave out places Google marks as permanently closed.
excludePlaceIdsarray[]Place IDs, feature IDs, CIDs or place links never delivered or charged (a list you already have).
onlyNewbooleanfalseDeliver only the places an earlier run with the same memory did not deliver. For a scheduled task that watches an area for new places.
stateStoreNamestring""The name of the memory onlyNew keeps (letters, digits, '.', '_', '-'); empty = a name derived from the inputs.
maxItemsinteger0The most charged places of the whole run, over every search and link; 0 = no cap beyond your charge limit.
proxyUrlstringYour own proxy (scheme://user:pass@host:port) for every call instead of ours. Leave empty: the Actor brings its own connections at no cost to you.

Errors

A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:

  • the status message starts with INPUT REJECTED;
  • the dataset holds one row, {"error": true, "code": "…", "message": "…"}, and no results;
  • the key-value store record ERROR holds the same object.

From code, check error on the first row before reading results.

A search with no place, a location nobody can place, a place ID Google does not know or a value that names nothing is not an error: it gets one free row with its status and a note, and the run goes on with the others. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.

FAQ

Why are some places of my search missing, or the count lower than another tool's?

This Actor delivers only places inside the area you asked for; Google's own list answers places outside the screen too, and tools that keep them report more rows. The search row counts the places dropped as outside_area. A search with maxCrawledPlacesPerSearch stops at it; with 0 the whole area is walked.

Do you return popular times, the price level or 'people also search'?

Not yet. The two calls this Actor reads (Google's list and its place call) carry none of them (0 of 2,796 places in our tests had a price level). Google's own place page carries them, one page per place, and some other Actors read it; this Actor does not deliver empty columns for them.

Do you return reviews or e-mails?

No: each place's rating, review count and 1–5-star distribution, but not the review texts (reviewers are private persons) and no contact finding on the place's website.

What does a place cost when two of my searches find it?

One row and one charge: each place is claimed once for the whole run, by its Google feature ID.

What is temporarily closed?

Google marks both on the place's record: permanently_closed and temporarily_closed (a seasonal place out of season is temporarily closed). skipClosedPlaces skips the permanently closed ones only. The run summary counts any other value of the closed mark it meets (status_unknown).

Is today's open status live?

open_now is computed from the place's weekly hours at the moment of the run, in the place's own timezone; Google's record carries no live status text.

Can I use my own proxy?

Yes, proxyUrl. Leave it empty and the Actor uses its own connections at no extra cost.

Where does the area's boundary come from?

For a location in words or fields, from OpenStreetMap's Nominatim (© OpenStreetMap contributors); for a postal code, from Google's own postal-code place and the places that carry the code; when OpenStreetMap does not answer, from the view Google Maps moves to for the words.

Integration

JavaScript

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/google-maps-scraper').call({"searchStringsArray": ["restaurant"], "locationQuery": "New York, USA", "maxCrawledPlacesPerSearch": 50});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Python

from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/google-maps-scraper').call(run_input={'searchStringsArray': ['restaurant'], 'locationQuery': 'New York, USA', 'maxCrawledPlacesPerSearch': 50})
items = client.dataset(run['defaultDatasetId']).list_items().items

CLI

$apify call hyperbach/google-maps-scraper --input '{"searchStringsArray": ["restaurant"], "locationQuery": "New York, USA", "maxCrawledPlacesPerSearch": 50}'

REST

curl -X POST "https://api.apify.com/v2/acts/hyperbach~google-maps-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
-H 'Content-Type: application/json' -d '{"searchStringsArray": ["restaurant"], "locationQuery": "New York, USA", "maxCrawledPlacesPerSearch": 50}'

AI agents and MCP

Apify's MCP server offers this Actor as a tool to Claude, Cursor, VS Code and any other MCP client. Connect https://mcp.apify.com?tools=hyperbach/google-maps-scraper and ask, for example: "Find 50 restaurants in New York on Google Maps with phone numbers and opening hours". The agent fills the input from the table above and reads the rows from the run's dataset. A field under the name another Actor gives it is read as this Actor's own: searchStrings, searchString, searchTerms, queries as searchStringsArray; urls, url, links, searchUrls as startUrls; placeIdList, place_ids, placeId as placeIds; location, locationName, near as locationQuery (and more).

n8n, Make and Zapier

The Apify node in n8n, the Apify app in Make and the Apify integration in Zapier run this Actor on a schedule or from a trigger and read its dataset. A webhook on the run's end (Integrations on the Actor page) sends the rows on to your own endpoint. Nothing to install on our side.

Support

Disagree with a charge? Write to apify@hyperbach.com with the run ID. We will ask Apify to compensate you, and the charge comes back to your Apify account as platform credit.

Did it do the job? A short review on the Store, at any rating, helps the next buyer choose.

See also

  • Airbnb Scraper — Airbnb listings for a place and dates, with the price for the stay to the cent, the calendar and the host.
  • Zillow Scraper — Zillow listings for sale, for rent and sold, by ZIP, city or search URL, with the Zestimate, and a property's price history.
  • Google Hotels Scraper — the hotels Google lists for a place and a stay, with the stay price and, on request, the price on each booking site.
  • Google Flights Scraper — every itinerary Google Flights lists for a one-way, round-trip or multi-city search, with the exact fare.
  • Eventbrite Scraper — the events of a place on Eventbrite, with the dates, the venue, the price range and the organizer.
  • ChatGPT Scraper — what ChatGPT, Gemini, Perplexity and Google's AI Mode and AI Overviews answer for your queries, with every source they cite.

This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.