Google Maps Places Scraper
Pricing
from $1.50 / 1,000 place scrapeds
Google Maps Places Scraper
Every Google Maps place for a search and area in one run: contacts, reviews breakdown, popular times, hours, photos and 50+ more fields.
Pricing
from $1.50 / 1,000 place scrapeds
Rating
0.0
(0)
Developer
Dev
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
2 days ago
Last modified
Categories
Share
Get every Google Maps place for a search and an area in one run, with 81 fields per place: contacts from the business's own website, the full 1–5 star review breakdown, review keywords, popular times, live busyness, 7-day opening hours and whether it is open right now, Google's review summary, the menu or services list with prices, owner, plus code, photos, menu and booking links, and a hotel block. No second actor, no API key, no chaining.
Built for lead lists, market mapping, local-SEO audits and location research, wherever you need the whole row rather than a name and a phone number.
Why this one
- One run, one row, all fields. Search, place details and website contacts are fetched in the same run. You never have to feed one scraper's output into another.
- Exact review counts. The review count is the sum of Google's own star histogram, so
reviewsandreviewBreakdownalways agree. On a measured 500-place run, the histogram's average matched the displayed rating to within 0.1 on every place. - Stays inside the area you asked for. Cities are searched inside their real boundary (a "New York City" search does not return Jersey City). Results are gathered outward from the point you searched.
- Fast and light. 500 places, with full details and website contacts, in 27–37 seconds with a residential proxy pool (about 50 seconds on the smallest datacenter pool). Most of the tail is waiting on slow business websites.
- Tracks changes between runs. Name a search with
monitoringKeyand every place comes back markednew,changedorunchanged, with the exact changes ("rating 4.2 → 3.9", "now closed", "phone changed"). AddonlyChangesand scheduled re-runs return — and charge for — only what changed. - Clean contacts, free. Phones normalised to international format with their line type (mobile / landline). Every email's domain checked for a mail server, and the business's own-domain addresses ranked first.
- Machine-readable. Opening hours as open/close times per day and price ranges as numbers with a currency — no parsing on your side.
- Fails loudly. A run that finds nothing ends as Failed with the reason ("the location could not be found", "all search requests were blocked", "your filters removed every place"). It never ends as a successful empty dataset.
Quick start
Search a category in a city:
{ "searchTerms": ["dentist"], "location": "Jaipur, India", "maxPlacesPerSearch": 500 }
Search a precise area (a circle or a box):
{ "searchTerms": ["coffee shop"], "customArea": { "lat": 40.7549, "lng": -73.9840, "radiusKm": 2 } }
Look up specific places (URLs, maps.app.goo.gl short links, or place IDs):
{ "startUrls": [{ "url": "https://maps.app.goo.gl/…" }], "placeIds": ["ChIJNV5sGiH8mzkR_hUMnJI9RHU"] }
Input
| Field | Default | What it does |
|---|---|---|
searchTerms | — | What to search for. Each term is searched over the whole area. |
location | — | City, neighbourhood or region, resolved with OpenStreetMap. |
customArea | — | {lat, lng, radiusKm} or {south, north, west, east}. Overrides location. |
startUrls | — | Google Maps search URLs (…/maps/search/pizza/@lat,lng,14z) or place URLs. |
placeIds | — | Place IDs (ChIJ…) to fetch directly. |
maxPlacesPerSearch | 500 | Cap per search term. |
maxPlaces | 0 (no cap) | Cap for the whole run. Exact: you are never charged past it. |
coverage | balanced | fast / balanced / exhaustive: how finely the area is scanned (see below). |
scrapeContacts | true | Read each business website for emails, extra phones, social and directory profiles. |
language | en | Language of categories, hours and labels. |
countryCode | from location | Two-letter market code. |
minRating | — | Only places rated at least this (unrated places are excluded). |
website | all | all / withWebsite / withoutWebsite. |
skipClosed | false | Leave out places Google marks as closed. |
maxImages | 10 | Photo URLs per place. |
verifyEmails | true | Check each email domain can receive mail; rank own-domain addresses first. Free. |
monitoringKey | — | Name a search to track changes between runs (see below). |
onlyChanges | false | With monitoringKey: return and charge only new or changed places. |
proxyConfiguration | Apify Proxy | Proxy for Google requests. |
Output
One item per place. Every key is always present: empty lists are [], and unknown values are null, never a made-up zero.
| Field | Meaning |
|---|---|
placeUrl, placeId | Google Maps link and place ID |
businessName, category, allCategories, categoryId | Name, main category, all categories, and a language-independent category slug |
placeTags | Identity and inclusivity attributes the business declares ("Identifies as women-owned", "LGBTQ+ friendly") |
rating, reviews, reviewBreakdown | Star rating, review count, and the 1–5 star histogram |
reviewKeywords | The topics reviews mention most, with counts |
reviewsUrl | Google's reviews page for the place |
priceRange | Google's price band, e.g. $10–20 or ₹200–800 |
phone, website | Main phone (international format) and website |
emails, additionalPhones, socials, directoryProfiles | From the business's own website: emails, other phones, Facebook/Instagram/X/LinkedIn/YouTube/TikTok/Pinterest, and Yelp/Tripadvisor/Foursquare pages |
address, street, neighborhood, city, state, postalCode, country | Address, as Google's own labelled components |
latitude, longitude, entranceLocation | Map pin and Google's navigation arrival point |
plusCode, locatedIn, floor | Plus Code; the venue it is inside (e.g. a mall); floor, when the address states one |
permanentlyClosed, temporarilyClosed, unclaimed | Status flags |
owner | Business profile owner {name, id, url} |
description, attributes | The business's description; Google's attribute groups (Service options, Accessibility, Payments, …; for hotels, the amenities: Wi-Fi, Pools, Parking, …) |
openingHours, specialHours | All seven days; per-service hours (e.g. drive-through, delivery) |
popularTimes, liveOccupancyPercent, liveStatus | Hourly busyness for each weekday; live busyness (only when Google has a live reading) |
coverPhoto, photos, photoCount | Real photos (Street View frames are kept apart in streetViewImage) |
relatedPlaces | Places at the same address (e.g. a mall's tenants) |
ownerPosts | The business's own updates |
menuUrl, reserveTableUrl, reservationLinks | Menu and booking links |
hotelType, hotelDescription, similarHotels, hotelAds | Hotel class, description, comparable hotels nearby, and live booking offers |
editorialSummary, reviewsSummary | Google's one-line summary of the place, and its summary of what reviewers say |
offerings | What the business lists: menu items, services or products, with section, description, price and photo |
openNow, currentStatus, hoursConfirmed | Open at the moment of the run (in the place's own time zone), e.g. Open · closes 18:00; and Google's "Confirmed by this business …" note |
nameLocal | The name in the local script, when Google has one (e.g. थे रॉयल हर्मिटेज) |
openingHoursStructured | Hours as data: {"Monday": [{"open": "06:30", "close": "18:00"}], "Sunday": []} |
priceMin, priceMax, priceCurrency | The price range as numbers: "₹200–800" → 200, 800, INR |
phoneE164, phoneType | The main phone in international format, and mobile / landline / toll_free … |
emailDetails | Per email: onWebsiteDomain, freeProvider, role (info@, sales@ …) and domainAcceptsMail |
visitDuration | How long people typically stay, e.g. People typically spend 1-3.5 hours here |
reviewHighlights | The review quotes Google features, with the reviewer's profile link |
evCharging | EV charging stations at the place, with connector types and speeds |
storeDirectory | For malls and venues: shop categories and how many places each holds |
photoDetails | Photos with caption, dish, uploader, upload date, size, and whether the owner posted it |
changeType, changes | With monitoringKey: new / changed / unchanged and [{field, from, to}] |
searchString, rank, scrapedAt, streetViewImage, coverage | Run context. coverage says whether details and contacts were fetched and where the review count came from. |
A real (trimmed) item:
{"businessName": "Om Dental Clinic","placeUrl": "https://www.google.com/maps/place/?q=place_id:ChIJDy5wQEGxbTkRoIr-g0ZK874","category": "Medical clinic","allCategories": ["Medical clinic", "Dental clinic", "Dentist", "Orthodontist"],"rating": 5, "reviews": 26,"reviewBreakdown": { "oneStar": 0, "twoStar": 0, "threeStar": 0, "fourStar": 0, "fiveStar": 26 },"reviewKeywords": [{ "keyword": "dental care", "count": 4 }, { "keyword": "friendly doctor", "count": 4 }],"phone": "+91 90011 78656","address": "Plot no.10, Gurunanak Colony, Tripolia Bazar, Jaipur, Rajasthan 302002","postalCode": "302002", "country": "IN", "latitude": 26.9348028, "longitude": 75.8237201,"plusCode": "WRMF+WF Jaipur, Rajasthan","openingHours": { "Monday": "10 am–2 pm", "Tuesday": "10 am–2 pm", "Sunday": "10 am–2 pm" },"photoCount": 12,"coverage": { "detail": "ok", "contacts": "ok", "reviewCountSource": "histogram" }}
Pricing
Pay per event. You pay only for places actually delivered:
| Event | Price | When |
|---|---|---|
| Place scraped | $0.0015 | Each place row, including all Google Maps details |
| Contacts scraped | $0.001 | Only when the place has a website and it could actually be read |
Example: 1,000 places, 600 of them with a readable website, costs 1,000 × $0.0015 + 600 × $0.001 = $2.10. Duplicates, and places removed by your filters, are never charged. Set a maximum charge on the run and it stops cleanly when that is reached.
Tracking changes between runs
Give a search a name and schedule it:
{ "searchTerms": ["dentist"], "location": "Jaipur, India", "monitoringKey": "jaipur-dentists", "onlyChanges": true }
The first run returns everything as new. Each later run compares with the one before and returns only places that are new or whose name, category, rating, review count, phone, website, address, price range, hours or closed status changed — each with changes: [{"field": "rating", "from": 4.2, "to": 3.9}]. Unchanged places are not charged. The run summary (SUMMARY in the key-value store) also lists places the previous run found and this one did not. Snapshots are kept in your account's places-monitor key-value store.
How coverage works
Google Maps answers a search for one map view at a time, and favours places near the middle of that view. To cover a whole city, the area is split into a grid of views, searched from the centre outwards. Any view that is still full of new places is split into four smaller, closer views. coverage sets how fine the starting grid is:
fast: large views, the main results, the fewest requests.balanced(default): a good compromise for neighbourhoods and cities.exhaustive: small views, finds the long tail of small businesses in a big area, and takes longer.
When an area is too large for the chosen coverage, each row's coverage.coarsened is true and the log says so. Use exhaustive, or a smaller area, for more complete results.
Known limits
Stated plainly, so nothing surprises you:
temporarilyClosedis alwaysfalse. Google's closed flag does not say whether a closure is temporary, so closed places showpermanentlyClosed: true.skipClosedfilters search results. Places you look up by URL or ID are always returned, withpermanentlyClosedtelling you their status.relatedPlaceslists places at the same address (tenants of a mall, a hotel's restaurant), not Google's "People also search for".flooris filled only when the business writes its floor into its address.liveStatus/liveOccupancyPercentandhotelAdsare live data. They appear only when Google has a live reading or live offers at the moment of the run.photoCountis empty, not zero, for places with no photos.emailscome from the business's own site. On sites built with a shared website builder, they can include the builder's addresses.- Review text is not included. You get the count, the star breakdown and the review keywords.
FAQ
The run failed. Why? The status message says why: an unknown location, requests blocked by Google, a term that names a single place outside your area, or filters that removed everything. A failed run with no results is never charged for places.
Do I need a proxy? The default Apify Proxy works. Google serves fuller place data through the proxy than from shared platform IPs, so keep it on.
Can I stop at N places? Yes. maxPlaces is exact, and the run also respects the maximum charge you set.