Google Maps Scraper - Business Leads & Emails

Eimantas V · @amethyst

Scrape Google Maps places by keyword and city: name, address, phone, website, rating, reviews, hours and coordinates, plus emails and socials from websites.

About

Google Maps Scraper extracts business listings from Google Maps: name, address, phone, website, rating, review count, opening hours, categories, coordinates and IDs, plus optional emails and social profiles from each business's website. Search by keyword and location, or paste Google Maps URLs and Place IDs. No login, no API key, no browser.

{
  "title": "Italala Caffè",
  "categoryName": "Coffee shop",
  "address": "Vokiečių g. 1, Vilnius, 01130 Vilniaus m. sav.",
  "phoneUnformatted": "063033363",
  "website": "https://www.italala.lt/",
  "totalScore": 4.7,
  "reviewsCount": 1519,
  "location": { "lat": 54.6785822, "lng": 25.2859445 },
  "openingHours": [{ "day": "Monday", "hours": "8 am–8 pm" }, { "day": "Tuesday", "hours": "8 am–8 pm" }],
  "placeId": "ChIJ6-1bDxWU3UYRue3sXBtJaiQ",
  "emails": ["[email protected]"],
  "instagrams": ["https://www.instagram.com/italalacaffe"]
}

Measured: 3,000 Manhattan restaurants in 2 min 7 s; 300 Chicago dentists with place details and website contacts in 60 s.

What does Google Maps Scraper do?

It searches Google Maps the way you would, "dentist" in "Austin, Texas", and returns every place as one row. A large location is split into map cells automatically, so a city returns thousands of places instead of the ~120 that one Google Maps search shows. Field and input names are the same as in compass/crawler-google-places, so existing inputs and integrations keep working.

  • Search a term in a city, region, country, postal code or a polygon you draw. Or paste Google Maps place links, search links, share links, Place IDs and CIDs.
  • Lead data in every row: phone in local and international format, website, full address split into street, city, postal code and state, rating, review count, categories, hours for the whole week, coordinates, Place ID and CID.
  • Optional add-ons: emails, phones and social profiles (Facebook, Instagram, LinkedIn, X, YouTube, TikTok, Pinterest) from each business's website, and place details with the 1-5 star breakdown, review topics and the top reviews.
  • Filters: category, minimum rating, with or without a website, closed places, exact name match, inside the location only.
  • Clear errors. Searches that find nothing, unknown locations and invalid IDs return an error row instead of failing the run. Each place is delivered once per run, even when several searches find it.
  • Built for automation. Run it on a schedule, call it from the API, or connect it to an AI agent through the Bytewells MCP server.

Why it is fast and cheap

It reads the same data endpoints the Google Maps website loads in your browser, over plain HTTP, without running a browser. One request returns up to ~150 places with all their fields, so 1,000 places take a handful of requests and a few seconds. That is why a run uses a fraction of the compute of browser-based scrapers.

What data can you extract from Google Maps?

FieldExampleWhat it is
titleItalala CaffèBusiness name
categoryName, categoriesCoffee shopMain category, and all of them
address, street, city, postalCode, state, countryCodeVokiečių g. 1, Vilnius…Full address and its parts
phone, phoneUnformatted(0-630) 33363, 063033363Local and international format
websitehttps://www.italala.lt/The business's own site
totalScore, reviewsCount4.7, 1519Average rating and number of reviews
openingHours, additionalOpeningHours[{"day":"Monday","hours":"8 am–8 pm"}]Hours for each weekday; delivery, kitchen and happy hours
location{"lat":54.678,"lng":25.286}Coordinates of the pin
placeId, cid, fid, kgmidChIJ6-1bDxWU3UYRue3sXBtJaiQGoogle's IDs (Places API Place ID included)
urlhttps://www.google.com/maps/search/?api=1&…Opens the place on Google Maps
descriptionBread-themed branch of the famed Italian market…Google's editorial summary
additionalInfo{"Accessibility":[{"Wheelchair accessible entrance":true}]}Attributes and the owner's highlights
permanentlyClosed, temporarilyClosedfalseClosed status
claimThisBusinessfalsetrue when no owner manages the listing: a local-marketing lead
reserveTableLinks, orderOnlineLinks[{"name":"opentable.com","url":…}]Booking and ordering links
imageUrl, imagesCount, imageUrls1183Main photo, number of photos, photo URLs
searchString, searchLocation, rank, insideSearchAreacoffee shop, 2Which search found the place, and where
emails, phones, facebooks, instagrams, linkedIns, twitters, youtubes, tiktoks, pinterests["[email protected]"]Contacts add-on: from the business's website
reviewsDistribution, reviewsTags, reviews, plusCode, ownerDescription, hotelStars{"fiveStar":1266,…}Place details add-on

How to scrape Google Maps places

  1. Click Try for free. Type what you are looking for in Search terms ("plumber", "coffee shop") and where in Location ("Austin, Texas, USA").
  2. Set Places per search. It also caps how much compute the run uses.
  3. Turn on the add-ons you need, then click Start. 1,000 places take about a minute.
  4. Open the Output tab (views: Overview, Contacts / leads, Location, Ratings, Top reviews, Opening hours), or read the dataset as JSON.

How much does it cost to scrape Google Maps?

One flat monthly rental, shown on this page, with a free trial. There is no per-place fee: scrape as many places as you need.

Runs use your credits for compute, as every Actor does. Measured on Bytewells: 100 New York restaurants in 15 seconds at 1 GB for $0.0006 of credits, and 20 Austin dentists with place details, reviews and website contacts in 10 seconds for $0.0004. Google Maps answers without a proxy, so compute is the whole cost: about $0.01 per 1,000 places, $0.02 with details and contacts.

Input

{
  "searchStringsArray": ["dentist", "orthodontist"],
  "locationQuery": "Austin, Texas, USA",
  "maxCrawledPlacesPerSearch": 500,
  "website": "withWebsite",
  "scrapeContacts": true
}
FieldDefaultNotes
Search terms (searchStringsArray)restaurantOne per line; each is searched in every location
Location (locationQuery)New York, USAOne per line; split into map cells for full coverage
Places per search (maxCrawledPlacesPerSearch)100Per term and location: your main cost lever
Max places in total (maxItems)noneOptional cap for the whole run
Language (language)enLanguage of categories, hours and summaries
Country, state, county, city, postal codenoneInstead of Location, as separate fields
Custom search area (customGeolocation)noneGeoJSON polygon, or a point with radiusKm
Google Maps URLs (startUrls), Place IDs (placeIds)noneSingle places, or a search link with its map view
FiltersoffCategory, minimum rating, website, closed, exact name, inside the location (on)
Place details (scrapePlaceDetailPage)offStar breakdown, review topics, top reviews, plus code, owner description
Contacts from website (scrapeContacts)offEmails, phones and social profiles from the business's site
Image URLs per place (maxImages)0Photo URLs in imageUrls
ProxyautomaticLeave empty: the Actor picks the address itself

Output

Each place is one row. The Overview view shows the key columns; every export includes all fields. With place details on, reviews holds the top reviews:

{
  "stars": 5,
  "text": "Everything was absolutely perfect. The service, pastries, and drinks were 11/10…",
  "publishedAtDate": "2026-05-17T15:30:22.997Z",
  "reviewerName": "Austeja G",
  "isLocalGuide": true,
  "reviewDetailedRating": { "Food": 5, "Service": 5, "Atmosphere": 5 },
  "reviewContext": { "Price per person": "€10–15", "Reservation": "Reservations not required" }
}

A search, URL or Place ID that cannot be read becomes a row with "recordType": "error" instead of failing the run:

errorCodeMeaning
LOCATION_NOT_FOUNDThe location is not on the map. Write it as "City, Country"
NOT_FOUNDNo place for this Place ID, CID or link
BAD_AREAThe custom search area is not valid GeoJSON
BLOCKED, RATE_LIMITED, UNREACHABLEGoogle refused or did not answer; run again
PARSE_FAILEDGoogle changed its format; please report it

The run's RUN_SUMMARY record has the totals: places, map views, places each filter dropped, and why the run stopped.

Tips and limits

  • Different terms find different places. "plumber" and "electrician" add places; "plumber" and "plumbers" mostly find the same ones.
  • "Only places inside the location" is on by default. A city's map rectangle also covers its neighbours; turn it off to keep them (each row has insideSearchArea).
  • Reviews: the top ones only. Google shows up to 5 reviews per place to visitors who are not signed in, and this Actor never signs in. Full review history, popular times and price levels are only shown to signed-in Google users, so they are not included.
  • Attributes are the groups Google's website shows to visitors who are not signed in (accessibility and the owner's highlights).
  • Review counts: Google sometimes hides them from visitors who are not signed in. The Actor detects that and asks again from another session, within a set number of retries per run; where Google keeps hiding it, reviewsCount is null and the run log says how many.

FAQ

Is it legal to scrape Google Maps?

This Actor collects business listings that Google Maps shows to anyone, plus what businesses publish on their own websites. It does not log in. Reviewer names are personal data under the GDPR: turn off Include reviewer names if you do not need them, and check with a lawyer what your use case allows. Google Maps is a trademark of Google LLC; this Actor is not affiliated with or endorsed by Google.

Can I use it through the API?

Yes. Start runs from the API, schedule them, and read the dataset as JSON. The output schema links the places, the leads view and the run summary.

Can AI agents use it?

Yes, through the Bytewells MCP server. The input fields and the Store description are written so an agent can fill them in from a request like "dentists in Austin with emails".

I switched from compass/crawler-google-places. Do I need to change my input?

Usually not: searchStringsArray, locationQuery, maxCrawledPlacesPerSearch, language, countryCode, city, state, county, postalCode, customGeolocation, startUrls, placeIds, the filters, scrapePlaceDetailPage and scrapeContacts work the same, and the output uses the same field names. Inputs for features this Actor does not have (full review history, people leads) are ignored.

Why did I get fewer places than I asked for?

The area holds fewer places for that term, filters dropped some, several searches found the same places (each is delivered once), or the run hit its timeout. A run also stops early, with everything found so far saved, when Google keeps answering with places it already found, places outside the area or places your filters remove: splitting a big area or a long list of similar terms across runs gets the rest. RUN_SUMMARY says which (stoppedBy).

FAQ

What data does it return for each place?
Name, address, phone, website, rating, review count, opening hours, categories and coordinates. Optional: place details, the top reviews, and e-mails and social profiles found on the business's website.
Can it cover a whole city?
Yes. Give a keyword and a location; the area is searched cell by cell so a whole city is covered, not only the first screen of results. Only places inside the location are kept by default, and each row has insideSearchArea.
How much does it cost?
One flat monthly rental, shown on this page, with a free trial and no per-place fee. Google Maps answers without a proxy, so compute is the whole cost. Measured on Bytewells: 100 New York restaurants in 15 seconds for $0.0006, about $0.01 per 1,000 places, $0.02 with details and contacts.
Does it get all reviews of a place?
No. Google shows up to 5 reviews per place to visitors who are not signed in, and this Actor never signs in. Full review history, popular times and price levels are shown only to signed-in users.
I use compass/crawler-google-places. Do I need to change my input?
Usually not. searchStringsArray, locationQuery, maxCrawledPlacesPerSearch, language, countryCode, city, state, postalCode, startUrls, placeIds, the filters, scrapePlaceDetailPage and scrapeContacts work the same, and the output uses the same field names.
Why did I get fewer places than I asked for?
The area holds fewer places for that term, filters dropped some, several searches found the same places (each is delivered once), or the run reached its timeout. RUN_SUMMARY says which (stoppedBy).
Can I use it through the API or from AI agents?
Yes. Start runs through the Bytewells API (bytewells.com/docs/api), schedule them and read the dataset as JSON; webhooks work too. The API is Apify-compatible, so apify-client works with the Bytewells base URL. AI agents can run it as a tool through the Bytewells MCP server (bytewells.com/docs/mcp).

More Actors from the same publisher.

View all from @amethyst