Google Maps Scraper avatar

Google Maps Scraper

Pricing

from $0.70 / 1,000 place scrapeds

Go to Apify Store
Google Maps Scraper

Google Maps Scraper

Stop wasting your budget on slow, resource-heavy browser-based scrapers. This is the fastest, most cost-effective, and data-rich Google Maps scraper on Apify, designed for high-scale lead generation and market research.

Pricing

from $0.70 / 1,000 place scrapeds

Rating

4.8

(18)

Developer

VortexData

VortexData

Maintained by Community

Actor stats

42

Bookmarked

2.2K

Total users

652

Monthly active users

2.9 hours

Issues response

3 hours ago

Last modified

Share

Google Maps Scraper extracts local businesses from Google Maps. No API key, no quota. One place per row: name, category, address, coordinates, phone, website, rating and opening hours, plus emails and reviews when you want them.

  • πŸ” Search: by keyword and place, dentist in Austin, Texas, United States
  • πŸ—Ί Or by a shape you draw: a polygon, a radius, a Google Maps URL, a Place ID
  • 🧲 Contacts: emails, phones and socials from each business's own website
  • ⭐ Reviews: text, rating, author, date
  • 🌍 Any country, any language: local names, local categories
  • 🎯 One business, one row: deduplicated across the whole run
  • πŸ’³ Pricing: per result, never per hour
  • πŸ“€ Export: JSON, CSV, Excel, XML, HTML, or straight from the API

How to scrape Google Maps

{
"searchStringsArray": ["plumber", "electrician"],
"locationQueries": ["Austin, Texas, United States", "Dallas, Texas, United States"],
"maxCrawledPlacesPerSearch": 300
}

Two search terms Γ— two locations Γ— 300 = up to 1,200 places. Press Start. Rows show up in the Output tab while the run is still going.

Good search terms. Different trades, each finding places the others miss: ["plumber", "electrician", "hvac contractor", "roofing contractor"]

Poor search terms. Variants of one word, costing time without adding places: ["plumber", "plumbers", "plumbing", "plumber near me"]

Write thisNot this
dentistdentist in Austin. The term is searched in every location
One location per lineAustin, Dallas. Read as one name
Paris, Texas, USAParis. A shared name resolves to the biggest one
50 on your first run5000 before you have seen the rows

Output

Google Maps Scraper output example

{
"title": "Bird & Branch Coffee Roasters",
"categoryName": "Coffee shop",
"categories": ["Coffee shop", "Cafe"],
"address": "359 W 45th St, New York, NY 10036, United States",
"city": "New York",
"postalCode": "10036",
"countryCode": "US",
"location": { "lat": 40.7602998, "lng": -73.9907758 },
"phone": "+1 917-265-8444",
"website": "https://www.birdandbranch.com/",
"totalScore": 4.6,
"reviewsCount": 412,
"currentStatus": "Closed",
"openingHoursToday": { "day": "Thursday", "hours": "7 AM–5 PM" },
"placeId": "ChIJTVhsxFNYwokRXgPwYnY0vgI",
"url": "https://www.google.com/maps/search/?api=1&query=Bird+%26+Branch&query_place_id=ChIJTVhsxFNYwokRXgPwYnY0vgI",
"searchString": "coffee shop",
"scrapedAt": "2026-08-27T10:30:00Z"
}

If a column is empty, Google didn't have it.

What data does Google Maps Scraper extract?

GroupColumns
Identitytitle categoryName categories categoryId description subTitle
Addressaddress street city postalCode state countryCode neighborhood plusCode timezone
Positionlocation entranceLocation
Contactphone phoneUnformatted website websiteDisplay
ReputationtotalScore reviewsCount reviewsUrl
Open or closedopeningHoursToday currentStatus nextOpensAt permanentlyClosed temporarilyClosed
PhotosimageUrl imageUrls imagesCount imageCategories
HotelshotelStars hotelPrice hotelAmenities hotelDescription hotelCheckInDate hotelCheckOutDate
Commercemenu price reserveTableUrl bookingLinks
ListingownerName claimThisBusinessUrl placeTags additionalInfo isAdvertisement
IdentifiersplaceId cid fid kgmid url
RunsearchString rank language scrapedAt searchPageUrl

categoryId reads identically in every language: jewelry_store in Tokyo and in Lisbon.

The Output tab has ready-made views: Overview, Lead generation, Reviews, Hotels, Full details.

Add-ons

Scrape emails and contacts from Google Maps

{ "extractContactsFromWebsite": true }

Opens each place's own website and adds emails additionalPhones whatsapps facebooks instagrams linkedIns twitters youtubes tiktoks pinterests tripadvisors yelps foursquares.

  • It keeps addresses that belong to the site. One on a different domain only survives if the page clearly presents it as a contact, so you don't end up with the web agency that built the site.
  • The list is ordered most useful first, so the first address is the one to write to.
  • You're charged only where it found something.
  • Expect fewer emails than places. Plenty of businesses have no website, and plenty of websites never show an address.
  • It skips two dozen global chains. A head office isn't the branch you found.

Scrape Google Maps reviews

{ "maxReviewsPerPlace": 20, "reviewsSort": "newest" }

You get the text and the rating, when it was written, and who wrote it: their name, their profile link, how many reviews and photos they've posted, whether they're a Local Guide. Plus the language it was written in, and any photos attached.

Sort by newest, most_relevant, highest or lowest. It asks for up to 8000 per place, and reviewsScrapedCount tells you how many actually arrived.

Each review is charged. 20 reviews Γ— 100 places = 2,000 charged reviews, and the run takes considerably longer. Start low.

Search by area, URL or Place ID

Scrape a custom area, polygon or radius

For a delivery zone, a sales territory, or a radius around a point.

{ "customGeolocation": { "type": "Point", "coordinates": [-74.006, 40.7128], "radiusKm": 5 } }

Paste whatever geojson.io, QGIS or Google My Maps gives you: a Point with radiusKm, a Polygon, a MultiPolygon, a Feature or a FeatureCollection. Draw something smaller than a district and it can come back empty.

Scrape Google Maps by URL

A CRM export, a supplier list, competitors you watch.

{ "startUrls": [{ "url": "https://maps.app.goo.gl/xxxx", "userData": { "crmId": "A-1042" } }] }

Accepts: a Google Maps share link Β· a …/maps/place/… URL Β· a copied search page with a map view.

Returns: userData back as inputUserData, so results join onto your own records.

Scrape Google Maps by Place ID

{ "placeIds": ["ChIJreV9aqYWdkgROM_boL6YbwA"] }

Full ChIJ… identifiers only, from the Places API or Google's Place ID Finder. Short /g/… ids aren't Place IDs and neither are URLs. If you've got a URL, paste it as a URL.

Results

How many results will Google Maps Scraper return?

maxCrawledPlacesPerSearch applies per search term, per location, so terms Γ— locations Γ— the limit is a ceiling rather than a forecast.

You get fewer when:

  • The area holds less. Forty coffee shops is forty coffee shops. Past that, Google pads its answer with unrelated places, saved and charged like any other unless you switch Only what you searched for on.
  • Search terms overlap. A place two terms both find is one row, not two.

Extra languages add places rather than copies. Each one searches the same ground again, and you only get what the earlier pass missed.

Every run publishes a map of its results, showing the area it searched with its places on it β€” as many as a browser can open, and the legend counts any that did not fit. You can look at your coverage instead of guessing at it.

Filter Google Maps results

In the formFieldEffect
πŸ“ Only places inside the areageoStrictMatchDrops everything outside the search area. A place Google files under your city counts as inside.
🚚 Keep unlocated placeskeepUnverifiedLocationsKeeps places Google gives no address: a plumber with a van, a studio run from home. Only acts when the setting above is on, which otherwise drops them.
⏩ Skip closed placesskipClosedPlacesDrops places Google marks closed, temporarily as well as permanently.
⏩ Only what you searched forskipPlacesNotMatchingSearchDrops places it recognises as unrelated. What it cannot judge is kept.

You're not charged for anything these drop, and it doesn't count against your limit either. The run just keeps looking.

With Only what you searched for on, every place kept carries searchTermMatch:

ValueMeaning
matchThe search term names this kind of place
arguableOnly this run's own results vouch for it
not-a-matchNot what you searched for
not-judgedNot enough evidence to decide. Kept, and charged

It gets rid of most of the obviously unrelated ones and rarely throws away something you wanted. It isn't a guarantee of a clean list, though. Anything it can't judge, it keeps, and you pay for that. A search term that names a kind of place (bakery, pest control service) judges well; a vague phrase can leave almost every place undecided.

Pricing

How much does it cost to scrape Google Maps?

Charged per result, never per hour. The Pricing tab shows current rates.

EventCharged
Place scrapedPer row in your dataset
Place with contact detailsOnly where the add-on found something
Review scrapedPer review
Actor startOnce per gigabyte of the run's memory

Both add-ons are off by default. Set maxTotalChargeUsd before you start and the run stops cleanly when it gets there, keeping everything it found.

Limits and speed

  • Places limit: 10 minimum, no maximum.
  • Rows are saved as they're found, so a run that stops early keeps everything up to that point.
  • Raise the run's timeout for multi-city jobs, or it'll stop before it's done.
  • The Setup block in the log prints what each location resolved to, and flags ambiguous ones.

FAQ

Do I need a Google Maps API key?

No. No Google billing account, no quota, nothing to apply for.

Why did I get fewer places than I asked for?

Four reasons, and the run's summary names which one:

  • The area holds fewer places than you asked for.
  • Several of your search terms found the same place, so you get it once.
  • A filter dropped rows. You weren't charged for them.
  • The run hit its timeout or your charge ceiling. Everything found by then is saved.

Why are the results not what I searched for?

Once an area runs out of what you asked for, Google keeps answering with whatever else is nearby, and those places get saved like any other. Switch Only what you searched for on and they're dropped before they reach you, at no charge. Whatever stays carries a searchTermMatch verdict.

Why are there places from the next town?

Google returns what it finds relevant, and near a boundary that takes in the neighbours. Leave Only places inside the area off and they arrive marked insideSearchArea: false. Switch it on and they're dropped.

Switch Keep unlocated places on with it, or you also lose every mobile trade. They have no coordinates to check.

My run returned nothing at all. What went wrong?

Usually one of four. The location resolved to a different place of the same name. Your search term is too specific to be a category anyone's filed under. A filter removed everything. Or the Place IDs and URLs weren't valid places. The run writes one row saying which, marked recordType: "run-diagnostic".

Why are some emails missing or wrong?

Emails come off each place's own website. No website, no email, and a website that never publishes an address gives you nothing either.

By default it keeps only addresses on that site's own domain, which is what stops an agency's address landing on its client's row.

How do I make a run faster?

The run tells you what is holding it up. Near the top of the log, Run plan prints a Bounded by line with one of two answers.

  • this memory's CPU. Raise the run's memory. Apify grants CPU in proportion to it, and the Actor sizes its own worker pools from the CPU it is given, so a larger machine searches more areas at once.
  • the far end. It is waiting on Google, not on itself. More memory buys nothing here.

Can I run this on a schedule or from my own code?

Yes. Schedule it from the Actor page, or start it through the Apify API.

It collects business listings Google Maps shows to anyone, plus what a business publishes on its own website. It logs into nothing and takes no personal data.

What you may do with that data depends on where you and the businesses are. Apify's guide to ethical web scraping is a good start; your own case is a question for a lawyer.

Support

Read the run first: the Log ends with what was searched, saved and dropped, and the OUTPUT record says the same via the API.

Still wrong? Open the Issues tab and include the run. Release notes are on Changelog.

Includes a place-category taxonomy Β© Overture Maps Foundation, CC BY 4.0.