Google Maps Lead Intelligence Scraper
Pricing
from $1.00 / 1,000 results
Google Maps Lead Intelligence Scraper
Scalable Google Maps lead scraper for agencies and growth teams. Extracts clean business data with bulk mode, deduplication, and API-ready datasets. Built for reliable, low-cost lead generation and automation at scale.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer

Team Cyber Orbit
Actor stats
0
Bookmarked
4
Total users
1
Monthly active users
5 days ago
Last modified
Categories
Share
Google Maps Scraper Actor
Author: Assad Baloch
A robust, production-ready Google Maps scraper using the Apify/Crawlee Playwright stack. The actor supports single and bulk queries, persistent deduplication (dataset-level or global), per-query dataset creation, run summaries, and backup/restore utilities for KV and dataset snapshots.
π Features
- β Single and bulk queries with per-query dataset creation
- β Persistent deduplication (dataset-level or global) with TTL and key strategy (place_id preferred)
- β Structured output β full lead serialization with metadata and raw snapshots
- β Backup & restore scripts for KV and datasets
- β
Testable design β scraping logic is in
lib/scrape.jsfor unit testing
π Features
- β Low Cost - Session reuse and concurrency=1 minimize proxy usage
- β Complete Data - Name, website, phone, category, address, rating, reviews
- β Auto Pagination - Scrolls through results until target reached
- β No External Visits - Only scrapes Google Maps (no website crawling)
- β JSON Output - Structured data pushed to Apify Dataset
- β API Ready - Instant access via Apify API
π₯ Input Parameters
{"keyword": "restaurants","location": "New York, NY","maxResults": 50}
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
keyword | string | β Yes | - | Search term (e.g., "coffee shops", "plumbers") |
location | string | β Yes | - | Location to search (e.g., "Los Angeles, CA") |
maxResults | integer | β No | 50 | Max number of results (1-500) |
niche | string | β No | - | Optional label used to group results into a named dataset |
datasetName | string | β No | - | Optional exact dataset name to save results into |
perRunDataset | boolean | β No | false | If true, creates a timestamped dataset for this run |
dedupEnabled| boolean | β No | true | Enable or disable deduplication (recommended: true) | |dedupScope| string | β No |dataset|datasetorglobalscope for deduplication | |dedupKeyStrategy| string | β No |place_id|place_idpreferred; fallback toname_address| |dedupTTLdays| integer | β No | 0 | Days to keep an entry in dedup store (0 = no expiry) | |dedupAutoAdd| boolean | β No | true | Automatically add saved records to dedup store | |dedupSkip| boolean | β No | true | If true, duplicates are skipped (not saved); otherwise they are flagged | |bulkQueries| string | β No | - | Multiline textarea. Each line:keyword | location | tag(optional)| |autoCreateDatasets| boolean | β No | true | If true, creates/uses per-query datasets for bulk runs | |datasetNameTemplate| string | β No |gmaps-{tag || keyword}-{location}| Template for dataset names | |maxParallelQueries| integer | β No | 3 | Max concurrency for bulk queries | |maxQueriesPerRun| integer | β No | 200 | Max queries processed in one run | Note: If you provide a customdatasetNameorniche, the actor will sanitize it (lowercase, letters/numbers and hyphens only) to comply with Apify dataset naming rules; youβll see a warning in logs if the name is modified.
π€ Output Format
Each business record includes:
{"business_name": "Blue Bottle Coffee","website_url": "https://bluebottlecoffee.com","phone_number": "+1 415-555-0123","category": "Coffee shop","address": "66 Mint St, San Francisco, CA 94103","google_maps_url": "https://www.google.com/maps/place/...","rating": 4.5,"total_reviews": 1234}
π― Usage
Via Apify Console
- Go to Apify Console
- Find your actor
- Click "Start"
- Enter input parameters
- View results in Dataset tab
Example inputs
- Run into a per-niche dataset and skip duplicates automatically:
{"keyword": "coffee shop","location": "Seattle, WA","niche": "coffee-shops-seattle","deduplication": "per_niche","dedupAuto": true}
- Run into a timestamped snapshot dataset and generate a CSV file for download:
{"keyword": "plumbers","location": "Chicago, IL","perRunDataset": true,"downloadAsCsv": true,"csvOptions": {"filename": "plumbers-chicago.csv","includeDuplicates": false,"delimiter": ","}}
Tip: If you only want to collect results and do dedup manually later, set
dedupAuto=falseand duplicates will be marked withis_duplicate: truein the saved records.
Via API
Start a Run
curl -X POST https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs \-H "Content-Type: application/json" \-H "Authorization: Bearer YOUR_API_TOKEN" \-d '{"keyword": "dentists","location": "Chicago, IL","maxResults": 100}'
Get Results
# Get latest run results as JSONcurl https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs/LAST/dataset/items?format=json \-H "Authorization: Bearer YOUR_API_TOKEN"# Get as CSVcurl https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs/LAST/dataset/items?format=csv \-H "Authorization: Bearer YOUR_API_TOKEN"
Via JavaScript/Node.js
import { ApifyClient } from 'apify-client';const client = new ApifyClient({token: 'YOUR_API_TOKEN',});// Start the actorconst run = await client.actor('YOUR_ACTOR_ID').call({keyword: 'coffee shops',location: 'Seattle, WA',maxResults: 75,});// Get resultsconst { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(`Scraped ${items.length} businesses`);items.forEach(business => {console.log(`${business.business_name} - ${business.rating}β`);});
Via Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_API_TOKEN')# Start the actorrun = client.actor('YOUR_ACTOR_ID').call(run_input={'keyword': 'plumbers','location': 'Boston, MA','maxResults': 50})# Get resultsitems = client.dataset(run['defaultDatasetId']).list_items().itemsfor item in items:print(f"{item['business_name']} - {item['rating']}β")
π§ Configuration
Enable Proxies (Important!)
For best results, enable Apify residential proxies:
- Go to Actor Settings
- Scroll to "Proxy configuration"
- Enable "Apify proxy"
- Select "Residential proxies"
- Click "Save"
Dataset CSV export
The actor no longer generates a separate CSV file automatically. You can download the dataset for any run as CSV directly from the Apify Console (Dataset tab) or via the API using the dataset format=csv parameter.
Example (download dataset as CSV via API):
GET https://api.apify.com/v2/datasets/{datasetId}/items?format=csv
Recommended Settings
- Memory: 2048 MB
- Timeout: 3600 seconds (1 hour)
- Proxy: Residential proxies
πΊπΈ Bulk query examples (USA) β 10+ niche input set β
You can paste the following sample directly into the bulkQueries textarea in the actor UI. Each line is a single query in the format keyword | location | tag(optional). The actor will process each line as an independent query and (if autoCreateDatasets is enabled) create a dataset using the datasetNameTemplate (for example: gmaps-home-contractors-united-states).
Run modes:
auto(default): the actor runs in bulk ifbulkQueriesis provided; otherwise single-query mode is used.single: explicit single-query mode β requireskeywordandlocation.bulk: explicit bulk mode β requiresbulkQueries(useful when you want to run a bulk job even ifkeyword/locationare present).
This makes it convenient to use either workflow while keeping validation strict and user-friendly.
Home contractors | United States | home-contractorsHVAC services | United States | hvacRecruitment agency | United States | recruitment-agencyDigital marketing agency | United States | digital-marketingPlumbing contractors | United States | plumbersElectrical contractors | United States | electriciansLandscaping services | United States | landscapingRoofing contractors | United States | roofingCleaning services | United States | cleaningIT managed services | United States | it-managed-servicesSecurity services | United States | securityAccounting firms | United States | accounting
β οΈ Tip: Country-wide searches can return a lot of results β set a reasonable
maxResultsper query and usemaxParallelQueriesto balance speed vs resource usage.
You can also save this sample as examples/preset-bulk-usa.txt and copy/paste it into the UI or use it as a starting point for larger bulk runs.
π API Endpoints
After run completion, access results via:
# JSON formatGET https://api.apify.com/v2/datasets/{datasetId}/items?format=json# CSV formatGET https://api.apify.com/v2/datasets/{datasetId}/items?format=csv# Excel formatGET https://api.apify.com/v2/datasets/{datasetId}/items?format=xlsx# XML formatGET https://api.apify.com/v2/datasets/{datasetId}/items?format=xml
Quick access to latest run:
GET https://api.apify.com/v2/acts/{actorId}/runs/LAST/dataset/items?format=json
β‘ Performance
| Results | Time | Est. Cost |
|---|---|---|
| 10 | ~1 min | $0.01 |
| 50 | ~3 min | $0.03 |
| 100 | ~5 min | $0.05 |
| 500 | ~20 min | $0.20 |
Times and costs are approximate and vary by location/density
π° Cost Optimization
This actor minimizes costs through:
- Session Reuse - Single session used up to 50 times
- Low Concurrency - Only 1 concurrent request
- Smart Scrolling - Stops when target reached
- No External Crawling - Never visits business websites
- Efficient Extraction - Minimal wait times
π οΈ Development
Local Setup
# Clone repositorygit clone https://github.com/techkaroshi-Assad/gmaps-scraper-apify-actor.gitcd gmaps-scraper-apify-actor# Install dependenciesnpm install# Set Apify tokenexport APIFY_TOKEN=your_token_here# Run locallynpm start
File Structure
.βββ main.js # Main scraper logicβββ package.json # Dependenciesβββ INPUT_SCHEMA.json # Input parameter definitionsβββ Dockerfile # Docker configurationβββ .actor/β βββ actor.json # Actor metadataβββ README.md # This file
User Guide & Local Testing
- For quick smoke tests that do not require browsers, run:
$node test-smoke.js
This will validate dataset creation, Key-Value store behavior, and run summary saving to the gmaps-run-summaries dataset and KV store.
- To perform a full local run with browsers (Playwright), install Playwright browsers locally first (large download):
npx playwright install --with-depsnpx apify run
Note: the production Docker image used on Apify already includes browsers.
π Troubleshooting
No Results Found
- Verify keyword and location are correct
- Test the same search on Google Maps manually
- Try more generic keywords (e.g., "restaurants" vs "vegan restaurants")
Missing Phone/Website
- Some businesses don't list this information on Google Maps
- This is expected behavior - the scraper gets all available data
Build Failures
- Ensure all 5 files are present
- Check
package.jsonsyntax - Verify
Dockerfilehas no extra whitespace
Run Timeouts
- Reduce
maxResultsto test (try 10-20) - Enable residential proxies in settings
- Increase timeout in Actor settings
π Resources
π Privacy & Terms
- This actor only scrapes publicly available data from Google Maps
- Respects Google's robots.txt and terms of service
- Uses residential proxies to avoid rate limiting
- No personal data collection beyond public business information
π License
IPO License-Tech_Karoshi_@Assad Balouch
ISC License - See LICENSE file for details
π€ Support
- Issues: Open an issue in this repository
- Dev Support: techkaroshi@gmail.com
- Apify Support: support@apify.com
- Documentation: Apify Docs
β Credits
Built with:
Made with β€οΈ by techkaroshi-Assad
For questions or custom development, reach out via GitHub Issues