# Google Maps Scraper: Businesses, Phones, Websites & Ratings (`redfoxscout/google-maps-business-scraper`) Actor

Scrape Google Maps business listings for any search and location: name, category, address, phone, website, rating, review count, opening hours, coordinates and place ID. Up to 140 places per search. No login, no browser, fast and cheap.

- **URL**: https://apify.com/redfoxscout/google-maps-business-scraper.md
- **Developed by:** [Red Fox Scout](https://apify.com/redfoxscout) (community)
- **Categories:** Lead generation, Travel
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.75 / 1,000 places

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

Scrape **every business on Google Maps** for a search and an area. Turn on **Cover the whole area** and the city is split into map tiles, so you get **every matching place Google shows in the area, once each**, not just the places one Google Maps search returns. Each place comes with **name, address, phone, website, rating, review count, opening hours, coordinates and place ID**. No login and no browser.

**Price: $1 per 1,000 places.** Duplicates, places removed by a filter and failed searches are free. Apify's free plan ($5 monthly credit) covers about 5,000 places a month.

[![Every dentist in Dubai, whole-city sweep: real output preview (Cover the whole area: every dentist in Dubai, not one search page)](https://raw.githubusercontent.com/TikTop-Data/apify-store-assets/main/images/google-maps-business-scraper-output.png)](https://apify.com/redfoxscout/google-maps-business-scraper)

### Questions it answers

- Which dentists are in the whole of Dubai, with phone numbers?
- Which businesses in my target city have no website (prospects for web agencies)?
- Where are all the branches of a brand in a city, and what is around a point on the map?
- Which places are not closed, have a phone number and at least 100 reviews?

### Who uses this

- 📈 **Sales and lead generation:** complete business lists with phone and website, by niche and city.
- 🏢 **Marketing and web agencies:** businesses with no website, or with weak ratings.
- 📍 **Market research and expansion:** count and map competitors, branches and gaps in any area.
- 🗂️ **Data teams:** feed places into a CRM, a directory or a map.

### Why this Google Maps Scraper

- 🗺️ **Whole-area coverage:** one Google Maps search returns one list. Cover the whole area sweeps the city and returns each matching place once.
- ⚡ **Fast and cheap:** reads the data Google Maps loads, without a browser. Runs of 20 places take seconds.
- 💰 **$1 per 1,000 places**, all fields included: phone, website, rating, reviews, hours, photos, coordinates and IDs.
- 🎯 **Filters:** rating, review count, website, phone, closed places, categories and name matching.
- 🔁 **Many searches in one run:** every search runs in every location; duplicates are removed and not charged.
- 📧 **Pairs with contact extraction:** send the `website` column to the Website Contact Extractor to get emails.

### How to use the Google Maps Scraper

1. Click **Try for free** (a free Apify account is enough).
2. Enter what to search, one per line, e.g. `dentists in Dubai`. Or enter `dentists` and add cities under Locations.
3. For every place in a city, turn on **Cover the whole area** and raise **Max results per search** (a plain search stops after a few hundred places).
4. Click **Start**, then download as JSON, CSV or Excel.

### Input

| Field | Default | What it does |
|---|---|---|
| `searchQueries` | – | Searches as typed in Google Maps, one per line, e.g. `dentists in Dubai`. |
| `locations` | – | Cities or areas; every search runs in each one (`<search> in <location>`). |
| `searchWholeArea` | `false` | Cover the whole area: sweep map tiles so every matching place Google shows in the area is returned once. |
| `maxItems` | 60 | Places per search. With Cover the whole area use hundreds or thousands. |
| `startUrls` | – | Google Maps search links (`/maps/search/...@lat,lng,zoom`) and place links. `?cid=` links are not supported. |
| `placeIds` | – | Google place IDs such as `ChIJ1S_Bov20RIYRe7MiR8tYawY`. One row per place. |
| `latitude`, `longitude` | – | A map point to search around. Set both. |
| `radiusKm` | 5 | Radius of the circle around the point (0.2 to 200 km). Places outside the circle are left out; with Cover the whole area, every place inside it is returned. |
| `skipClosedPlaces` | `false` | Leave out places Google marks as permanently or temporarily closed. |
| `categoryFilterWords` | – | Keep a place only if one of its Google categories contains one of these words, e.g. `dentist`, `orthodontist`. |
| `searchMatching` | `all` | Name must match: any place Google returns, the name contains the search words, or the name is exactly the search words. Works with `Starbucks in Dubai` or with `Starbucks` plus Locations `Dubai`: the city part is not part of the name check. |
| `minRating` | – | Skip places rated below this (whole number, 1 to 5). Places without a rating are skipped when this is set. |
| `minReviews` | – | Skip places with fewer reviews. Places without a review count are skipped when this is set. |
| `website` | `allPlaces` | All places, only places with a website, or only places without one. |
| `skipWithoutPhone` | `false` | Skip places that list no phone number. |
| `language` | `en` | Language of names and categories, e.g. `de`, `ar`, `fr`. Use the language of your search. |
| `countryCode` | `us` | Country Google uses for regional results, e.g. `gb`, `ae`, `de`. |
| `maxConcurrency` | 3 | Searches run at once. |
| `proxyConfiguration` | off | Off by default and usually not needed. Turn on for very large runs if Google starts rate-limiting. |

`skipWithoutWebsite` still works: it is the same as `website` = only places with a website.

Examples from real runs:

- Map point: `{ "searchQueries": ["gyms"], "latitude": 25.2048, "longitude": 55.2708, "radiusKm": 3, "maxItems": 20 }`
- Brand branches: `{ "searchQueries": ["Starbucks"], "locations": ["Dubai"], "searchMatching": "only_includes", "maxItems": 20 }`
- Businesses without a website: `{ "searchQueries": ["roofers in Dallas TX"], "website": "withoutWebsite", "maxItems": 15 }`
- Google Maps search link: `{ "startUrls": [{ "url": "https://www.google.com/maps/search/pizza/@40.758,-73.9855,15z" }], "maxItems": 20 }`
- Place IDs: `{ "placeIds": ["ChIJG-gJw2vKRIYROWi2uwOp8QE", "ChIJ1S_Bov20RIYRe7MiR8tYawY", "ChIJlZDDXbK1RIYRXDHg0KomqhY"] }`

### Output

One row per place. Fields:

- **Identity:** `name`, `placeId`, `cid`, `fid`, `kgmid`, `url` (Google Maps link by CID), `googleMapsUrl`.
- **Location:** `address`, `street`, `city`, `neighborhood`, `postalCode`, `state`, `countryCode`, `latitude`, `longitude`, `timezone`.
- **Contact:** `phone`, `phoneInternational`, `website`, `domain`.
- **Business:** `category`, `categories`, `description`, `openingHours`, `additionalInfo` (Accessibility and other About items), `highlights` (e.g. "Women-owned"), `reservationUrl`, `bookingLinks`.
- **Ratings:** `rating`, `reviewsCount`, `reviewsDistribution` (one to five stars).
- **Status:** `permanentlyClosed`, `temporarilyClosed`.
- **Photos:** `imageUrl`, `imageUrls`.
- **Search:** `searchQuery`, `rank` (position in the search; in a whole-area sweep, the order the places were found).
- **Errors:** a failed search adds a row with `searchQuery` and `error`. Error rows are free.

A real row (shortened with `...`):

```json
{
  "name": "Best Dental Clinic Al Rigga",
  "category": "Dental clinic",
  "categories": ["Dental clinic", "Cosmetic dentist", "Dentist", "Orthodontist", "..."],
  "postalCode": null,
  "state": "Dubai",
  "countryCode": "AE",
  "phone": "+971 4 327 0888",
  "phoneInternational": "+97143270888",
  "website": "https://www.bestdentalclinic.ae/",
  "domain": "bestdentalclinic.ae",
  "rating": 4.8,
  "reviewsCount": 488,
  "reviewsDistribution": { "oneStar": 13, "twoStar": 2, "threeStar": 6, "fourStar": 15, "fiveStar": 452 },
  "permanentlyClosed": false,
  "temporarilyClosed": false,
  "openingHours": { "Thursday": "9 AM–10 PM", "Friday": "9 AM–10 PM", "...": "..." },
  "additionalInfo": { "Accessibility": ["Wheelchair accessible entrance", "..."] },
  "highlights": ["Identifies as women-owned"],
  "latitude": 25.2636017,
  "longitude": 55.3241072,
  "timezone": "Asia/Dubai",
  "placeId": "ChIJE9jF8gBdXz4RcJIuQMJXOdQ",
  "cid": "15403722168318503599",
  "fid": "0x3e5f5d00f2c5d813:0xd43957c2402e9270",
  "kgmid": "/g/11t4bmwnrl",
  "url": "https://www.google.com/maps?cid=15403722168318503599",
  "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJE9jF8gBdXz4RcJIuQMJXOdQ",
  "rank": 6,
  "searchQuery": "dentists in Dubai"
}
```

### Example tasks

Ready-made inputs you can open, change and run:

- [Every dentist in Dubai, whole-city sweep](https://apify.com/redfoxscout/google-maps-business-scraper/examples/every-dentist-in-dubai-whole-city)
- [Get restaurants in New York from Google Maps](https://apify.com/redfoxscout/google-maps-business-scraper/examples/restaurants-google-maps)
- [Find real estate agencies in London](https://apify.com/redfoxscout/google-maps-business-scraper/examples/real-estate-agents-google-maps)
- [Find plumbers in Chicago for lead generation](https://apify.com/redfoxscout/google-maps-business-scraper/examples/plumbers-google-maps-leads)
- [Get gyms and fitness centers in Los Angeles](https://apify.com/redfoxscout/google-maps-business-scraper/examples/gyms-google-maps)
- [Find law firms in Toronto](https://apify.com/redfoxscout/google-maps-business-scraper/examples/law-firms-google-maps)
- [Get coffee shops in Austin, Texas](https://apify.com/redfoxscout/google-maps-business-scraper/examples/coffee-shops-google-maps)

### Cover the whole area (every place, not one search)

Google Maps returns one list for each search, and that list runs out. In our test runs, a plain search for "restaurants in New York" returned 171 places and stopped, and "dentists in Dubai" returned 235. With **Cover the whole area** on, the same kind of search returned 1,000 places in about 7 minutes; we stopped the test there.

The area is the city named in the search or under Locations, the map view of a Google Maps link, or your own map point. It is split into map tiles of about 8 km, and a tile that still holds many places is split again. Each place is returned once, by its place ID, so places that appear in two tiles are not repeated or charged twice. Max results per search is the limit: the run stops there, and you pay only for the places returned. Large areas take minutes.

Input (real run, shortened with `...`):

```json
{ "searchQueries": ["dentists in Dubai"], "searchWholeArea": true, "maxItems": 20 }
```

One row from that run:

```json
{
  "name": "Best Dental Clinic Al Rigga",
  "category": "Dental clinic",
  "address": "Al Salmiya Building - Office 416 - Al Rigga Rd - Al Muraqqabat - Deira - Dubai - United Arab Emirates",
  "city": "Dubai - United Arab Emirates",
  "phone": "+971 4 327 0888",
  "website": "https://www.bestdentalclinic.ae/",
  "domain": "bestdentalclinic.ae",
  "rating": 4.8,
  "reviewsCount": 488,
  "rank": 6,
  "searchQuery": "dentists in Dubai"
}
```

### What this Actor does not do

It does not open `?cid=` links, collect review text, popular times, menus or prices, and it does not collect people's names or personal emails. It does not log in.

### How much does it cost?

$1 per 1,000 places, every field included.

- 100 places: about $0.10
- 1,000 places (for example, a whole-city sweep): about $1
- 10,000 places: about $10
- Duplicates, places removed by a filter and failed searches: free

Apify's free plan gives $5 of credit every month, enough for about 5,000 places.

### FAQ

**Is this legal?** It collects public business listings: names, addresses, phone numbers, websites, ratings and hours that businesses publish on Google Maps. It does not log in and does not collect reviewer profiles or personal data. You are responsible for using the data in line with the laws and terms that apply to you.

**Why do I get fewer places than the area has?** A plain search returns one Google list, and it runs out. Turn on **Cover the whole area**, or split the work with Locations or a map point.

**Why is the review count empty for some places?** Google sometimes sends a listing without its review count. The row keeps its other fields. Run again later for a fuller result. Places without a review count are skipped when Minimum number of reviews is set.

**Why is the phone empty for some places?** Not every business lists a phone number on Google Maps. Use "Only places with a phone number" to skip them.

**Why do place ID and link lookups have fewer fields?** They return the place's main details. Some fields, such as the review breakdown, can be empty.

**Can I get emails?** Google Maps does not show emails. Run the `website` column through the Website Contact Extractor.

### Related Actors

- [Website Contact Extractor](https://apify.com/redfoxscout/website-contact-extractor): emails, phones and social profiles from each place's website.
- [Google Maps Leads with Emails](https://apify.com/redfoxscout/google-maps-leads-with-emails): the same kind of Google Maps leads, with emails from their websites.
- [Tech Stack Detector](https://apify.com/redfoxscout/tech-stack-detector): which technologies each business website runs on.
- [Company Social Links Finder](https://apify.com/redfoxscout/company-social-links): official social profiles for any list of websites.

# Actor input Schema

## `searchQueries` (type: `array`):

Searches as you would type them in Google Maps, one per line, e.g. dentists in Dubai, or just dentists with a location below. Optional when you give Google Maps URLs or place IDs.

## `locations` (type: `array`):

Cities or areas. Every search is run in every location (<search> in <location>).

## `searchWholeArea` (type: `boolean`):

A normal Google Maps search ends after ~120-250 places. On: the area (location, "in <city>" or your map point) is split into map tiles, busy tiles are split again, and every matching place is returned once. Duplicates are free. Use with a higher max results.

## `startUrls` (type: `array`):

Google Maps search URLs (maps/search/...@lat,lng,zoom), place URLs, ?cid= links or maps.app.goo.gl short links.

## `placeIds` (type: `array`):

Google place IDs such as ChIJ1S_Bov20RIYRe7MiR8tYawY. One row per place.

## `language` (type: `string`):

Language of names and categories, e.g. en, de, ar, fr.

## `countryCode` (type: `string`):

Two-letter country code Google uses for regional results, e.g. us, gb, ae.

## `latitude` (type: `number`):

Search around a point instead of a named place, e.g. 25.2048. Use with longitude and radius.

## `longitude` (type: `number`):

e.g. 55.2708.

## `radiusKm` (type: `number`):

Size of the circle around the map point. Places outside it are left out. With Cover the whole area every place inside it is returned.

## `skipClosedPlaces` (type: `boolean`):

Leave out places Google marks as permanently or temporarily closed.

## `categoryFilterWords` (type: `array`):

Keep a place only if one of its Google categories contains one of these words, e.g. dentist, orthodontist.

## `searchMatching` (type: `string`):

Useful for brand searches (e.g. Starbucks): drop places Google adds that are not that business.

## `minRating` (type: `integer`):

Skip places rated below this. Places without a rating are skipped when this is set.

## `minReviews` (type: `integer`):

Skip places with fewer reviews.

## `website` (type: `string`):

Places without a website are prospects for web design and marketing agencies.

## `skipWithoutWebsite` (type: `boolean`):

Older switch, same as Website = Only places with a website.

## `skipWithoutPhone` (type: `boolean`):

Skip places that list no phone.

## `maxItems` (type: `integer`):

Stop each search after this many places. A normal search ends after ~120-250; with Cover the whole area use hundreds or thousands.

## `maxConcurrency` (type: `integer`):

How many searches run at once.

## `proxyConfiguration` (type: `object`):

Off by default and usually not needed. Turn on for very large sweeps if Google starts rate-limiting.

## Actor input object example

```json
{
  "searchQueries": [
    "coffee shops in Austin TX"
  ],
  "searchWholeArea": false,
  "language": "en",
  "countryCode": "us",
  "radiusKm": 5,
  "skipClosedPlaces": false,
  "searchMatching": "all",
  "website": "allPlaces",
  "skipWithoutWebsite": false,
  "skipWithoutPhone": false,
  "maxItems": 60,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "coffee shops in Austin TX"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("redfoxscout/google-maps-business-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "searchQueries": ["coffee shops in Austin TX"] }

# Run the Actor and wait for it to finish
run = client.actor("redfoxscout/google-maps-business-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "coffee shops in Austin TX"
  ]
}' |
apify call redfoxscout/google-maps-business-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,redfoxscout/google-maps-business-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/fYg44tZMEJ8JizkQD/builds/FGRpwbxSjrH829TxF/openapi.json
