Google Maps Scraper — Extract Business Data at Scale avatar

Google Maps Scraper — Extract Business Data at Scale

Pricing

from $4.00 / 1,000 result scrapeds

Go to Apify Store
Google Maps Scraper — Extract Business Data at Scale

Google Maps Scraper — Extract Business Data at Scale

Collect public Google Maps business listing data including names, categories, addresses, websites, ratings, review counts, hours, coordinates, and Maps URLs. Export structured data to JSON, CSV, or Excel.

Pricing

from $4.00 / 1,000 result scrapeds

Rating

0.0

(0)

Developer

Md Jakaria Mirza

Md Jakaria Mirza

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

4 days ago

Last modified

Share

Google Maps Scraper - Extract Business Data at Scale

Production-grade Apify Actor for scraping public Google Maps business listings worldwide. Enter a keyword and location, run a small test, then export clean business data to JSON, CSV, Excel, XML, or RSS from the Apify Dataset.

This Actor is built with Node.js 20, TypeScript, Apify SDK v3, Crawlee, and Playwright. It uses Apify residential proxies, session rotation, randomized delays, and resilient extraction logic for Google Maps result pages.

Apify Store Listing

Title: Google Maps Scraper - Extract Business Data at Scale

Short description: Scrape worldwide Google Maps listings with names, phones, websites, ratings, reviews, categories, hours, and coordinates. Export to CSV, JSON, or Excel.

Store description:

Google Maps Scraper - Extract Business Data at Scale helps teams collect structured local business data from Google Maps searches worldwide. Use it to find restaurants in London, dentists in Dubai, hotels in Tokyo, plumbers in Toronto, clinics in Berlin, or any other keyword/location combination. The Actor opens Google Maps in a real browser, scrolls the search feed, visits each business detail panel, and extracts practical B2B data including business name, address, phone, website, category, rating, reviews count, opening hours, coordinates, Google Maps ID, plus code, and Maps URL.

It supports batch scraping by combining multiple keywords with multiple locations in a single run. Locations can be cities, countries, postal codes, neighborhoods, addresses, latitude/longitude pairs, the built-in 169-city high_demand_markets preset, or the broader 171-city world_major_cities preset. Country targeting is optional: leave countryCode empty for worldwide location-text based searches, or set it to bias Google Maps and proxy country for a specific market.

The Actor uses Apify Pay Per Event + platform usage pricing. As of the last live check on 2026-06-29, the current pricing entry started on 2026-06-25: result-scraped at $0.004 per saved result and apify-actor-start at $0.001 per start event. The start event is charged by allocated memory (one event per GB, minimum one), and users also pay Apify platform usage generated by the run, such as compute and proxy traffic. Failed searches, empty locations, retries, and blocked pages do not create result-scraped events.

For first tests, keep the run small: one keyword, one location, maxResults 5 or less, maxCrawledPlacesPerQuery 5 or less, and scrapeDetails disabled unless you need phone/full-address enrichment.

Built for market research, local SEO audits, and retail site selection, this scraper is designed for repeatable production use and Apify Store publishing.

What It Extracts

  • Business name
  • Address (full street address from the place page when scrapeDetails is enabled)
  • Phone number (from the place page when scrapeDetails is enabled)
  • Website
  • Category
  • Rating
  • Reviews count
  • Opening hours
  • Latitude and longitude
  • Google Maps ID
  • Plus code (from the place page when scrapeDetails is enabled)
  • Google Maps URL
  • Keyword, location, query, and scrape timestamp

Worldwide Use

This Actor is not limited to Kolkata, India, the United States, or any single country. It works globally because:

  • Search locations are free-form strings, e.g. Paris, France, Sao Paulo, Brazil, Shibuya, Tokyo, Japan, Dubai Marina, UAE.
  • The built-in high_demand_markets preset covers 169 commercial cities where local business data, local SEO, and market research use cases are most common.
  • The built-in world_major_cities preset covers 171 big and famous cities across North America, Latin America, Europe, the Middle East, Africa, South Asia, East/Southeast Asia, and Oceania.
  • countryCode is optional and defaults to no gl country bias.
  • The proxy country is not forced by default.
  • If you set countryCode, the Actor also uses that country for proxy targeting unless you explicitly override proxyConfig.apifyProxyCountry.

For best accuracy, include the country in each location. For example, use restaurants in Georgia, USA or restaurants Tbilisi, Georgia instead of only Georgia.

Preset Strategy

  • high_demand_markets: best default for broad coverage. Focuses on rich metro areas, business hubs, startup hubs, GCC markets, English-speaking countries, EU business centers, India metros, and fast-growing APAC/LATAM cities where customers commonly use local business data, local SEO, and market research data.
  • world_major_cities: broader global coverage for users who want famous cities across more regions, including tourism, emerging markets, and general business hubs.
  • none: use only custom locations when the customer already knows the exact target market.

Use Cases

  1. Local business data: build business listing datasets with names, phones, websites, addresses, and Maps URLs.
  2. Market research: compare competitor density, ratings, and categories by city or region.
  3. Local SEO audits: check business presence, category choices, and public NAP data.
  4. Territory planning: understand business distribution before entering a new market.
  5. Retail and real estate analysis: identify dense commercial clusters and underserved areas.

Pricing and cost control

This Actor uses Apify Pay Per Event + platform usage pricing. Prices can be changed only through Apify's pricing window or Support process, so always treat the live Console pricing as the source of truth before running large jobs.

Event namePrice per event1,000 results10,000 results
result-scraped$0.004 active live$4.00$40.00
apify-actor-start$0.001 active liven/an/a

In addition to the event prices above, the user pays Apify platform usage generated by the run, including compute and proxy traffic. Residential proxy is recommended for Google Maps reliability, but it can increase run cost. For a default 2048 MB run, the start event may be counted as two GB-based events, so the effective default start charge is about $0.002.

The code charges only after a business record is extracted and before it is pushed to the dataset. If the charge budget is exhausted, the Actor stops gracefully. Dataset writes are retried after charging to reduce the risk of paid rows not being stored.

Cost-control tips:

  • Start with one keyword and one location.
  • Use maxResults 1-5 for a test run.
  • Keep maxCrawledPlacesPerQuery close to maxResults.
  • Leave locationPreset as none unless you intentionally want a large multi-city run.
  • Keep scrapeDetails=false for cheaper list-style runs; enable it only when phone/full address/plus code matter.

Input

FieldTypeRequiredDefaultDescription
keywordsarrayyesnoneBusiness types or search terms.
locationsarraynononeCustom cities, regions, postal codes, addresses, or lat,lon pairs anywhere in the world. Required only when no preset is selected.
locationPresetstringnononeUse high_demand_markets for 169 commercial hotspots, world_major_cities for broad global coverage, or none for custom locations only. Custom locations are added on top.
maxResultsintegerno5Maximum saved rows per keyword/location pair. Start with 1-5 for tests; increase for production. Allowed: 1-5000.
maxCrawledPlacesPerQueryintegerno5Maximum place cards/detail pages to inspect per query. Keep close to maxResults for low-cost tests; set higher only when many listings may be closed or duplicates.
languagestringnoenResult language code, e.g. en, de, es, fr, ja.
countryCodestringnononeOptional 2-letter country bias, e.g. gb, de, jp, ae.
skipClosedBusinessesbooleannotrueSkip listings marked permanently closed.
scrapeDetailsbooleannofalseVisit each place page when phone or full address is missing from the list view; also captures the plus code. Keep disabled for faster/cheaper list-only runs.
proxyConfigobjectnoResidential Apify proxyApify proxy configuration. Leave country empty for global runs.

The Actor removes duplicate keywords and locations. The keyword/location cartesian product is capped at 1,000 queries to prevent accidental huge runs. With either large preset, up to 5 keywords fit under the 1,000-query cap. For first tests, keep locationPreset as none and use 1-2 custom locations.

When scrapeDetails is enabled, the Actor performs an extra navigation to each place's individual Google Maps page whenever the list view did not expose a phone number or full address. Each detail page has a 10-second timeout. If the detail page fails, the Actor keeps the list-view data so no record is dropped.

Example Inputs

Quick Low-Cost Test

{
"keywords": ["coffee shop"],
"locations": ["London, UK"],
"locationPreset": "none",
"maxResults": 5,
"maxCrawledPlacesPerQuery": 5,
"language": "en",
"countryCode": "gb",
"skipClosedBusinesses": true,
"scrapeDetails": false,
"proxyConfig": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}

High-Demand Markets Batch

{
"keywords": ["coffee shop"],
"locationPreset": "high_demand_markets",
"maxResults": 25,
"maxCrawledPlacesPerQuery": 50,
"language": "en",
"skipClosedBusinesses": true,
"scrapeDetails": true,
"proxyConfig": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}

Broad World Cities Batch

{
"keywords": ["restaurant"],
"locationPreset": "world_major_cities",
"maxResults": 25,
"maxCrawledPlacesPerQuery": 50,
"language": "en",
"skipClosedBusinesses": true,
"scrapeDetails": true
}

Custom Global Batch

{
"keywords": ["coffee shop", "coworking space"],
"locations": ["London, UK", "Berlin, Germany", "Tokyo, Japan", "Dubai, UAE"],
"maxResults": 50,
"maxCrawledPlacesPerQuery": 100,
"language": "en",
"skipClosedBusinesses": true,
"scrapeDetails": true,
"proxyConfig": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}

Country-Biased Run

{
"keywords": ["dentist"],
"locations": ["Manchester", "Birmingham", "Leeds"],
"maxResults": 200,
"maxCrawledPlacesPerQuery": 300,
"language": "en",
"countryCode": "gb",
"skipClosedBusinesses": true,
"scrapeDetails": true
}
{
"keywords": ["hotel"],
"locations": ["25.2048,55.2708", "48.8566,2.3522"],
"maxResults": 100,
"scrapeDetails": true
}

Fast List-Only Run

{
"keywords": ["pizza"],
"locations": ["New York, USA"],
"maxResults": 200,
"scrapeDetails": false
}

Output dataset

The default Google Maps Business Listings dataset view is built for business research, local SEO, and market analysis exports. It shows business name, category, rating, review count, address, phone, website, opening hours, Google Maps URL, keyword, location, and scraped timestamp. The full JSON output also includes coordinates, Maps ID, Plus Code, and the combined query when available.

Verified small-run sample from an existing successful run:

{
"title": "Hideaway Coffee House",
"address": "7 Farrier's Psge, London W1D 7DP",
"phone": null,
"website": "https://www.instagram.com/hideawaycoffee/",
"category": "Coffee shop",
"rating": 4.7,
"reviewsCount": 1241,
"hours": [
"Sunday: 9 am-5 pm",
"Monday: 7:30 am-5 pm",
"Tuesday: 7:30 am-5 pm"
],
"latitude": 51.5113375,
"longitude": -0.1352386,
"mapsId": "0x4876057cc8805b41:0x60c897012e57e344",
"plusCode": null,
"url": "https://www.google.com/maps/place/Hideaway+Coffee+House/data=!4m7!3m6!1s0x4876057cc8805b41:0x60c897012e57e344!8m2!3d51.5113375!4d-0.1352386!16s%2Fg%2F11g4lm05yc!19sChIJQVuAyHwFdkgRRONXLgGXyGA",
"keyword": "coffee shops",
"location": "London",
"query": "coffee shops London",
"scrapedAt": "2026-06-21T08:02:48.057Z"
}

API Example

curl -X POST "https://api.apify.com/v2/acts/fascinating_lentil~google-maps-scraper/runs?token=YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"keywords": ["coffee shop"],
"locations": ["London, UK"],
"maxResults": 5,
"maxCrawledPlacesPerQuery": 5,
"language": "en",
"scrapeDetails": false
}'
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });
const run = await client.actor('fascinating_lentil/google-maps-scraper').start({
keywords: ['coffee shop'],
locations: ['London, UK'],
maxResults: 5,
maxCrawledPlacesPerQuery: 5,
language: 'en',
scrapeDetails: false,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Got ${items.length} businesses`);

How It Works

  1. Validates input with clear errors.
  2. Builds one Google Maps search URL per keyword/location pair.
  3. Adds hl language and optional gl country bias only when provided.
  4. Runs Playwright through Apify residential proxies and Crawlee sessions.
  5. Scrolls Google Maps results until enough places are loaded or the feed ends.
  6. Opens each listing detail panel and extracts business data.
  7. If scrapeDetails is enabled and phone or address is still missing, visits the place's individual Google Maps page with a 10-second timeout to retrieve phone, full address, and plus code.
  8. Deduplicates records by Maps ID and title.
  9. Charges result-scraped and writes records to the Apify Dataset.

Anti-Bot Handling

  • Apify residential proxy support.
  • Optional country-matched proxy targeting.
  • Session pool with limited usage per session.
  • Randomized scroll, click, and extraction delays.
  • Retry support for transient blocks and navigation failures.
  • Graceful field-level fallback to null when optional data is unavailable.

Project Structure

google-maps-scraper/
.actor/
actor.json
Dockerfile
src/
main.ts
routes.ts
types.ts
INPUT_SCHEMA.json
input.json
package.json
package-lock.json
README.md
PROMOTION-NOTES.md
tsconfig.json

Local Development

npm ci
npm run build
npx playwright install chromium
npm start

For Apify local runs, put your input in storage/key_value_stores/default/INPUT.json or use the included input.json as a starting point.

Suggested Next Updates

  • Add live smoke-test fixtures for 3 countries before each release.
  • Add optional review scraping as a separate PPE event, e.g. review-scraped.
  • Add region presets such as North America, Europe, GCC, APAC, and LATAM.
  • Add a per-query summary dataset or key-value output for marketplace-quality reporting.

Known Limits

  • scrapeDetails defaults to false for faster list-style runs. When it is enabled, keep maxCrawledPlacesPerQuery small because each detail page may add extra navigation time.
  • The current default run timeout is 1 hour (timeoutSecs: 3600 in .actor/actor.json) and the per-query handler timeout is 10 minutes. Use one keyword, one location, and low caps for tests; split larger multi-city jobs into separate runs.
  • Detail-page enrichment only fires when phone or full address is missing from the list view, so runs against well-structured queries where the list view already exposes the phone will not pay the extra navigation cost.
  • Duplicate detection is based on mapsId (or title when mapsId is unavailable). Two chain stores with the same business name but different mapsId are kept as separate records.

Use this Actor for legitimate business intelligence, local business data collection, local SEO, and market research. You are responsible for complying with Google Maps terms, privacy laws, anti-spam rules, GDPR, CAN-SPAM, and local outreach regulations in every country where you use the data.

Responsible Use

This Actor is intended for lawful collection of publicly available information only. Users are responsible for ensuring their use complies with the source website's terms, robots.txt, applicable privacy laws, including India's DPDP Act, and all local regulations.

Do not use this Actor to collect, store, sell, or misuse personal data without a lawful basis. The Actor author is not responsible for misuse by end users.

License

Apache-2.0. See LICENSE.