Google Maps Leads Scraper
Pricing
from $0.30 / 1,000 place (core lead fields)s
Google Maps Leads Scraper
Fast, precise Google Maps lead lists: name, category, address, phone, website, rating, reviews, 7-day hours and GPS for any search term and location. About 1 minute per 50 places. $0.50 per 1,000 with full details.
Pricing
from $0.30 / 1,000 place (core lead fields)s
Rating
0.0
(0)
Developer
Deependra Singh
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a month ago
Last modified
Categories
Security
Limited permissionsShare
Extract business data from Google Maps at scale: name, category, address, phone, website, rating, review count, 7-day opening hours, GPS coordinates, amenities and description, for any search term in any city, region or country. Built for lead generation, local SEO, competitor tracking and market research in the US and Europe.
- Fast: 100 places with full details in about 2 minutes, 1,000 in about 24 minutes, measured on the Apify platform.
- Precise: data comes from Google's own structured place records, not screen text, so numbers and hours are exact. In a 1,000-place London test, 96% of places had a phone number, 85% a website, 99% full weekly hours and 87% a description; rating and review count were present on every place that has reviews.
- Priced at cost: $0.30 per 1,000 places for the lead list, $0.50 with full details. No platform usage fee on top. Apify's free plan covers about 10,000 places a month.
What can Google Maps Leads Scraper do?
Google's official Places API returns at most 60 results per search and charges per request. Google Maps itself shows about 20 results per map view. This Actor removes both limits: it splits any area into a grid of map cells, searches each one, removes duplicates and returns every business it finds, with the full record for each.
Typical uses:
- Lead generation: every dentist in Boston with phone and website, every restaurant in Berlin without a website, every gym in Madrid rated under 4 stars.
- Local SEO and agencies: monitor ratings, review counts and hours for client locations and their competitors.
- Market research and site selection: count competitors by neighborhood, compare ratings, check opening hours and price levels before opening a location.
- Data for AI and apps: a clean, typed dataset for RAG pipelines, chatbots, directories and enrichment workflows, reachable by API and MCP.
What data does it extract?
| Field | Description | Example |
|---|---|---|
title | Business name | Boston Smiles |
category, categories | Primary category and all categories | Dentist, [Dentist, Periodontist, ...] |
address | Full formatted address | 151 Merrimac St #100, Boston, MA 02114 |
street, city, postalCode, state, countryCode, neighborhood | Address components | 151 Merrimac St #100, Boston, 02114, Massachusetts, US |
phone, phoneInternational | Local and E.164 format | (617) 982-2233, +16179822233 |
website, domain | Website and bare domain | https://bostonsmilesdental.com/, bostonsmilesdental.com |
rating, reviewCount | Google rating and number of reviews | 4.8, 346 |
openingHours | Seven entries, one per weekday | Monday: 9 AM–6 PM |
openStatus | Status at scrape time | Open · Closes 6 PM |
permanentlyClosed, temporarilyClosed | Closure flags | false, false |
lat, lng, plusCode | Coordinates and Plus Code | 42.36418, -71.0631346, 9W7P+MP |
timezone | IANA time zone | America/New_York |
priceLevel | Price bracket when Google shows one | $$ |
description | Business description from the owner | "Boston Smiles Dental offers affordable..." |
amenities | Attributes Google lists | Wheelchair accessible entrance |
imageUrl, imagesCount | Cover photo and photo count | https://lh3.googleusercontent.com/..., 27 |
ownerName | Google Business Profile owner name (only when "Include owner name" is on; personal data for sole traders) | Boston Smiles |
placeId, cid, url | Google identifiers and Maps link | ChIJOW5Yj0Vx44kRkAYKYmDSae4 |
searchTerm, searchLocation, scrapedAt | Provenance | dentist, Boston, MA, 2026-10-06T08:40:00Z |
Thirty-seven fields in total. Every field is present on every row, with null where Google has no value, so spreadsheets and databases import cleanly.
How to scrape Google Maps
- Open the Actor and enter one or more search terms, exactly as you would type them into Google Maps:
dentist,coffee shop,plumber,hotel. - Enter a location: a city, region, postal code or address such as
Boston, MA,Berlin, Germany,Lyon,SW1A 1AA. - Choose how many places per search term. The form starts at
50; the API default is200.0collects everything in the area. - Optional filters: minimum rating, only places with or without a website, skip closed places. When a filter is on, the whole area is searched until the quota is met, so a "no website" run over a big city takes longer than a plain one.
- Click Start. Download the results as Excel, CSV, JSON or XML, or connect them to Google Sheets, Make, n8n, Zapier or your own code.
Choosing search terms
| Works well | Avoid | Why |
|---|---|---|
dentist | best dentist near me | Google Maps ignores filler words and may return unrelated places |
italian restaurant | restaurant italian pizza pasta | one clear category per term, add more terms as separate lines |
plumber and plumbing contractor as two terms | plumber OR plumbing | Maps has no boolean search, each term is a separate search |
Zahnarzt with language de | dentist with language de | match the search language to the location for full coverage |
Several search terms in one run share one grid and one deduplication set, so overlapping categories never produce duplicate rows.
Choosing a location
The location is geocoded to a bounding box and that box is searched as a grid. Specific locations give the best results: Brooklyn, NY or Munich, Germany work better than USA or Europe. For a very large area, split the run by city or district. A whole country at 0 places per term can run for hours.
Direct URLs and place IDs
Skip the search step by pasting Google Maps search URLs, place URLs or short links (maps.app.goo.gl/...) into "Google Maps URLs", or Google place IDs (starting with ChIJ) into "Place IDs". Place IDs are useful for refreshing an existing list: rating, review count, hours and open status come back current, and closed places are reported rather than dropped.
Full details or list only
- Full details (default on) opens Google's full place record for every result and adds the description, the full weekly opening hours, Plus Code and extra attributes. About 1 minute per 50 places.
- List only (switch "Open every place page for full details" off) is the fastest and cheapest mode. You still get name, category, address, phone, website, rating, review count, today's hours, coordinates and amenities.
Output example
One row from a real run for dentist in Boston, MA:
{"placeId": "ChIJOW5Yj0Vx44kRkAYKYmDSae4","cid": "0x89e371458f586e39:0xee69d260620a0690","title": "Boston Smiles","category": "Dentist","categories": ["Dentist", "Dental implants periodontist", "Pediatric dentist", "Periodontist", "Prosthodontist"],"address": "151 Merrimac St #100, Boston, MA 02114","street": "151 Merrimac St #100","city": "Boston","postalCode": "02114","state": "Massachusetts","countryCode": "US","neighborhood": "Bulfinch Triangle Historic District","lat": 42.36418,"lng": -71.0631346,"plusCode": "9W7P+MP Boston, Massachusetts","phone": "(617) 982-2233","phoneInternational": "+16179822233","website": "https://bostonsmilesdental.com/","domain": "bostonsmilesdental.com","rating": 4.8,"reviewCount": 346,"priceLevel": null,"openingHours": [{ "day": "Monday", "hours": "9 AM–6 PM" },{ "day": "Tuesday", "hours": "9 AM–5 PM" },{ "day": "Wednesday", "hours": "7 AM–7 PM" },{ "day": "Thursday", "hours": "9 AM–3:30 PM" },{ "day": "Friday", "hours": "7 AM–3:30 PM" },{ "day": "Saturday", "hours": "8:30 AM–2:30 PM" },{ "day": "Sunday", "hours": "Closed" }],"openStatus": "Open · Closes 6 PM","permanentlyClosed": false,"temporarilyClosed": false,"timezone": "America/New_York","description": "Boston Smiles Dental offers affordable, professional dentistry with cutting edge technology in a relaxed setting to patients of all ages. Located in Boston's West End. Accepting most insurances.","amenities": ["Wheelchair accessible entrance", "Wheelchair accessible restroom"],"imageUrl": "https://lh3.googleusercontent.com/grass-cs/ACvplmMpQ9Pyw6cLherVcaST8GStsvlcLtwaqCnsEH4I17sBMRgM0Ub7pQeBdJCFtTrzLi5HKQMdrIzYWx7qI9bdbc-EjLDJ1fwCNUf2EJrNZBspzz1P2FC8qzh98wP8sUcs3UVqGPTU=w800-h600-k-no","imagesCount": 27,"ownerName": null,"url": "https://www.google.com/maps/place/Boston+Smiles/data=!4m7!3m6!1s0x89e371458f586e39:0xee69d260620a0690!8m2!3d42.36418!4d-71.0631346!16s%2Fg%2F11j8gm5pk7!19sChIJOW5Yj0Vx44kRkAYKYmDSae4?hl=en","searchTerm": "dentist","searchLocation": "Boston, MA","detailsScraped": true,"scrapedAt": "2026-10-06T08:40:00.000Z"}
The dataset has two built-in views: Leads, a spreadsheet-friendly selection of the contact columns, and All fields.
Pricing
Pay-per-event. You pay for what the Actor produces, and nothing for platform usage.
| Event | Price | When it is charged |
|---|---|---|
| Actor start | $0.002 | once per run |
| Place | $0.0003 ($0.30 per 1,000) | for every place in the dataset |
| Place details | $0.0002 ($0.20 per 1,000) | for every place, only when full details are on |
| Run | Cost |
|---|---|
| 1,000 businesses, list only | $0.30 |
| 1,000 businesses with full details | $0.50 |
| 10,000 businesses with full details | $5.00 |
Set Maximum total charge on the run to cap spending. The Actor stops cleanly when the cap is reached and keeps everything collected so far. Comparable Google Maps scrapers on the Store charge $1.50 to $7 per 1,000 places, often with usage fees added.
Input parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
searchTerms | array of strings | required | What to search for, one term per line |
locationQuery | string | required with search terms | City, region, postal code or address |
maxPlacesPerSearch | integer | 200 | Stop each term after this many unique places. 0 for all |
language | select | en | Language for categories, hours and addresses. 30 languages |
scrapeDetails | boolean | true | Open the full place record for every result |
minRating | number | 0 | Keep places rated at or above this value |
onlyWithWebsite | boolean | false | Keep only places with a website |
onlyWithoutWebsite | boolean | false | Keep only places without a website |
skipClosedPlaces | boolean | true | Drop permanently and temporarily closed places (search runs) |
strictLocation | boolean | true | Drop places outside the location's municipal boundary |
includeOwnerName | boolean | false | Add the profile owner name (personal data, opt-in) |
excludePlaceIds | array of strings | Place IDs from earlier runs to skip, for repeat runs | |
startUrls | array of strings | Google Maps search or place URLs to scrape directly | |
placeIds | array of strings | Google place IDs to fetch directly | |
proxyConfiguration | object | Apify datacenter proxy | Switch to residential only if a very large run reports blocks |
maxConcurrency | integer | 8 | Browser pages open at once |
Full input example:
{"searchTerms": ["dentist", "orthodontist"],"locationQuery": "Boston, MA","maxPlacesPerSearch": 500,"language": "en","scrapeDetails": true,"minRating": 4,"onlyWithWebsite": false,"onlyWithoutWebsite": false,"skipClosedPlaces": true,"strictLocation": true,"proxyConfiguration": { "useApifyProxy": true },"maxConcurrency": 8}
Use it from code
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });const run = await client.actor('superxcoder/google-maps-leads-scraper').call({searchTerms: ['dentist'],locationQuery: 'Boston, MA',maxPlacesPerSearch: 200,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.length, 'places');
Python
from apify_client import ApifyClientclient = ApifyClient("YOUR_APIFY_TOKEN")run = client.actor("superxcoder/google-maps-leads-scraper").call(run_input={"searchTerms": ["dentist"],"locationQuery": "Boston, MA","maxPlacesPerSearch": 200,})items = client.dataset(run["defaultDatasetId"]).list_items().itemsprint(len(items), "places")
Command line
$apify call superxcoder/google-maps-leads-scraper --input '{"searchTerms":["dentist"],"locationQuery":"Boston, MA"}'
AI agents and MCP: the Actor uses pay-per-event with limited permissions, so it is available through the Apify MCP server to Claude, ChatGPT, Cursor and other agents. Ask your agent for "100 dentists in Boston with phone numbers" and it can call this Actor directly.
Integrations
Every run writes to a dataset with a stable URL, so results flow into Google Sheets, Make, n8n, Zapier, Airbyte, Slack, LangChain and LlamaIndex through Apify's integrations page, or into any system through the REST API. Schedule runs in the Console to refresh a list weekly, and add a webhook to be notified when a run finishes.
Frequently asked questions
How many results can I get for one search? As many as exist in the area. Google Maps shows about 20 results per map view; the Actor splits the area into smaller map cells until it has your quota or the area is exhausted, then removes duplicates.
How is this different from the Google Places API? The official API returns at most 60 results per query, charges per request, and does not return the full weekly hours or description for free. This Actor returns everything a Maps visitor can see, for whole cities, at a flat price per place.
How fast is it? About 50 places per minute with full details on the default settings, faster in list mode. A 1,000-place city-wide run takes about 24 minutes. A run that approaches its time limit stops cleanly and keeps its results.
Does it work outside the US? Yes. Tested in the US, the UK and Germany. Set the language to match the country for native categories and hours; closed-place detection and empty-result detection work in all 30 languages offered. EU consent screens are handled automatically.
How is the location resolved?
The location text is turned into real municipal boundaries from OpenStreetMap data, then searched as a grid from the town centre outwards. Native and English names both work (Roma or Rome, Wien or Vienna, 東京 or Tokyo). For names that exist in several countries add the region or country, as in Paris, TX, Cambridge, UK or Springfield, IL; without a hint the best-known place wins. If the boundary lookup is unavailable the Actor falls back to Google Maps' own view of the place and says so in the log; in that case the "inside the location" check uses a wider box. A location that cannot be found fails the run immediately and costs nothing.
What happens if part of a run fails? Every map cell is retried three times with a fresh browser session. Cells that still fail are counted and reported in the run's status message and final log, so you know whether the list is complete. Re-run with "Exclude place IDs" set to the first run's results to fetch only what is missing.
Can I get reviews, emails or social media links? Not in this version. Review text, website email and social profile enrichment are planned as optional paid events. If you need them now, open an Issue and say which one matters most.
Why are some fields null?
Google does not list a phone, website, price level or description for every business. The Actor returns null rather than guessing.
What proxy should I use? The default Apify datacenter proxy is included in your plan and handled 100% of requests in testing. If a very large run reports blocked requests, switch to residential in the proxy setting.
Why do I get places from the next town over with other scrapers, and not here? Google pads sparse map views with businesses from further away. Every place here is checked against the boundary of the location you asked for, and anything outside is dropped. The run log reports how many were removed. Turn "Only places inside the location" off if you want the wider set.
The boundary is the municipal polygon from OpenStreetMap (with about 100 m of slack at the edge), so "Cambridge, MA" does not return Somerville or Boston addresses even though they sit inside Cambridge's bounding rectangle. When no polygon exists for a location (a street address, a neighbourhood without an official boundary, or a public boundary service being down) the check falls back to the bounding rectangle with a 10% margin, and the log says so.
Can a repeat run return only new businesses?
Yes. Paste the placeId column from your earlier export into "Exclude place IDs". Those places are skipped and not charged, so weekly runs only cost you the new ones.
How do I refresh an existing list?
Paste the placeId values from your earlier export into "Place IDs". Each place comes back with current rating, review count, hours and open status.
Is it legal to scrape Google Maps? The Actor collects only information businesses publish on Google Maps and that any visitor can see. It does not collect reviewer names, and the profile owner name is off by default because it can identify a sole trader. You are responsible for using the data in line with the laws that apply to you, including GDPR when contacting businesses in the EU. See Apify's guidance on the legality of web scraping for more.
I found a missing field or a broken run. What now? Open an Issue on this Actor's Issues tab with the input you used. Issues are answered within one business day.