Google Maps Business Scraper
Pricing
from $4.00 / 1,000 business results
Google Maps Business Scraper
Collect public Google Maps business listings for lead generation and local market research. Get names, categories, structured addresses, phones, websites, ratings, coordinates, CIDs, source queries, and ranks. Supports JSON, CSV, Excel, API, and scheduled runs.
Pricing
from $4.00 / 1,000 business results
Rating
0.0
(0)
Developer
Johnn Mottin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Google Maps Business Scraper
Collect public Google Maps business profiles for lead generation, local marketresearch, competitor comparison, and CRM preparation.
This Actor uses Python, Playwright, Chrome, and the official Apify proxyconfiguration. It does not use the Google Places API, a Google account,authenticated cookies, or an API key.
What this Actor does
For every search query or supported public Google Maps search URL, the Actor:
opens the public Google Maps search page;
handles a public consent screen when one appears;
discovers unique /maps/place/ links from the results page;
preserves the position of each business in the search results;
opens each public business detail page;
extracts evidenced public business information;
applies per-query and global limits;
removes duplicates within each search context;
records quality checks, warnings, retries, and stop reasons in STATS;
writes business records to the default dataset.
The Actor can continue when Google Maps exposes valid place links even when asemantic results feed is not present.
Use cases
Lead generation — build structured lists of local businesses.
Local market research — compare companies operating in a city or region.
Competitor research — inspect categories, ratings, websites, phones, and locations.
CRM preparation — export structured business records to JSON, CSV, Excel, or API.
Location datasets — collect coordinates, structured addresses, Maps URLs, and CIDs.
Input
Provide at least one non-empty searchQueries item or one valid searchUrlsitem.
Field
Type
Default
Rules
searchQueries
string array
[]
Blank and case-insensitive duplicate queries are removed.
searchUrls
request-list array
[]
Accepts URL strings and { "url": "..." }. Only supported public google.com/maps/search routes are accepted.
maxPlacesPerQuery
integer
20
Minimum 1, maximum 200.
maxTotalPlaces
integer
100
Minimum 1, maximum 2,000.
language
string
en
Supported values: en, pt-BR, es, de, fr, and it.
proxyCountryCode
string
US
Exactly two letters, normalized to uppercase.
includeOpeningHours
boolean
true
When false, openingHours is returned as null.
includeContactDetails
boolean
true
When false, phone and website fields are returned as null.
debug
boolean
false
Saves screenshots and HTML for successful pages. Error and block evidence may be saved independently.
Small input example
{ "searchQueries": [ "dentists in Albany, NY" ], "searchUrls": [], "maxPlacesPerQuery": 5, "maxTotalPlaces": 5, "language": "en", "proxyCountryCode": "US", "includeOpeningHours": true, "includeContactDetails": true, "debug": false }
Queries are converted to public search URLs such as:
https://www.google.com/maps/search/?api=1&query=<QUERY_ENCODED>
Invalid input produces a controlled INPUT_ERROR and a failed run.
Invalid search URLs are counted and ignored when another valid query or URLexists. The run fails with ALL_QUERIES_FAILED when no search context completessuccessfully.
Dataset output
The Actor produces one dataset record per collected business.
Missing scalar values are returned as null. categories is always an array.openingHours is a normalized object when successfully extracted, otherwisenull.
Visible text is Unicode-normalized, leading interface glyphs are removed, andknown marketing parameters are removed from business website URLs.
Structured address components are extracted only when supported by evidencefrom the page or by a conservative address parser. The search query is neverused to invent a business address.
Real output example
The following record came from a successful controlled run fordentists in Albany, NY:
{ "name": "Dental Wellness of Albany", "primaryCategory": "Dentist", "categories": [ "Dentist" ], "address": "651 Delaware Ave, Albany, NY 12209", "neighborhood": null, "city": "Albany", "state": "NY", "postalCode": "12209", "country": "United States", "countryCode": "US", "phone": "+15184272447", "phoneUnformatted": "+15184272447", "website": "https://www.651dental.com/", "rating": 4.9, "reviewCount": null, "priceLevel": null, "businessStatus": null, "openingHours": null, "latitude": 42.6350596, "longitude": -73.7950078, "placeId": null, "cid": "12250295333788525579", "googleMapsUrl": "https://www.google.com/maps/place/Dental+Wellness+of+Albany/data=!4m7!3m6!1s0x89de0a7e2759f93f:0xaa01cab38417240b!8m2!3d42.6350596!4d-73.7950078!16s%2Fg%2F1tklrkb5!19sChIJP_lZJ34K3okRCyQXhLPKAao", "searchQuery": "dentists in Albany, NY", "searchUrl": "https://www.google.com/maps/search/?api=1&query=dentists+in+Albany%2C+NY", "rank": 1, "language": "en", "scrapedAt": "2026-07-25T19:36:16.370587Z" }
Output fields
Field
Description
name
Business name.
primaryCategory
Main category shown for the business.
categories
Available business categories.
address
Visible full address after text cleanup.
neighborhood
Neighborhood when evidenced, otherwise null.
city
City when evidenced or conservatively parsed.
state
State or region when evidenced or conservatively parsed.
postalCode
Postal or ZIP code when evidenced or conservatively parsed.
country
Country name when evidenced.
countryCode
Two-letter country code when evidenced.
phone
Normalized phone number when available.
phoneUnformatted
Phone representation retained by the extractor.
website
Business website with known tracking parameters removed.
rating
Rating shown by Google Maps.
reviewCount
Review or rating count when reliably identified; otherwise null.
priceLevel
Price level when present, otherwise null.
businessStatus
Public business status when present, otherwise null.
openingHours
Structured opening hours when reliably available, otherwise null.
latitude
Latitude parsed from public Maps data.
longitude
Longitude parsed from public Maps data.
placeId
Google place identifier when explicitly evidenced, otherwise null.
cid
Decimal Google CID extracted from a supported public Maps URL pattern.
googleMapsUrl
Public Google Maps business URL.
searchQuery
Original search query, when query input was used.
searchUrl
Search URL used for the record.
rank
Position discovered within the search context.
language
Requested interface language.
scrapedAt
UTC timestamp of extraction.
Dataset views
The dataset includes three views:
Leads — business, category, contact, rating, source, and rank.
Map data — structured address, coordinates, identifiers, and Maps URL.
Full details — every documented public output field.
Deduplication and limits
Deduplication is scoped to one search context.
The same business may be retained in different searches because its searchcontext and rank can be useful.
Identity evidence is checked in this order:
placeId;
cid;
canonical Google Maps URL;
normalized name + address.
maxPlacesPerQuery limits the results returned for each query.
maxTotalPlaces is a hard run-wide dataset limit.
Search collection can also stop when:
the requested per-query limit is reached;
the global limit is reached;
the results stop changing;
an end marker appears;
the scroll safety limit is reached.
Stop reasons are recorded in STATS.capReasons.
Reliability and block handling
Google Maps is a dynamic web application and its public interface can change.
The Actor uses:
bounded navigation and extraction timeouts;
fresh browser contexts and proxy sessions for retries;
block and captcha detection;
controlled retry limits;
bounded screenshot and HTML evidence;
progress logs for search and detail stages;
partial and final STATS records.
Known blocking or suspicious signals include:
captcha or reCAPTCHA pages;
unusual-traffic messages;
Google /sorry/ routes;
account or login redirects;
a search page with no feed, no place links, and no legitimate no-results marker;
a detail page where no business identity can be established.
Normal pages are not saved unless debug is enabled.
The Actor never fabricates missing values.
A run that ends with zero collected places fails explicitly with EMPTY_RESULTS unless every search context reported a legitimate public no-results page. The Actor never reports success with a silently empty dataset.
STATS
The final STATS key-value record includes run totals, missing-field counters,quality alerts, stop reasons, and a summary for each search context.
Real STATS example
This example came from the same successful five-result run:
{ "inputQueries": 1, "validSearchUrls": 0, "invalidSearchUrls": 0, "queriesSucceeded": 1, "queriesFailed": 0, "placesDiscovered": 5, "placesCollected": 5, "duplicatesSkipped": 0, "detailPagesOpened": 5, "blockedPages": 0, "consentPages": 0, "retries": 0, "missingNameCount": 0, "missingAddressCount": 0, "missingPhoneCount": 0, "missingWebsiteCount": 0, "missingCoordinatesCount": 0, "missingReviewCountCount": 5, "missingStructuredAddressCount": 0, "missingCityCount": 0, "missingStateCount": 0, "missingPostalCodeCount": 0, "missingCountryCount": 0, "missingCidCount": 0, "qualityAlert": true, "warnings": [ "Review count quality alert: more than 20% of records have a rating but no reviewCount." ], "capReasons": [ "per_query_limit" ], "querySummary": [ { "key": "query-1", "searchQuery": "dentists in Albany, NY", "searchUrl": "https://www.google.com/maps/search/?api=1&query=dentists+in+Albany%2C+NY", "status": "succeeded", "placesDiscovered": 5, "placesCollected": 5, "reason": "per_query_limit", "attempt": null, "stage": "complete", "elapsedSeconds": 34.494, "lastError": null } ] }
Quality alerts are raised when:
more than 5% of records lack name or googleMapsUrl;
more than 30% have an address but insufficient structured components;
more than 20% have a rating but no reviewCount;
more than 20% contain a detectable CID pattern but no extracted cid.
A quality alert does not automatically mean the run failed. It indicates thatthe returned dataset should be reviewed for the fields named in warnings.
Known limitations
Review count is best-effort. Google Maps can expose ratings without areliably identifiable review count. In that case, reviewCount is null andthe condition is reported in STATS.
Opening hours are optional. They may be unavailable or not reliablyexposed in a supported structure.
Place ID is optional. cid may be available even when placeId is not.
Localized interfaces vary. Labels and number formats can differ bylanguage and country.
Some businesses omit fields. Phone, website, address components,business status, price level, and coordinates are not guaranteed.
Google Maps changes over time. Public page structure, ARIA labels, andembedded data can change.
Websites
Known marketing parameters are removed from collected website URLs:
utm_source utm_medium utm_campaign utm_term utm_content gclid fbclid gbraid wbraid
Unknown query parameters are preserved because they may be required for thewebsite to function.
Data intentionally not collected
The Actor does not collect:
email addresses;
review text;
reviewer profiles;
authenticated or private data;
data from logged-in Google accounts.
It does not use the Google Places API and does not bypass account accesscontrols.
Cost and scheduling
Runtime cost depends on:
number of searches;
requested result limits;
detail pages opened;
proxy usage;
retries;
browser duration.
A controlled run collecting five businesses completed in approximately63 seconds and incurred an infrastructure cost of approximately USD 0.062 forthe Actor owner. Actual cost can vary.
For repeated monitoring, use Apify Schedules and keep explicit result and costlimits.
Development validation
The project was validated with offline unit tests, synthetic fixtures, Pythoncompilation checks, JSON validation, Apify schema validation, remote builds,and controlled live runs.
The production package does not include internal tests, fixtures, prompts, orvalidation reports.
PT-BR — Resumo
Este Actor coleta perfis públicos de empresas no Google Maps para prospecção,pesquisa de mercado local, análise de concorrentes e preparação de CRM.
Ele recebe consultas ou URLs públicas de busca, encontra empresas, abre aspáginas públicas de detalhes e retorna dados estruturados como:
nome;
categoria;
endereço;
cidade, estado, CEP e país;
telefone;
website;
avaliação;
coordenadas;
CID;
URL do Google Maps;
consulta de origem;
posição no resultado.
O Actor usa Python, Playwright, Chrome e proxy oficial da Apify. Ele não usa aAPI do Google Places, conta Google, cookies autenticados ou chave de API.
Campos ausentes ficam null. reviewCount, horários, placeId, nível de preçoe status da empresa são best-effort e podem não estar disponíveis.
Os limites por consulta e por run são rígidos. Métricas, avisos de qualidade,bloqueios, retentativas e motivos de parada ficam armazenados em STATS.
Em um teste controlado real, o Actor coletou cinco empresas em aproximadamente63 segundos, com custo de infraestrutura de aproximadamente USD 0.062 para oproprietário do Actor.
Changelog
1.0.8
Prefilled example input so the automated Store health test runs with a valid search.
Empty-dataset health check: a run that collects zero places without an explicit public no-results state now fails with EMPTY_RESULTS instead of succeeding silently.
Dead-selector detection: a rendered results page with zero place links now fails the search context explicitly.
1.0
Initial Python and Playwright implementation.
Search query and supported request-list URL inputs.
Public Google Maps search and detail extraction.
Per-query and global limits.
Contextual deduplication.
Retry, timeout, block-detection, and evidence controls.
Dataset views for Leads, Map data, and Full details.
Structured address extraction.
Unicode and interface-glyph cleanup.
Website tracking-parameter cleanup.
Decimal CID extraction from supported public Maps URL patterns.
Localized review-count parsing with best-effort output.
Expanded STATS quality metrics and warnings.