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

Rising star

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

5.0

(10)

Developer

VortexData

VortexData

Maintained by Community

Actor stats

18

Bookmarked

711

Total users

192

Monthly active users

2.4 hours

Issues response

23 minutes ago

Last modified

Share

πŸ—ΊοΈ Google Maps Scraper: Places, Reviews, Emails & Local Leads

Scrape Google Maps places by keyword, location, Google Maps URL, Place ID, or custom GeoJSON area. Extract business names, categories, addresses, phone numbers, websites, ratings, coordinates, reviews, and Google identifiers.

For lead generation, the Actor can also enrich saved places with public website emails, extra phone numbers, WhatsApp links, social profiles, and business-profile links such as Tripadvisor, Yelp, and Foursquare.

  • βœ… No Google Maps API key required.
  • ⚑ HTTP-first Google Maps scraping, without browser automation for normal search.
  • πŸ“¦ Export results from Apify datasets as JSON, CSV, Excel, XML, RSS, or HTML.

🎯 Best Use Cases

Use caseWhat you get
🧲 Local lead generationBusiness names, categories, addresses, phones, websites, emails, social profiles, and lead-qualification links.
πŸ™οΈ Market researchBusiness density, categories, ratings, websites, and coordinates across cities, regions, or custom areas.
⭐ Review monitoringGoogle Maps reviews attached to each scraped place.
πŸ“ Area-based scrapingCity, suburb, ZIP/postal code, radius, polygon, or multipolygon searches.
πŸ”— Exact place scrapingKnown places from Google Maps URLs, query_place_id URLs, or raw Google Place IDs.
πŸ”Œ AutomationScheduled runs, Apify API, webhooks, integrations, CLI, and SDK workflows.

πŸ“¦ Extracted Data

GroupFields
🏷️ Place identitytitle, categoryName, categories, description, subTitle
πŸ“ Address and locationaddress, street, city, state, postalCode, countryCode, location, insideSearchArea
☎️ Google Maps contactsphone, phoneUnformatted, website, websiteDisplay
βœ‰οΈ Website contactsemails, additionalPhones, whatsapps
🌐 Social profilesfacebooks, instagrams, linkedIns, twitters, youtubes, tiktoks, pinterests
🧭 Business-profile linkstripadvisors, yelps, foursquares
⭐ Ratings and statustotalScore, reviewsCount, currentStatus, openingHoursToday, permanentlyClosed, temporarilyClosed
πŸ’¬ Reviewsreviews, reviewsScrapedCount, review text, author data, dates, photos when available
πŸ”— Google identifiersplaceId, fid, cid, kgmid, canonical Google Maps url
🏨 Hotel fieldshotelStars, hotelPrice, hotelAmenities, hotelCheckInDate, hotelCheckOutDate

The Output tab has focused views:

  • Overview - common place fields.
  • Lead generation - business identity plus contact and lead fields.
  • Reviews - review payload and review counters.
  • Hotels - hotel-specific fields.
  • Full details - complete record grouped by meaning.

Apify also provides its built-in All fields view.

πŸš€ Quick Start

For a normal keyword + location search, fill in:

  1. πŸ” searchStringsArray - one search term per line.
  2. πŸ“ locationQueries - one complete location per line.
  3. πŸ’― maxCrawledPlacesPerSearch - maximum saved places per search term and location.
{
"searchStringsArray": ["coffee shop"],
"locationQueries": ["Brooklyn, New York, United States"],
"maxCrawledPlacesPerSearch": 200
}

This saves up to 200 coffee shop places for that search/location, with fields such as name, category, address, phone, website, rating, coordinates, Place ID, and Maps URL.

πŸ§ͺ Input Recipes

βœ‰οΈ Lead Generation With Website Contacts

Enable extractContactsFromWebsite when you need public contacts from business websites.

{
"searchStringsArray": ["dental clinic"],
"locationQueries": ["Austin, Texas, United States"],
"maxCrawledPlacesPerSearch": 500,
"extractContactsFromWebsite": true
}

How enrichment works:

  • Places without websites are still saved.
  • For places with websites, the Actor checks the homepage first.
  • If the homepage has no email, it tries lightweight contact-style pages such as /contact, /contact-us, /about, /booking, /impressum, and local-language equivalents.
  • Rows are pushed to the dataset as soon as each website is processed.
  • Website enrichment can find emails, extra phones, WhatsApp links, social profiles, Tripadvisor, Yelp, and Foursquare links.

If you need only rows with emails, filter the finished dataset by emails.length > 0.

⭐ Reviews

Set maxReviewsPerPlace above 0.

{
"searchStringsArray": ["pizza"],
"locationQueries": ["Brooklyn, New York, United States"],
"maxCrawledPlacesPerSearch": 100,
"maxReviewsPerPlace": 100,
"reviewsSort": "newest"
}

The Actor can fetch up to 1000 reviews per place. Higher limits take longer and use more requests.

πŸ”Ž Multiple Search Terms

{
"searchStringsArray": ["restaurant", "coffee shop", "bakery"],
"locationQueries": ["Helsinki, Finland"],
"maxCrawledPlacesPerSearch": 300,
"language": "fi",
"additionalLanguages": ["en"]
}

Each search term has its own result limit. Extra languages run additional full passes and can improve coverage in multilingual regions.

πŸ“ Multiple Locations

Use multiple locationQueries entries to run the same search terms across several independent areas.

{
"searchStringsArray": ["plumber", "electrician"],
"locationQueries": [
"Seddon, Victoria, Australia",
"Footscray, Victoria, Australia"
],
"maxCrawledPlacesPerSearch": 100
}

Use one complete location per line. Do not combine two cities in one location string.

maxCrawledPlacesPerSearch applies per search term per location. The example above can save up to about 400 rows before deduplication: 2 search terms Γ— 2 locations Γ— 100.

πŸ”— Google Maps URLs And Place IDs

Use startUrls when you already know exact places or copied a Google Maps search page with a visible map viewport.

{
"startUrls": [
{
"url": "https://www.google.com/maps/search/?api=1&query=Example+Business&query_place_id=ChIJreV9aqYWdkgROM_boL6YbwA",
"userData": { "externalId": "crm-123" }
}
],
"maxReviewsPerPlace": 50
}

Accepted direct inputs:

  • βœ… Full Google Maps place URLs in startUrls.
  • βœ… Google Maps share links in startUrls.
  • βœ… Search URLs with @lat,lng,zoom or @lat,lng,meters in startUrls.
  • βœ… Raw Google Place IDs in placeIds only when they come from Google Places API, Google's Place ID Finder, or a query_place_id URL parameter.

Do not paste /g/... values, short IDs, fids, numeric CIDs, or full URLs into placeIds. Paste the full Google Maps URL into startUrls instead.

Search URLs without @lat,lng,zoom or @lat,lng,meters are ignored because no search area is available.

πŸ›°οΈ Custom Search Area

Use customGeolocation when automatic location boundaries are too small, too large, or not accurate enough.

{
"searchStringsArray": ["plumber"],
"maxCrawledPlacesPerSearch": 1000,
"customGeolocation": {
"type": "Point",
"coordinates": [-74.006, 40.7128],
"radiusKm": 20
}
}

Supported custom areas:

  • GeoJSON Point with radiusKm
  • GeoJSON Polygon
  • GeoJSON MultiPolygon

For exact suburbs, service areas, or multiple separate areas, use a real Polygon or MultiPolygon.

Very small polygons are risky for discovery searches: Google Maps may return no places inside a tiny cell. For grid-cell workflows, scrape a larger real search area first, then assign saved places to small cells by coordinates after the run.

πŸ“ Strict Area Matching

geoStrictMatch=true keeps only places whose coordinates are inside the resolved location or custom GeoJSON area.

Normal strict behavior:

  • in-area places are saved;
  • out-of-area places are dropped;
  • GeoJSON Polygon and MultiPolygon inputs use exact point-in-polygon checks;
  • small geocoded areas such as suburbs and neighborhoods use exact OpenStreetMap boundaries when available;
  • broader geocoded areas and Point + radiusKm use the resolved bounding box.

When the area itself is empty

A city's official boundary is often far smaller than the city people mean. Mendoza's is 54 kmΒ², and its industrial suppliers all sit in Godoy Cruz, GuaymallΓ©n and MaipΓΊ β€” so a strict search of "Mendoza" can find nothing at all while Google is returning a full page of exactly the businesses you wanted, one street past the line.

When that happens, the Actor:

  • saves nothing from outside the area β€” you asked for the area, not for its neighbours, and you are not charged for rows you told it to drop;
  • stops searching early instead of opening viewport after viewport over ground that keeps answering with the next town;
  • returns a single diagnostic row (recordType="run-diagnostic", isPlace=false), as every run does when it has no places to show;
  • tells you which towns your results were in, by name and count, in the run log and in OUTPUT.searchStats.nearbyCitiesWithResults.

That list is usually the answer: search those towns as Location(s) of their own, or turn geoStrictMatch off to keep nearby results marked insideSearchArea=false.

πŸ’³ Pricing And Cost Control

Check the Actor's Pricing tab on Apify for the current billing events and prices.

Typical billing events:

  • one base event for each saved Google Maps place;
  • optional contact-details event when website enrichment finds contacts or social profiles;
  • optional review event for each review attached to a place.

Cost control tips:

  • Start with maxCrawledPlacesPerSearch=50 for a test run.
  • Keep maxReviewsPerPlace=0 unless you need reviews.
  • Enable extractContactsFromWebsite only when you need website contacts.
  • Extra languages and extra zoom passes increase request volume.
  • Use Apify's maxTotalChargeUsd run limit for large automated batches.
  • If the charge limit is reached, the Actor stops gracefully and saves a partial run summary when possible.

βš™οΈ Configuration Reference

Input fieldWhat it doesRecommended use
searchStringsArrayGoogle Maps search terms.Add one business category or keyword per line.
locationQueriesOne or more independent search locations.Add one complete city, suburb, region, or country per line.
maxCrawledPlacesPerSearchMaximum saved places per search term per location or direct target.Use 50 for tests, 500+ for city-scale lists.
languagePrimary Google Maps language.Use the local language for local categories when needed.
additionalLanguagesExtra language passes.Useful in multilingual regions; increases requests.
extractContactsFromWebsiteVisits business websites and extracts public contacts and profiles.Enable for lead generation.
contactsFetchContactPageChecks lightweight contact/about/location pages when the homepage has no email.Keep enabled for better email yield without deep crawling.
contactsProxyFallbackRetries failed website/contact-page fetches through residential proxy after a direct attempt.Keep enabled for better contact coverage; disable only to minimize proxy bandwidth.
contactsFilterEmailsByWebsiteDomainKeeps emails related to the business website.Enabled by default for cleaner leads; turn off to keep every valid-looking public email found.
maxReviewsPerPlaceNumber of reviews to attach to each place.Use 0 for fastest runs; increase for review analysis.
reviewsSortRequested review order.newest is best-effort; Google can ignore it for some places.
skipClosedPlacesRemoves temporarily or permanently closed places.Enable for active-business lead lists.
geoStrictMatchUses stricter area matching.Enable for strict exports; read the strict-mode section above.
keepUnverifiedLocationsKeeps service-area businesses, which have no address at all, in a strict run.Enable for lead generation: they are real businesses with phone, website and category, and a strict run would otherwise drop them.

There is nothing to tune. The Actor works out how to cover an area, how deep to split it, at what zoom, and how many workers to run from the job you give it: a grid is laid over the search area at the closest zoom that still covers it, a map view is split wherever Google truncates its answer, and the workers scale with the queue. The settings that used to control this by hand (maxPlacesPerViewport, enableSubdivision, maxSubdivisionDepth, multiZoomDelta, zoom, concurrency, requestTimeoutSecs, minRequestIntervalMs) are gone β€” a wrong guess at any of them quietly cost coverage or money. Runs saved with those fields keep working.

reverseGeocodeMissingAddress is gone for good: it invented a street address for businesses that do not have one, by reverse-geocoding the placeholder coordinate Google gives them. Use keepUnverifiedLocations instead β€” it keeps those businesses with an honestly empty address.

Legacy post-fetch filters such as categoryFilterWords, placeMinimumStars, and searchMatching are no longer applied. They could remove valid rows only after Google Maps data had already been fetched. Filter the finished dataset by categories, totalScore, title, or searchString instead.

πŸ“€ Output Example

The default dataset contains one row per unique Google Maps place.

{
"searchString": "coffee shop",
"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",
"state": "New York",
"countryCode": "US",
"location": { "lat": 40.7602998, "lng": -73.9907758 },
"insideSearchArea": true,
"phone": "+1 917-265-8444",
"website": "https://www.birdandbranch.com/",
"emails": ["hello@example.com"],
"instagrams": ["https://www.instagram.com/example"],
"totalScore": 4.6,
"currentStatus": "Closed",
"placeId": "ChIJTVhsxFNYwokRXgPwYnY0vgI",
"url": "https://www.google.com/maps/search/?api=1&query=Bird+%26+Branch+Coffee+Roasters&query_place_id=ChIJTVhsxFNYwokRXgPwYnY0vgI",
"reviewsScrapedCount": 5,
"reviews": [
{
"author": "Alex Smith",
"text": "Great coffee and friendly service.",
"publishedAt": "3 months ago",
"publishedAtTimestamp": "2026-02-04T14:22:09Z"
}
],
"scrapedAt": "2026-05-29T10:30:00Z"
}

Website enrichment fields appear only when extractContactsFromWebsite=true. Review fields appear only when maxReviewsPerPlace is greater than 0.

🩺 Run Diagnostics

At the end of each run, the Actor writes an OUTPUT record to the default key-value store and prints the same important information in the log as Run diagnosis.

Useful fields:

  • status - SUCCEEDED, PARTIAL, or INPUT_NEEDS_ATTENTION.
  • inputWarning - explanation when input changes are needed.
  • diagnosticHints - concrete reasons for low or zero output.
  • totalPlaces - number of real Google Maps place rows.
  • diagnosticRows - number of non-place diagnostic rows.
  • datasetItems - total default dataset items.
  • searchStats - returned, filtered, out-of-area, and dropped place counters.
  • stoppedByChargeLimit - true when Apify's max total charge limit stopped the run.
  • datasetUrl - direct API link to the dataset.

If a run saves zero Google Maps places, the Actor may write one diagnostic dataset row with recordType="run-diagnostic", isDiagnostic=true, and isPlace=false. This row is not a place. It explains why the run produced no places and may be charged as one dataset result under pay-per-event pricing.

πŸ› οΈ Troubleshooting

πŸ” The Run Succeeded But Returned 0 Places

Open the OUTPUT record or the Apify log and look for Run diagnosis.

Common causes:

  • the location was misspelled or resolved to the wrong area;
  • the search term is too narrow for the selected location;
  • skipClosedPlaces=true removed closed places;
  • geoStrictMatch=true removed places outside the selected area;
  • direct URLs or Place IDs were not valid Google Maps place targets.

Try a broader search term, a clearer location such as City, Country, or a larger custom area.

πŸ“ Results Look Outside My Location

Google Maps can return nearby or ranked results outside the requested area. When the Actor can check the boundary, it marks those rows with insideSearchArea=false.

Options:

  • leave geoStrictMatch=false and filter by insideSearchArea;
  • enable geoStrictMatch=true for stricter exports;
  • use a clearer location such as Brooklyn, New York, United States;
  • use customGeolocation with a real Polygon or MultiPolygon.

πŸ’¬ Support

If a run does not return what you expected, check OUTPUT.inputWarning, OUTPUT.diagnosticHints, and the Apify log first. They usually explain whether the issue is location resolution, strict filtering, out-of-area results, unsupported direct URLs, or an empty Google response.

For bugs, feature requests, or confusing results, use the Actor's Issues tab on Apify and share the affected run when possible.

Version history is available in the Actor's Changelog on the Apify page.