Google Maps Lead Intelligence Scraper avatar
Google Maps Lead Intelligence Scraper
Under maintenance

Pricing

from $1.00 / 1,000 results

Go to Apify Store
Google Maps Lead Intelligence Scraper

Google Maps Lead Intelligence Scraper

Under maintenance

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

Team Cyber Orbit

Maintained by Community

Actor stats

0

Bookmarked

4

Total users

1

Monthly active users

5 days ago

Last modified

Share

Google Maps Scraper Actor

Author: Assad Baloch

Apify Actor License: ISC

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.js for 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
}
ParameterTypeRequiredDefaultDescription
keywordstringβœ… Yes-Search term (e.g., "coffee shops", "plumbers")
locationstringβœ… Yes-Location to search (e.g., "Los Angeles, CA")
maxResultsinteger❌ No50Max number of results (1-500)
nichestring❌ No-Optional label used to group results into a named dataset
datasetNamestring❌ No-Optional exact dataset name to save results into
perRunDatasetboolean❌ NofalseIf true, creates a timestamped dataset for this run
  • dedupEnabled | boolean | ❌ No | true | Enable or disable deduplication (recommended: true) | | dedupScope | string | ❌ No | dataset | dataset or global scope for deduplication | | dedupKeyStrategy | string | ❌ No | place_id | place_id preferred; fallback to name_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 custom datasetName or niche, 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

  1. Go to Apify Console
  2. Find your actor
  3. Click "Start"
  4. Enter input parameters
  5. 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=false and duplicates will be marked with is_duplicate: true in 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 JSON
curl https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs/LAST/dataset/items?format=json \
-H "Authorization: Bearer YOUR_API_TOKEN"
# Get as CSV
curl 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 actor
const run = await client.actor('YOUR_ACTOR_ID').call({
keyword: 'coffee shops',
location: 'Seattle, WA',
maxResults: 75,
});
// Get results
const { 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 ApifyClient
client = ApifyClient('YOUR_API_TOKEN')
# Start the actor
run = client.actor('YOUR_ACTOR_ID').call(run_input={
'keyword': 'plumbers',
'location': 'Boston, MA',
'maxResults': 50
})
# Get results
items = client.dataset(run['defaultDatasetId']).list_items().items
for item in items:
print(f"{item['business_name']} - {item['rating']}⭐")

πŸ”§ Configuration

Enable Proxies (Important!)

For best results, enable Apify residential proxies:

  1. Go to Actor Settings
  2. Scroll to "Proxy configuration"
  3. Enable "Apify proxy"
  4. Select "Residential proxies"
  5. 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
  • 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 if bulkQueries is provided; otherwise single-query mode is used.
  • single: explicit single-query mode β€” requires keyword and location.
  • bulk: explicit bulk mode β€” requires bulkQueries (useful when you want to run a bulk job even if keyword/location are present).

This makes it convenient to use either workflow while keeping validation strict and user-friendly.

Home contractors | United States | home-contractors
HVAC services | United States | hvac
Recruitment agency | United States | recruitment-agency
Digital marketing agency | United States | digital-marketing
Plumbing contractors | United States | plumbers
Electrical contractors | United States | electricians
Landscaping services | United States | landscaping
Roofing contractors | United States | roofing
Cleaning services | United States | cleaning
IT managed services | United States | it-managed-services
Security services | United States | security
Accounting firms | United States | accounting

⚠️ Tip: Country-wide searches can return a lot of results β€” set a reasonable maxResults per query and use maxParallelQueries to 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 format
GET https://api.apify.com/v2/datasets/{datasetId}/items?format=json
# CSV format
GET https://api.apify.com/v2/datasets/{datasetId}/items?format=csv
# Excel format
GET https://api.apify.com/v2/datasets/{datasetId}/items?format=xlsx
# XML format
GET 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

ResultsTimeEst. 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:

  1. Session Reuse - Single session used up to 50 times
  2. Low Concurrency - Only 1 concurrent request
  3. Smart Scrolling - Stops when target reached
  4. No External Crawling - Never visits business websites
  5. Efficient Extraction - Minimal wait times

πŸ› οΈ Development

Local Setup

# Clone repository
git clone https://github.com/techkaroshi-Assad/gmaps-scraper-apify-actor.git
cd gmaps-scraper-apify-actor
# Install dependencies
npm install
# Set Apify token
export APIFY_TOKEN=your_token_here
# Run locally
npm 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-deps
npx 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.json syntax
  • Verify Dockerfile has no extra whitespace

Run Timeouts

  • Reduce maxResults to 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

⭐ Credits

Built with:


Made with ❀️ by techkaroshi-Assad

For questions or custom development, reach out via GitHub Issues