Google Maps Leads + Contact Enrichment
Pricing
from $1.40 / 1,000 results
Google Maps Leads + Contact Enrichment
Turns any Google Maps search into a local lead list: name, phone, website, full address, coordinates, rating, review count, categories, opening hours and place/CID ids. Optionally visits each business's own website to pull the email addresses and social profiles Google never exposes.
Pricing
from $1.40 / 1,000 results
Rating
0.0
(0)
Developer
Ibnu Adzim
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Turns any Google Maps search into a local B2B lead list — and, optionally, finds the email addresses Google Maps itself never exposes by visiting each business's own website.
What you get
One row per business (recordType: PLACE):
| Group | Fields |
|---|---|
| Identity | name, placeId, cid, featureId, knowledgeGraphId, mapsUrl, cidUrl |
| Contact | phone, phoneE164, website, websiteDomain |
| Enriched contact | emails, socialProfiles (facebook / instagram / twitter / linkedin / youtube / tiktok / pinterest / whatsapp), enrichedFrom, enrichmentStatus |
| Location | fullAddress, streetAddress, addressLines, addressParts, neighbourhood, cityRegion, countryCode, latitude, longitude, timezone |
| Reputation | rating, reviewCount, reviewsUrl |
| Operations | openingHours, openStatus, attributes (accessibility, service options, …), categories, primaryCategory |
Plus one SEARCH_SUMMARY row per query (what was asked, what came back, which
honesty flags fired) and an ERROR row for any query that fails — so every
input maps to at least one row.
Example input
{"searchQueries": ["dentist Austin TX", "plumber Manchester UK"],"enrichContacts": true,"maxPlacesPerQuery": 100}
Known limits — read these before you buy
- ~200 results per query. Google's own ceiling for a single query and
viewport, measured by walking offsets 0→200: pages stay full to offset 160,
offset 180 returns a short page, offset 200 returns nothing. It ends
honestly — no clamp back to page 1. To go wider, split the area: several
narrow queries, or explicit
latitude/longitudeper district. TheperQueryCeilingReachedflag on the summary row tells you when you hit it. reviewCountis best-effort. Google alternates between two response variants for the identical request: one carries the review count, one does not. It is not a cookie, not the request shape, and not a clean function of time — all three were tested. The actor re-issues any thin page once, then reports the truth inreviewCountsAvailableandplacesWithReviewCountrather than emitting a silent null. Ratings are unaffected — they are present in both variants.openingHoursmay be today-only. The same two variants: the rich one carries all seven days, the thin one carries today. The field reflects whichever arrived; it never pads a partial week into a full-looking one.- No
totalMatches. Google publishes no match count for a local search, so this actor does not invent one —upstreamTotalAvailableis alwaysfalse. - The viewport is not a geocode. Without explicit
latitude/longitude, the map centre comes back as the country centroid for yourcountryCode, and the query text does the geographic work.viewportSourcesays which applied."dentist Austin TX"returns Austin businesses over a nationwide viewport — verified 30/30. - Enrichment is bounded and polite. Up to 3 pages per site (homepage,
then
/contact,/contact-us,/about,/about-us,/impressum), stopping as soon as both an email and a social profile are found. Every third-party host'srobots.txtis fetched and honoured first; a disallowed site is reported asenrichmentStatus: robots_disallowed, not scraped anyway. Roughly 60% of businesses yield an email in practice — the rest have no site, a JS-only contact form, or no address published.
How it works
No API key, no login, no browser.
GET /maps/search/<query>— the Maps shell, for theeisession token.GET /search?tbm=map&tch=1&pb=<protobuf>— the results endpoint, paged by offset, 100 places per request.
tch=1 is load-bearing: without it the same request answers 200 with no
results array at all — a silent empty rather than an error. 5.4 KB and zero
places without it, 315 KB and a full page with it.
The pb protobuf is deliberately minimal. A 90-token capture of the real web
client's pb was tried first and returned nothing, because hand-editing it
desynchronised the m<N> sub-message counts. Bisecting down, only the
viewport block, the !7i/!8i pagination pair and the !22m6 session block
actually matter.
WAF and TLS
None observed. chrome124, chrome131, chrome136, firefox133,
safari18_0 and chrome99_android all returned identical 200s on both
surfaces, with no challenge markers and no cookie warmup needed. The profile
pool exists for transport flakiness, not for a bypass. Default chrome124.
Google rate limits by exit IP, and answers a hot address with a 302 to
/sorry/index (a reCAPTCHA interstitial) rather than an HTTP error — detected
on the redirect target, since the followed body looks like a normal 200. The
actor rotates the exit IP on that signal. Residential proxy is the default on
the platform for the same reason. Raise minRequestInterval if you see the
warning.
Policy
www.google.com/robots.txt carries no blanket Disallow for ClaudeBot,
anthropic-ai, GPTBot or CCBot, and both surfaces this actor uses are
explicitly allowed:
Allow: /search?*tbm=mapAllow: /maps/search/Allow: /maps/place/
Only public business listings are read. No login, no user data, no reviews text, no personal profiles.