Google Maps Business Directory Scraper
Pricing
from $1.44 / 1,000 business places
Google Maps Business Directory Scraper
Build bounded Google Maps business directories from keyword and location batches, with place identities, addresses, public contacts, coordinates and ratings.
Pricing
from $1.44 / 1,000 business places
Rating
0.0
(0)
Developer
Automation Lab
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
13 days ago
Last modified
Categories
Share
Build a Google Maps business directory from supplied business keywords and locations. Export bounded public place records with names, categories, addresses, ratings, business websites, phones, coordinates and Maps identity. Use repeated runs to refresh a local contact directory; compare snapshots downstream rather than assuming this Actor detects changes.
This is a limited-view directory tool, not an exhaustive area scanner. It does not collect reviews, reviewer identities, photos, email addresses, employee contacts or website enrichment.
Who is it for?
- Local-market researchers comparing visible businesses across cities.
- Agencies building small, recurring prospecting directories from public business contacts.
- Operations teams connecting place coordinates to route planning or spreadsheets.
Why use it?
The input is a small keyword × location batch. Each business row carries the originating query, stable feature identity and extraction time. Run-global deduplication keeps one row per place without mixing prior runs into the current export. Missing public contact fields remain null; nothing is guessed or enriched.
Unlike broader Maps products, this Actor intentionally focuses on a bounded first search view and public business profiles. It offers no reviews, galleries or exhaustive discovery.
Getting started
- Enter one or more business keywords, such as
coffeeorbakery. - Enter cities or regions, such as
Austin Texas. - Choose a per-query and global row limit.
- Run the Actor and inspect the Business directory dataset view.
- Export JSON, CSV or Excel from Apify, or read the dataset through its API.
Input example
{"keywords": ["coffee"],"locations": ["Austin Texas"],"maxPlacesPerQuery": 10,"maxItems": 100}
Input parameters
| Parameter | Default | Meaning |
|---|---|---|
keywords | Required | 1–10 business search strings, each up to 150 characters. |
locations | Required | 1–10 city/region strings, each up to 150 characters. |
maxPlacesPerQuery | 10 | 1–20 new business rows per keyword/location combination after deduplication. |
maxItems | 100 | 1–200 saved business rows across the entire run. |
At most 10 keyword/location combinations are supported. Every keyword is combined with every location in keyword-major input order. Strings are trimmed and whitespace-normalized; exact normalized duplicates are removed case-sensitively.
Locations are appended as search text, not strict geographic boundaries. Google decides relevance and may include nearby or related businesses. English interface and US search context are fixed; place records need not be in the US. No exact phrase, whole-word, rating or category filter is applied by this Actor.
Zero and unlimited limits are unsupported. The global limit, per-query limit and customer charge limit may stop collection earlier than the source view. Only up to 20 source results per query are fetched; there is no pagination.
Extracted data
| Fields | Meaning |
|---|---|
name, category, categories | Public business name and source categories. |
address | Source formatted street address when shown. |
rating, reviewsCount | Aggregate rating and review count, not individual reviews. |
website, phone | Public business contacts shown by Maps; null when absent. |
location.lat, location.lng | Business coordinates, not viewport center. |
placeId, fid, cid | Google identities; CID is a string to preserve precision. |
googleMapsUrl | Maps link using CID. |
keyword, searchLocation, effectiveQuery | First query that produced the saved place. |
sourceUrl, scrapedAt, coverage | Search provenance, UTC extraction time and limited_view scope. |
Business records must have a name, feature identity, category and valid coordinates. Geographic-only results without business categories are excluded. Optional fields can be null.
Output example
A representative Austin coffee result has this shape (public business fields; identities omitted here for readability):
{"name": "Epoch Coffee","category": "Coffee shop","categories": ["Coffee shop"],"address": "221 W N Loop Blvd, Austin, TX 78751","rating": 4.5,"website": "http://www.epochcoffee.com/","location": {"lat": 30.3186037, "lng": -97.7245402},"keyword": "coffee","searchLocation": "Austin Texas","effectiveQuery": "coffee Austin Texas","coverage": "limited_view"}
Actual rows include all documented fields. Source values and result order change over time. The key-value store OUTPUT record contains saved count, coverage and deduplication semantics, not additional places.
How much does it cost to extract Google Maps business directories?
Pricing is a $0.005 run start plus each unique saved business place. BRONZE item price is $0.0024; FREE $0.00276, SILVER $0.001872, and GOLD/PLATINUM/DIAMOND $0.00144. Spend tiers follow qualifying aggregate monthly Apify Store spend, not this Actor's individual run volume.
At BRONZE, estimated costs are $0.029 for 10 places, $0.065 for 25 places and $0.245 for 100 places. The start fee applies even if no business rows are returned. Duplicates, excluded geographic records and failed requests have no item charge. Failed runs may contain already charged partial output. Consult the Pricing tab for your applicable plan tier and set a maximum total charge when needed.
Limits and reliability
- Limited first-view results, not all businesses in a city or category.
- Run-global FID deduplication; the first producing query retains provenance.
- Sequential queries and at most two attempts per query with renewed request session identity.
- No automatic residential proxy or browser fallback, and no customer proxy controls.
- Unexpected shells, challenges and unrecognized response shapes fail instead of claiming a valid empty directory.
- A recognized geographic-only result can yield zero business rows legitimately.
- Upstream interruptions can leave partial rows; a failed run is not a complete batch.
Tips for useful searches
Use specific business keywords and city/region names. Start with one query before expanding a batch. Nearby results are source relevance, not a hard-boundary error. Use coordinates for downstream territory checks; this Actor does not apply a geofence. Compare stable FIDs across snapshots instead of business names alone.
Integrations
Export a directory to Google Sheets or a CRM through an Apify integration. Schedule the same input to refresh contact listings, then compare snapshots in your own workflow. Use webhooks to trigger downstream processing only after a successful run; treat failed-run exports as partial.
For routing, pass the returned coordinates to Google Maps Directions and Routes API. It is a separate route-record product, not business directory enrichment.
API usage
Start a run once and retain its run/storage IDs:
curl -X POST 'https://api.apify.com/v2/acts/automation-lab~google-maps-keyword-location-directory/runs' \-H "Authorization: Bearer $APIFY_TOKEN" \-H 'Content-Type: application/json' \-d '{"keywords":["coffee"],"locations":["Austin Texas"],"maxPlacesPerQuery":10}'
JavaScript with apify-client:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: process.env.APIFY_TOKEN });const run = await client.actor('automation-lab/google-maps-keyword-location-directory').call({ keywords: ['coffee'], locations: ['Austin Texas'], maxPlacesPerQuery: 10 });const { items } = await client.dataset(run.defaultDatasetId).listItems({ limit: 20 });
Python with apify-client:
import osfrom apify_client import ApifyClientclient = ApifyClient(os.environ['APIFY_TOKEN'])run = client.actor('automation-lab/google-maps-keyword-location-directory').call(run_input={'keywords': ['coffee'], 'locations': ['Austin Texas'], 'maxPlacesPerQuery': 10})items = client.dataset(run['defaultDatasetId']).list_items(limit=20).items
Initialize clients with your own token kept outside source. Poll the same run if using the asynchronous API; do not start a replacement merely to check status.
MCP usage
Use the Actor-specific hosted endpoint:
claude mcp add --transport http apify \'https://mcp.apify.com?tools=automation-lab/google-maps-keyword-location-directory'
Claude Desktop, Cursor and VS Code: use an HTTP-capable MCP client with this configuration (authenticate with your own Apify token):
{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/google-maps-keyword-location-directory"}}}
Discover actual names and argument schemas with scoped tools/list. Actor selection also adds run/storage/abort tools; discovery does not authorize execution. Example prompt: “Run the business directory for coffee in Austin Texas, maximum 10 places, and show names, categories and websites.”
For an authorized invocation, start once, retain the run ID, and poll that same run with bounded backoff (2, 4, 8, then 10 seconds) up to a 120-second consumer deadline. call-actor can wait at most 45 seconds, so its response may contain only run metadata. Configure client timeout above the chosen wait plus transport margin. On timeout recover the known run rather than restart; if its ID is unknown, report uncertainty.
After success, read get-dataset-items with explicit limit, offset and needed fields. An example consumer budget is pages of 20 source rows, at most 100 rows and 64 KiB serialized UTF-8 admitted to model context. Enforce bytes host-side; omit or summarize oversized rows with disclosure. Report continuation offset and truncated status. If the client cannot enforce bytes, do not promise a hard byte guarantee. Full exports remain outside model context. These are consumer limits, not Actor collection settings.
Legality and privacy
Use public business data responsibly, comply with source terms and applicable privacy/contact laws, and do not assume that public phone listings authorize unsolicited outreach. This Actor is not affiliated with Google and offers no legal advice.
Failed operations send sanitized diagnostic input, exceptions and actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed; reports are retained for 30 days. No diagnostic credentials are exposed in the input schema. Runtime uses no AI provider. Query text is sent to Google for public search; business websites are not visited. Results and run logs remain in your Apify storage until your account retention settings or deletion remove them; this Actor sets no independent dataset expiry. Request sessions are ephemeral. Contact us through the Actor's Apify Issues tab with a safe input and run ID for support.
Troubleshooting and FAQ
Why fewer rows than requested? Limits are ceilings. The first view may contain fewer business results, or duplicate FIDs may already have been saved by earlier queries.
Why are website or phone null? The public Maps result did not show the field. No website visit or enrichment is performed.
Can I collect reviews, photos or emails? No. Only aggregate review counts and ratings are included.
Does this cover every business in an area? No. Source relevance and first-view limits make exhaustive claims inappropriate.
What if the run fails? Check the log for upstream status or unexpected response shape. Keep partial rows separate from complete batches. A challenge or shell is not reported as a successful empty directory.
Related Actor
Google Maps Directions and Routes API turns known coordinates into route records. This directory Actor does not reinstate retired enrichment products or collect route records itself.