Google Maps Scraper By Radius & GeoJSON Territory avatar

Google Maps Scraper By Radius & GeoJSON Territory

Pricing

from $2.99 / 1,000 results

Go to Apify Store
Google Maps Scraper By Radius & GeoJSON Territory

Google Maps Scraper By Radius & GeoJSON Territory

Automate Google Maps scraping to power your internal tools. Whether for targeting, analysis, or reporting, this actor gives you clean, reliable business data with no API limitations or UI restrictions.

Pricing

from $2.99 / 1,000 results

Rating

0.0

(0)

Developer

SimpleAPI

SimpleAPI

Maintained by Community

Actor stats

1

Bookmarked

12

Total users

2

Monthly active users

7 days ago

Last modified

Share

Google Maps Scraper — Radius, GeoJSON Territory and NAP Data

Google Maps Scraper By Radius & GeoJSON Territory extracts business listings — name, address, phone, website, rating, review count, hours and lat/long — restricted to an exact zone you draw yourself: a center coordinate plus a mile radius, a GeoJSON polygon or multipolygon sales territory, a single postal/ZIP code, or classic city/region names. Every place is returned with distance_miles from your center and a within_territory flag. Built for local SEO agencies, franchise site-selection teams, and sales territory planners who need places from one specific shape, not a fuzzy place name. Results stream into the dataset live as each in-zone place is found.

What is Google Maps Scraper By Radius & GeoJSON Territory?

It is an Apify Actor that scrapes public Google Maps place data for one or more keywords and returns it filtered to a precise geographic zone instead of Google's own fuzzy "near this city" matching. No Google account or Maps API key is required — it reads the same public search results any visitor sees.

  • 🎯 Five ways to define where to search: center coordinate + radius, GeoJSON Point/Polygon/MultiPolygon, postal code, named locations, or a bulk list of Google Maps search URLs
  • 📞 Core identifying and contact fields: name, address components, phone, website, coordinates
  • ⭐ Decision-driving data: average rating and total review count
  • 🗺️ Every place annotated with distance_miles from your center and a within_territory in/out flag
  • 🔎 Multiple keywords multiply the search across every geo target you configure
  • 📤 Structured JSON dataset, exportable as JSON, CSV, Excel, XML or HTML through the Apify platform

What data can I extract with Google Maps Scraper By Radius & GeoJSON Territory?

Every place is one dataset row built from the same fields, run after run.

FieldExample ValueUse Case
name"Kim's Island"Business identity
website"http://kimsislandsi.com"Outreach / lead qualification
avg_rating4.5Quality threshold filtering
total_reviews91Demand / popularity signal
distance_miles3.42Sort or cap by distance from your center
within_territorytrueKeep only in-zone results
street_address"175 Main St"Mailing / site-visit address
city"Staten Island"Geographic grouping
state"New York"Geographic grouping
zip"10307"Postal-level segmentation
country_code"US"Country filtering
full_address"175 Main St Staten Island New York 10307 US"Single-line address for exports
tags["Chinese restaurant"]Category filtering
notes"Cozy neighborhood spot with counter service."Extra descriptive context, when Google shows one
place_id"ChIJJQz5EZzKw4kRCZ95UajbyGw"Deduplication key / stable record ID
phone"(718) 356-5168"Outreach
lat40.5107736Mapping, distance math
long-74.2482624Mapping, distance math
hours[{"day": "Monday", "hours": "Closed", ...}]Availability / best-time-to-call
successtrueRow passed parsing and territory filtering

The row above is the full output — this Actor's dataset view is not a trimmed subset; all 20 keys the Actor writes are the same 20 keys shown by default in the table view.

Two different "missing data" placeholders are used, and they don't mix: street_address, city, state, zip, country_code, website and full_address fall back to an empty string "" when Google's payload doesn't have them. name, avg_rating, total_reviews, tags, notes, place_id, phone, lat and long fall back to null instead. A place with no listed phone number returns "phone": null, not a missing key — but a place with no listed website returns "website": "". Check for both when filtering incomplete rows. Also note the longitude key is long, not lng or lon.

Ratings and review signals

avg_rating and total_reviews are read directly off the same ratings block Google Maps renders on the search card — no extra input flag needed, they're returned on every row automatically. Both fall back to null when a place has no rating block at all (a brand-new or unrated listing). Use them together to threshold a shortlist — for example, keep only places with avg_rating >= 4.0 and total_reviews >= 20 to filter out unestablished or unreliable listings before an outreach list goes to sales.

Location and targeting fields

lat, long, distance_miles and within_territory are what make this Actor's results zone-precise rather than city-fuzzy: distance_miles is the haversine distance from your active center (the coordinate you gave, the GeoJSON shape's centroid, or the geocoded center for a postal code, named location, or URL), and within_territory is true/false only when a radius or GeoJSON boundary is actually in effect. city, state, zip and country_code let you segment results by administrative area once they're in your dataset.

Why not build this yourself?

Google Maps Platform sells an official Places API, but using it means opening a separate Google Cloud project, enabling billing on it, generating your own API key, and tracking usage-based charges — a different signup and cost-tracking flow from the Apify run you already know how to trigger. Google Maps Scraper By Radius & GeoJSON Territory runs on Apify: the same console, the same pay-per-event billing as every other Actor in this account, no Google Cloud project to provision.

The harder cost of building this yourself is the geometry, not the scraping. A single Google Maps search view only surfaces a limited slice of results before it needs a new map tile, so covering a real territory means tiling your target zone into a grid and firing one request per cell — this Actor sizes that grid automatically (from a 6×6 sweep up to 12×12, depending on how many results are still needed) and merges the results, deduping by place_id as it goes. On top of that: geocoding city and postal names to coordinates, haversine distance math for the radius mode, and ray-casting point-in-polygon tests for GeoJSON territories — all of it already built and running per keyword, per zone, in a single input.

What can you do with Google Maps place data from a specific zone?

  • 🏢 A local SEO agency onboarding a new client pulls every coffee shops and dentists listing inside the client's actual service radius, sorts by avg_rating and total_reviews, and hands over a competitor map scoped to the exact area the client serves — not the whole metro.
  • 📍 A franchise or site-selection team draws the real trade-area polygon for a proposed location in customGeolocation, then counts within_territory: true places per category to gauge how saturated that specific footprint already is before signing a lease.
  • 📊 A market researcher sweeps the same GeoJSON territory monthly and diffs total_reviews and avg_rating per place_id to track how a category's density and reputation shift inside one defined boundary over time.
  • 🤖 An AI agent pipeline calls this Actor as a tool with a postalCode and a category keyword, then reasons over name, full_address, phone and distance_miles to answer "which of these are actually inside my client's five-mile zone" without a human drawing the map by hand.

⬇️ Input

Only keywords is required by the schema — but a run with keywords and none of coordinates, customGeolocation, postalCode, locations, or urls set has no zone to search and returns zero rows. Pair keywords with at least one of the five targeting inputs below.

ParameterRequiredTypeDescriptionExample Value
keywordsYesarrayBusiness types or search terms to find inside your target zone — e.g. coffee shops, dentists, car dealerships. Add several to multiply the searches.["coffee shops", "cafes"]
coordinatesNostringLatitude,longitude pair used as the search center instead of a named location. Pair with radius below; places farther away are dropped. Leave blank to use locations/GeoJSON/postal instead."29.7604,-95.3698"
radiusNointegerHow far around the center coordinates (or a GeoJSON Point) to search, in miles. Places farther than this are dropped. Minimum 1, maximum 100, default 5. Used only when coordinates or a GeoJSON Point are set.5
customGeolocationNoobjectGeoJSON geometry — Point, Polygon, or MultiPolygon (Feature/FeatureCollection also accepted) — defining the exact search area. Every place is point-in-polygon tested; only places inside the shape are kept. Overrides coordinates and locations when set. GeoJSON coordinate order is [longitude, latitude].{"type":"Polygon","coordinates":[[[-95.40,29.74],[-95.34,29.74],[-95.34,29.78],[-95.40,29.78],[-95.40,29.74]]]}
postalCodeNostringSingle postal/ZIP code area to scrape — combine with a country or city in locations for unambiguous targeting (one code per run). Leave blank to skip."77002"
locationsNoarrayCity, region, or neighborhood names to sweep. Also used as the country/city hint for postalCode above. Skipped automatically when customGeolocation is active.["New York", "Texas", "Downtown Chicago"]
urlsNoarrayBulk-friendly list of Google Maps search links (with @lat,lng or /search/ query).["https://www.google.com/maps/search/coffee/@29.76,-95.37,13z"]
maxResultsNointegerTotal unique places (deduped by place_id) across all geo jobs, locations, keywords, and URLs combined. Minimum 1, maximum 10000, default 20.200
proxyConfigurationNoobjectApify Proxy settings. Off by default for simple runs. On a block, the Actor auto-escalates direct → datacenter → residential (sticky).{"useApifyProxy": false}

Common pitfalls: GeoJSON longitude/latitude order is reversed from the coordinates field's lat,lng order — swap them and your shape lands in the wrong place with no error thrown. postalCode takes exactly one code per run, not a list. And radius silently does nothing unless coordinates is set or customGeolocation is a bare GeoJSON Point — it has no effect on a Polygon/MultiPolygon territory, a postal code lookup, or a named-location search.

Example input

{
"keywords": ["coffee shops", "cafes"],
"coordinates": "29.7604,-95.3698",
"radius": 10,
"maxResults": 200,
"proxyConfiguration": { "useApifyProxy": false }
}

⬆️ Output

Typed, normalized JSON with a consistent 20-key schema, written to the dataset live as each in-zone place is found. Export as JSON, CSV, Excel, XML or HTML, or read the dataset through the Apify API.

Example output

{
"street_address": "175 Main St",
"city": "Staten Island",
"zip": "10307",
"state": "New York",
"country_code": "US",
"full_address": "175 Main St Staten Island New York 10307 US",
"website": "http://kimsislandsi.com",
"avg_rating": 4.5,
"total_reviews": 91,
"name": "Kim's Island",
"tags": ["Chinese restaurant"],
"notes": "Cozy neighborhood spot with counter service.",
"place_id": "ChIJJQz5EZzKw4kRCZ95UajbyGw",
"phone": "(718) 356-5168",
"lat": 40.5107736,
"long": -74.2482624,
"hours": [
{ "day": "Monday", "hours": "Closed", "open24Hour": null, "close24Hour": null },
{ "day": "Tuesday", "hours": "11 AM to 9:30 PM", "open24Hour": [11, 0], "close24Hour": [21, 30] }
],
"distance_miles": 3.42,
"within_territory": true,
"success": true
}

success is present on every row and reflects that the place cleared parsing and territory filtering — a place that fails those checks is never pushed at all, so you will not see success: false in the dataset; a missing keyword+zone combination simply contributes zero rows instead.

How do you filter and target specific places?

This is the core mechanic of this Actor — five distinct ways to define where "here" means, each solving a different targeting problem:

  1. coordinates + radius — a plain lat,lng center and a mile radius. Simplest mode for a circular sweep around one point; radius (miles) only applies here or to a GeoJSON Point.
  2. customGeolocation (GeoJSON Point/Polygon/MultiPolygon/Feature/FeatureCollection) — the precision mode. Every scraped place is point-in-polygon tested, and only places inside the shape keep within_territory: true. When it parses successfully, it overrides coordinates and locations — both are skipped for that run. It does not override postalCode or urls, which still run as their own independent geo jobs alongside it. If the GeoJSON fails to parse, it's ignored with a warning and the run falls back to coordinates/locations normally.
  3. postalCode — one ZIP/postal code per run, geocoded to its own area. Pair it with a country or city in locations to disambiguate codes that exist in more than one country.
  4. locations — the classic named-area mode: cities, states, neighborhoods. Automatically skipped when a customGeolocation territory is active.
  5. urls — bulk Google Maps search links, each resolved to its own coordinates or geocoded query.

maxResults is the one volume control, and it is a total across every job combined — not per keyword, not per location, not per URL. Set it once; the Actor stops as soon as that many unique places (by place_id) have been collected across all five modes together.

{ "keywords": ["dentists"], "customGeolocation": {"type": "Polygon", "coordinates": [[[-95.40, 29.74], [-95.34, 29.74], [-95.34, 29.78], [-95.40, 29.78], [-95.40, 29.74]]]}, "maxResults": 500 }
{ "keywords": ["car dealerships"], "postalCode": "77002", "locations": ["USA"], "maxResults": 100 }
{ "keywords": ["coffee shops"], "locations": ["Downtown Chicago"], "maxResults": 150 }
Scraper NameWhat it extracts
Apartments.com Scraper & Floor Plan UnitsRental listings with floor plans and unit-level availability
Booking.com Scraper With Property Contact LeadsAccommodation listings with property contact details
Realtor.com Agents + Recent Sold ListingsReal-estate agent profiles paired with recent sold-listing data

How to extract Google Maps place data programmatically

Google Maps Scraper By Radius & GeoJSON Territory is a standard Apify Actor call — one run, one input payload, structured JSON back through the Apify API.

Python example

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<YOUR_USERNAME>/google-maps-scraper-by-radius-geojson-territory").call(run_input={
"keywords": ["coffee shops"],
"coordinates": "29.7604,-95.3698",
"radius": 5,
"maxResults": 200,
})
for place in client.dataset(run["defaultDatasetId"]).iterate_items():
print(place["name"], place["distance_miles"], place["within_territory"])

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.

Export to spreadsheets or CRM

Export the dataset as CSV and map name to a Business Name column, full_address (or the individual street_address/city/state/zip fields) to Address, phone to Phone, and website to Website when importing into a CRM or Google Sheets.

Yes. Google Maps place listings are public business records — names, addresses, phone numbers, hours and ratings that Google displays to every anonymous visitor so the business can be found. This Actor only returns what is already visible on the public search results page.

Because the output is business and product data — commercial listings, not individual consumer profiles — the regime that applies is Google's Terms of Service and general database-rights and unfair-competition rules around systematic reuse of a compiled dataset, not GDPR/CCPA personal-data obligations. Consult legal counsel for commercial applications involving bulk storage of personal data (for example, if a place's notes field happens to surface an individual's name).

❓ Frequently asked questions

What happens if a keyword and target zone combination returns zero places?

That combination simply contributes zero rows — no error, no placeholder record. The Actor logs it and moves on to the next keyword or geo job in the run. If every combination in a run comes back empty, the final dataset has zero rows and zero charged events; nothing uncharged is written to account for the miss.

Can I get ratings and review counts along with the main place data?

Yes, automatically — no separate flag to enable. avg_rating and total_reviews are returned on every row alongside the address and contact fields, falling back to null on places with no rating block.

How accurate is the phone, address and hours data?

It reflects exactly what Google Maps shows for that place at the moment of the run. Accuracy depends on whether the business keeps its own Google Business Profile current — the standard downstream step is to spot-check a sample before using the phone or address fields for outreach at scale.

How many places can I get per run?

Up to maxResults, which accepts a minimum of 1 and a maximum of 10000, default 20. That figure is a total of unique places (deduped by place_id) across every keyword, geo job, location and URL combined in the run — not a per-job or per-keyword limit.

Which targeting mode wins if I set coordinates, a GeoJSON territory, and a postal code together?

customGeolocation, once it parses into a valid Point, Polygon, or MultiPolygon, overrides coordinates and locations — both are skipped. postalCode and urls are independent of that override and still run as their own geo jobs in the same run.

Do I need to set a location field, or can I search by keywords alone?

keywords is the only field the schema requires, but a run with keywords and no coordinates, customGeolocation, postalCode, locations, or urls has no zone to search against and returns zero places. Set at least one targeting input alongside your keywords.

Does Google Maps Scraper By Radius & GeoJSON Territory work with Claude, ChatGPT and AI agent frameworks?

Yes. It is callable as a standard HTTP endpoint through the Apify API, so any agent framework that can make a request — LangChain, CrewAI, n8n, a custom tool definition — can invoke it and get typed JSON back.

How does this Actor compare to other Google Maps scrapers?

Checked on the Apify Store on 2026-07-26: compass/crawler-google-places (Google Maps Scraper) and its siblings compass/google-maps-extractor and lukaskrivka/google-maps-with-contact-details all document a "custom search area" GeoJSON mode (Polygon, MultiPolygon, and a Point with a radiusKm property), but none of their published READMEs describe a standalone lat,lng-plus-mile-radius input outside of GeoJSON, and none document annotating every output row with a distance-from-center or in-boundary flag the way distance_miles and within_territory do here. Those three Actors document a much larger field set overall (reviews, images, popular-times histograms, contact and social enrichment add-ons), which this Actor does not return — its focus is precise zone targeting on core NAP data, not full place-detail enrichment.

Can I use this Actor without a Google Cloud API key or developer account?

Yes. You only need an Apify account to run it. There is no Google Cloud project, no billing account, and no Google Maps Platform API key to set up.

Conclusion

Google Maps Scraper By Radius & GeoJSON Territory turns Google Maps into a shape-bound dataset: draw a radius, a sales-territory polygon, a ZIP code, a city name, or a bookmarked search URL, and get back typed JSON rows tagged with distance and in-zone status for every business inside it. It is built for anyone who needs places from one specific area rather than a whole fuzzy city — local SEO agencies, franchise planners, and market researchers alike. Open it on the Apify Console, set your keywords and one targeting field, and start the run.