# Google Maps Business Scraper | $1 per 1,000 (`datascraperes/actor-google-maps`) Actor

Scrape unique Google Maps business listings by city, region, or country. Export names, addresses, phones, websites, ratings, review counts, opening hours, photos, and coordinates. Fast, API-ready, and priced at $1 per 1,000 successful results.

- **URL**: https://apify.com/datascraperes/actor-google-maps.md
- **Developed by:** [DataScraperES](https://apify.com/datascraperes) (community)
- **Categories:** Lead generation, SEO tools, Business
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 unique business results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Google Maps Business Scraper | $1 per 1,000

Scrape unique Google Maps business listings from cities, regions, or whole
countries. Export business names, addresses, phone numbers, websites, ratings,
review counts, opening hours, photos, categories, and coordinates in a clean
dataset ready for lead generation, local SEO, market research, or automation.

**Price:** $0.001 per unique business successfully written to the dataset —
**$1.00 per 1,000 results**. There is no Actor-start fee.

No Google Places API key, OAuth setup, or external account is required.

### What this Actor does

Provide one or more geographic locations and one or more Google Maps search
queries. The Actor searches every requested query in every location, expands
coverage across the target area, filters geographic spillover, and writes
unique businesses to the default Apify dataset.

For example, these inputs:

- locations: `Madrid`, `Barcelona`
- queries: `dentists`, `orthodontists`

produce searches for both queries in both cities. If the same business appears
in multiple searches, it is written and billed only once because results are
deduplicated globally by Google Place ID.

### Key benefits

- **Global geographic targeting:** search cities, municipalities, regions,
  states, or countries.
- **Coverage beyond a single Google Maps search:** the target area is divided
  automatically into geographic sectors.
- **Strict area filtering:** businesses outside the resolved target boundary
  are excluded.
- **Unique results:** duplicate Place IDs found across sectors, queries, and
  locations are not written twice.
- **Simple pricing:** one chargeable event at $0.001 per unique dataset item.
- **Cost controls:** use `maxResults` and Apify's **Maximum cost per run**.
- **Structured output:** 24 documented fields per business.
- **Easy automation:** run from Apify Console, API, CLI, schedules, webhooks,
  Make, Zapier, or your own application.

### Best use cases

- Build local business prospect lists for sales and outreach.
- Discover companies by category in a city, region, or country.
- Compare market density, ratings, and review counts.
- Find business websites and public phone numbers.
- Enrich a CRM with Google Maps identifiers and location data.
- Create or maintain local business directories.
- Research competitors and branch coverage.
- Map retail, hospitality, healthcare, or service-business locations.
- Prepare location datasets for GIS and business intelligence tools.

This Actor returns Google Maps business data. It does not crawl business
websites for email addresses or social profiles, and it does not extract
individual Google reviews.

### Quick start

1. Open the Actor's **Input** tab.
2. Enter a location such as `Madrid`.
3. Enter a search query such as `dentists`.
4. Keep `countryCode` aligned with the location, for example `ES`.
5. Set **Max Results** to `20` for a small test.
6. Click **Start**.
7. Open the **Output** or **Dataset** tab to inspect and download the results.

Minimal input:

```json
{
  "locations": ["Madrid"],
  "queries": ["dentists"],
  "language": "es",
  "countryCode": "ES",
  "maxResults": 20
}
````

At the configured price, a completed 20-result run costs $0.02 in Actor event
charges.

### Input reference

| Field | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `locations` | Array of strings | Yes | — | Cities, regions, states, or countries to search. Use a country name for the widest coverage and highest potential number of results. |
| `queries` | Array of strings | Yes | — | Google Maps search terms. Every query runs in every location until the global result limit is reached. |
| `language` | String | Yes | `es` | Language used for Google Maps results. Choose one of 100 available languages. |
| `countryCode` | String | Yes | `ES` | Country used to disambiguate and constrain locations. Choose one of 100 available countries and markets. |
| `maxResults` | Integer | No | `1000` | Global maximum number of unique businesses written across the complete run. `0` means unlimited. |

#### Locations

Use clear geographic names that match `countryCode`:

```json
{
  "locations": ["Madrid", "Barcelona", "Valencia"],
  "countryCode": "ES"
}
```

Locations can have different geographic sizes:

- city: `Chicago`
- county: `Cook County`
- state or region: `California`
- country: `Singapore`

For the widest coverage and highest potential number of results, enter the
country name itself in `locations` and select its matching `countryCode`:

```json
{
  "locations": ["Spain"],
  "countryCode": "ES",
  "maxResults": 10000
}
```

This searches across the country instead of limiting discovery to one city or
region. Selecting `ES` without using `Spain` as the location does not turn a
city search into a country search. Country-wide runs usually take longer and
can cost more, while `maxResults` remains the global output and billing limit.

For ambiguous names, include the state or region in the location text, for
example `Springfield, Illinois`.

#### Queries

Queries work like searches a person would type into Google Maps:

```json
{
  "queries": [
    "Italian restaurants",
    "dental clinics",
    "coworking spaces"
  ]
}
```

Specific queries usually produce more relevant datasets than broad terms.
Related queries can improve discovery, but a business matched by several
queries is still stored only once.

#### Language

The input form provides a validated dropdown with 100 unique language options.
The most commonly used options appear first, followed by the extended list:

`af`, `am`, `ar`, `az`, `be`, `bg`, `bn`, `bs`, `ca`, `cs`, `cy`, `da`,
`de`, `el`, `en`, `es`, `et`, `eu`, `fa`, `fi`, `fil`, `fr`, `ga`, `gl`,
`gu`, `ha`, `he`, `hi`, `hr`, `hu`, `hy`, `id`, `ig`, `is`, `it`, `ja`,
`jv`, `ka`, `kk`, `km`, `kn`, `ko`, `ku`, `ky`, `lb`, `lo`, `lt`, `lv`,
`mg`, `mi`, `mk`, `ml`, `mn`, `mr`, `ms`, `mt`, `my`, `nb`, `ne`, `nl`,
`nn`, `no`, `ny`, `or`, `pa`, `pl`, `ps`, `pt`, `ro`, `ru`, `rw`, `sd`,
`si`, `sk`, `sl`, `sm`, `sn`, `so`, `sq`, `sr`, `st`, `su`, `sv`, `sw`,
`ta`, `te`, `tg`, `th`, `tk`, `tl`, `tr`, `tt`, `uk`, `ur`, `uz`, `vi`,
`xh`, `yo`, `zh`, and `zu`.

Language affects the text returned by Google Maps, including categories,
descriptions, and opening-day labels where available.

#### Country code

The input form provides a validated dropdown with 100 unique countries and
markets. Each option shows its name and two-letter ISO 3166-1 code, preventing
mistyped or unsupported values. Common examples include:

- `ES` — Spain
- `US` — United States
- `GB` — United Kingdom
- `BR` — Brazil
- `DE` — Germany
- `JP` — Japan
- `AU` — Australia

Available codes:

`AE`, `AM`, `AO`, `AR`, `AT`, `AU`, `AZ`, `BD`, `BE`, `BH`, `BO`, `BR`,
`BW`, `CA`, `CH`, `CI`, `CL`, `CM`, `CN`, `CO`, `CR`, `CU`, `CZ`, `DE`,
`DK`, `DO`, `DZ`, `EC`, `EG`, `ES`, `ET`, `FI`, `FR`, `GB`, `GE`, `GH`,
`GR`, `GT`, `HN`, `HR`, `HU`, `ID`, `IE`, `IL`, `IN`, `IQ`, `IT`, `JM`,
`JO`, `JP`, `KE`, `KR`, `KW`, `KZ`, `LB`, `LK`, `MA`, `MX`, `MY`, `MZ`,
`NA`, `NG`, `NI`, `NL`, `NO`, `NP`, `NZ`, `OM`, `PA`, `PE`, `PH`, `PK`,
`PL`, `PT`, `PY`, `QA`, `RO`, `RS`, `RU`, `RW`, `SA`, `SE`, `SG`, `SN`,
`SV`, `TH`, `TN`, `TR`, `TT`, `TZ`, `UA`, `UG`, `US`, `UY`, `UZ`, `VE`,
`VN`, `ZA`, `ZM`, and `ZW`.

The country code applies to every location in the run. Use separate runs when
searching locations in different countries.

#### Maximum results

`maxResults` is a global limit, not a per-query or per-location limit.
Processing stops after that many unique businesses have been successfully
written to the dataset.

If you provide three locations and four queries with `maxResults: 1000`, the
combined output from all 12 location-query combinations is capped at 1,000
unique businesses.

Use `0` only when you intentionally want the complete planned scan. For large
areas, also set an appropriate run timeout and **Maximum cost per run** in
Apify's run options.

### Input recipes

#### One category in one city

```json
{
  "locations": ["London"],
  "queries": ["accounting firms"],
  "language": "en",
  "countryCode": "GB",
  "maxResults": 500
}
```

#### Several related categories

```json
{
  "locations": ["Miami, Florida"],
  "queries": [
    "dentists",
    "orthodontists",
    "dental implants"
  ],
  "language": "en",
  "countryCode": "US",
  "maxResults": 2000
}
```

#### Region-wide market research

```json
{
  "locations": ["Andalusia"],
  "queries": [
    "hotels",
    "hostels",
    "holiday apartments"
  ],
  "language": "es",
  "countryCode": "ES",
  "maxResults": 10000
}
```

#### Country-scale scan

```json
{
  "locations": ["Singapore"],
  "queries": ["restaurants"],
  "language": "en",
  "countryCode": "SG",
  "maxResults": 0
}
```

Country and large-region scans can require a longer timeout. Start with a
capped test before running without a result limit.

### Output

Every accepted business is stored as one item in the default dataset. You can
inspect results as a table in Apify Console or export them as JSON, JSONL, CSV,
Excel, XML, or RSS.

#### Example result

```json
{
  "name": "Example Dental Clinic",
  "placeId": "ChIJEXAMPLE",
  "googleMapsUrl": "https://www.google.com/maps/place/?q=place_id:ChIJEXAMPLE",
  "address": "Calle de Ejemplo, 10",
  "city": "Madrid",
  "region": "Madrid",
  "postalCode": "28001",
  "countryCode": "ES",
  "phone": "910 000 000",
  "website": "https://example.com/",
  "avgRating": 4.7,
  "totalReviews": null,
  "priceRange": null,
  "tags": ["Dentista", "Clínica dental"],
  "description": "",
  "businessPhoto": "https://lh5.googleusercontent.com/.../s800/photo.jpg",
  "photoUrls": [
    "https://lh5.googleusercontent.com/.../s800/photo.jpg"
  ],
  "hours": [
    {
      "day": "lunes",
      "hours": "9:00–20:00",
      "open24Hour": 9,
      "close24Hour": 20
    }
  ],
  "lat": 40.4168,
  "long": -3.7038,
  "discoveryQuery": "dentists",
  "searchLocation": "Madrid",
  "searchCoordinates": "40.4200,-3.7000",
  "scrapeTimestamp": "2026-07-23T11:58:22.031656+02:00"
}
```

### Complete output field reference

| Field | Type | Observed presence | Description |
| --- | --- | ---: | --- |
| `name` | String | 100% | Business name displayed on Google Maps. Required for every accepted result. |
| `placeId` | String | 100% | Stable Google Maps Place ID used to deduplicate results within the run. Required. |
| `googleMapsUrl` | String | 100% | Direct Google Maps link generated from `placeId`. |
| `address` | String or null | 100% | Street address or the most complete formatted address available. |
| `city` | String or null | 100% | City, municipality, or locality extracted from the listing. |
| `region` | String or null | 100% | Region, state, province, or first-level administrative area. |
| `postalCode` | String or null | 99.70% | Postal or ZIP code. |
| `countryCode` | String or null | 100% | Two-letter ISO country code associated with the result. |
| `phone` | String or null | 97.75% | Public phone number shown on Google Maps. Formatting is returned as displayed and may not include an international prefix. |
| `website` | String or empty | 84.57% | Public website linked from the listing. Tracking redirects are removed when possible. |
| `avgRating` | Number or null | 97.83% | Average Google Maps rating, normally from 1.0 to 5.0. |
| `totalReviews` | Integer or null | 2.72% | Review-count value when present in the returned listing payload. Individual review text and reviewer data are not collected. |
| `priceRange` | String or null | 0% | Price-level text when exposed. It was not present in the measured sample. |
| `tags` | Array of strings | 100% | Business categories associated with the listing, in the selected language. |
| `description` | String or empty | 0% | Business description when exposed. It was empty in the measured sample. |
| `businessPhoto` | String or null | 91.19% | Main business photo URL, normalized to an 800-pixel Google image URL when available. |
| `photoUrls` | Array of strings | 91.19% | Unique photo URLs found for the business. An empty array means no photo URL was exposed. |
| `hours` | Array of objects | 94.37% | Displayed opening-hours entries returned for the listing. An empty array means hours were not exposed. |
| `lat` | Number | 100% | Latitude. A candidate without valid coordinates is not accepted. |
| `long` | Number | 100% | Longitude. A candidate without valid coordinates is not accepted. |
| `discoveryQuery` | String | 100% | First input query that added this unique business to the dataset. |
| `searchLocation` | String | 100% | Input location being processed when the business was first accepted. |
| `searchCoordinates` | String | 100% | Latitude and longitude of the search sector that discovered the business, formatted as `lat,lng`. |
| `scrapeTimestamp` | ISO 8601 string | 100% | Collection timestamp including its UTC offset. |

#### How to interpret field availability

Only `name` and `placeId` are contractual required fields. Other values depend
on the listing, business category, country, selected language, and the data
returned by Google Maps at collection time.

The percentages above are measured values, not guaranteed fill rates. They
come from 10,000 row observations collected on July 23, 2026 across ten
repeated 1,000-result runs for `dentistas` in Madrid:

- **100% observed:** identity, link, address components, categories,
  coordinates, discovery context, and timestamp
- **97-99.99% observed:** postal code, phone, and average rating
- **80-96.99% observed:** website, photos, and opening hours
- **below 5% observed:** total review count, price range, and description

This sample is useful for planning an integration, but it is not representative
of every category or country. For example, restaurants may expose price
information more often, while listings without an official website will
naturally leave `website` empty.

#### Missing-value conventions

The Actor does not invent, predict, or enrich missing Google Maps values:

- missing text can be `null` or an empty string `""`
- missing arrays such as `photoUrls` and `hours` are normally `[]`
- missing numeric values such as `avgRating` or `totalReviews` are `null`
- `0` is a valid number and should not automatically be treated as missing

When importing CSV or Excel exports, configure your destination to accept empty
cells for optional fields. When consuming JSON, check both `null` and empty
strings or arrays.

#### Opening-hours object

Each item inside `hours` can contain:

| Nested field | Type | Description |
| --- | --- | --- |
| `day` | String or null | Localized day label returned using the selected input language. |
| `hours` | String or null | Human-readable interval such as `10:00–20:00`. Use this value when minutes or split periods matter. |
| `open24Hour` | Integer or null | Opening-hour component in 24-hour format. |
| `close24Hour` | Integer or null | Closing-hour component in 24-hour format. |

Google Maps may return only the hours entries available in the current search
payload rather than a complete seven-day schedule. Do not assume seven items
will always be present.

#### Identity, discovery, and geographic fields

`placeId` identifies a Google Maps listing. It is the recommended key for
merging exports or comparing repeated runs. Different branches of the same
brand normally have different Place IDs and remain separate businesses.

`lat` and `long` describe the business itself. `searchCoordinates` describes
the search sector that discovered it; it is not a replacement for the
business coordinates. `discoveryQuery` and `searchLocation` explain why the
result is present in a multi-query or multi-location run.

### Pricing and billing

The Actor uses pay-per-event pricing with one billable event:

| Event | Price | When it is charged |
| --- | ---: | --- |
| `business-result` | $0.001 | Once for each unique business successfully written to the default dataset |

There is no Actor-start charge and no second dataset-item charge.

You are not charged a `business-result` event for:

- duplicate Place IDs found again in another sector or query
- businesses filtered out because they are outside the target area
- failed search requests
- empty search responses
- candidates that are not written to the dataset

Example costs:

| Unique results | Actor event charge |
| ---: | ---: |
| 20 | $0.02 |
| 100 | $0.10 |
| 1,000 | $1.00 |
| 5,000 | $5.00 |
| 10,000 | $10.00 |
| 50,000 | $50.00 |

#### Control your maximum cost

Use both available safeguards:

1. Set `maxResults` to the largest dataset you want.
2. Set **Maximum cost per run** in Apify's run options.

The Actor checks the remaining pay-per-event capacity before starting
additional work and stops gracefully when the configured charge limit is
reached.

### Coverage and deduplication

#### Geographic coverage

The Actor resolves each requested location, plans an area-appropriate search
grid, and filters returned coordinates against the target boundary. This
reduces the common Google Maps behavior of returning nearby businesses outside
the requested city or region.

Where an exact geographic boundary is available, point-in-polygon filtering is
used. Otherwise, the resolved bounding area is used. Results with missing or
invalid coordinates are excluded because their location cannot be verified.

#### Unique business rules

Uniqueness is based on `placeId` across the entire run:

- the same business found in several grid sectors is stored once
- the same business found by several queries is stored once
- the same business found through overlapping locations is stored once
- separate branches with different Place IDs remain separate results

When a result matches more than one query, `discoveryQuery` records the query
that first added it to the dataset.

#### Coverage expectations

Google Maps results are dynamic and can vary with query wording, language,
location, availability, and upstream changes. No scraper can guarantee a
permanent or exhaustive copy of every business. For broader discovery:

- use the country name as the location when you want the widest geographic
  coverage and the highest potential result count
- combine several specific, related queries
- scan the correct geographic level
- use a sufficient timeout
- compare repeated runs when monitoring changes over time

### Performance and run timeout

The default Actor memory is 512 MB and the default timeout is 300 seconds.
Small capped runs usually finish well within that window. Larger grids may
need more time.

| Workload | Suggested timeout |
| --- | --- |
| Small test, up to 100 results | 5 minutes |
| City scan, up to 1,000 results | 5-10 minutes |
| Large city or region, up to 10,000 results | 15-30 minutes |
| Unlimited region or country scan | 30-60 minutes or more |

Actual duration depends on the target area's size, number of queries, number of
locations, result cap, and Google Maps response conditions.

If a run reaches its timeout, increase the timeout in **Run options** and start
a new run. Do not use unlimited mode for a large area until a capped test has
confirmed the expected coverage and cost.

### Run through the API

Actor identifier:

```text
datascraperes/actor-google-maps
```

#### Synchronous HTTP request

This endpoint waits for the run and returns the default dataset items:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/datascraperes~actor-google-maps/run-sync-get-dataset-items?timeout=300" \
  -H "Authorization: Bearer YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "locations": ["Madrid"],
    "queries": ["dentists"],
    "language": "es",
    "countryCode": "ES",
    "maxResults": 20
  }'
```

For large runs, start the Actor asynchronously and poll the run status instead
of waiting on a synchronous HTTP connection.

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("datascraperes/actor-google-maps").call(
    run_input={
        "locations": ["Madrid"],
        "queries": ["dentists"],
        "language": "es",
        "countryCode": "ES",
        "maxResults": 20,
    }
)

items = client.dataset(run["defaultDatasetId"]).list_items().items
print(f"Downloaded {len(items)} unique businesses")
```

#### JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });

const run = await client.actor('datascraperes/actor-google-maps').call({
    locations: ['Madrid'],
    queries: ['dentists'],
    language: 'es',
    countryCode: 'ES',
    maxResults: 20,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(`Downloaded ${items.length} unique businesses`);
```

#### Apify CLI

Save the input as `input.json`, then run:

```bash
apify actors call datascraperes/actor-google-maps \
  --input-file input.json \
  --output-dataset
```

### Automation and integrations

Because results are stored in the default Apify dataset, you can:

- schedule recurring runs in Apify Console
- trigger workflows through webhooks
- download JSON, CSV, or Excel files
- connect the Actor to Make or Zapier
- import results into Google Sheets, Airtable, a CRM, or a database
- use the Actor from an AI agent through Apify integrations
- combine it with another Actor that enriches the returned websites

When scheduling repeated runs, each run creates its own dataset by default.
Use `placeId` as the stable key when comparing or merging results across runs.

### Troubleshooting

#### The location cannot be resolved

- Check the spelling.
- Ensure `countryCode` matches the location.
- Add a state or region to ambiguous names.
- Split locations from different countries into separate runs.

If none of the requested locations can be planned, the Actor fails explicitly
instead of reporting a misleading successful empty run.

#### The run succeeded but returned no businesses

- Try a broader or more common query.
- Verify the selected language and country code.
- Test the same search manually in Google Maps.
- Use a city-level location before attempting a very small district.

An empty but successfully processed search is not billed as a business result.

#### Fewer businesses were returned than expected

- Check whether `maxResults` or **Maximum cost per run** was reached.
- Increase the run timeout for large areas.
- Add related queries because Google Maps ranks different businesses for
  different search terms.
- Remember that only businesses with a valid Place ID, name, and coordinates
  inside the target area are accepted.

#### A business has no phone number or website

Google Maps does not expose every field for every listing. Missing optional
values can be returned as `null`, an empty string, or an empty array; the Actor
does not invent or infer them. See **How to interpret field availability** for
measured fill rates and handling guidance.

#### The same brand appears several times

Different physical branches normally have different Google Place IDs and are
therefore valid separate results. Exact Place ID duplicates are removed.

#### The run stopped at a specific number of results

The run reached `maxResults` or the Apify maximum-charge limit. This is a
successful controlled stop, not a scraper error.

#### A large scan timed out

Increase the timeout in Apify run options, reduce the number of
location-query combinations, or split the workload into several runs.

### FAQ

#### Do I need a Google Maps or Google Places API key?

No. The Actor does not require a Google API key or Google Cloud project.

#### Does it work worldwide?

Yes. Use a valid two-letter country code and a location name that can be
resolved in that country. To maximize potential coverage, use the country name
itself as the location. Large or complex areas can require longer runs and may
cost more than a city search.

#### Are results unique?

Yes, within each run. Results are deduplicated by Google Place ID across all
queries, sectors, and locations.

#### Are duplicate discoveries charged?

No. The `business-result` event is charged only when a unique item is
successfully written to the default dataset.

#### Does it extract email addresses or social profiles?

No. It returns the public website and phone number shown by Google Maps. You
can pass the website field to a separate enrichment workflow if needed.

#### Does it extract individual reviews?

No. It returns `avgRating` and `totalReviews`, not individual review text or
reviewer profiles.

#### Can I search several countries in one run?

The public input uses one shared `countryCode`, so locations from different
countries should be placed in separate runs.

#### Can I use it as an API?

Yes. You can start runs and retrieve datasets using the Apify REST API, Python
client, JavaScript client, or CLI.

#### Can I schedule recurring Google Maps exports?

Yes. Use Apify schedules and optionally attach a webhook or integration to
process the dataset after each successful run.

#### Is a result guaranteed to have every field?

No. `name` and `placeId` are required. All other fields depend on the
information available for that business on Google Maps.

### Responsible use

Use this Actor only for lawful purposes and in accordance with applicable
terms, privacy rules, database rights, and data-protection laws. Business data
can include personal data in some jurisdictions. You are responsible for
determining the legal basis for collecting, storing, combining, and contacting
people using the output.

Avoid excessive collection, secure downloaded datasets, keep data only as long
as necessary, and honor valid deletion or opt-out requests where applicable.

### Support

If you encounter a reproducible problem, open an issue from the Actor's Apify
page and include:

- the run ID
- a sanitized copy of the input
- the expected result
- the observed result
- whether the issue occurs consistently

Do not include API tokens, credentials, or confidential customer data.

# Actor input Schema

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

Cities, regions, or countries to search, one per line. For the widest coverage and highest potential number of results, enter the country name itself (for example Spain) and select its matching country code. Country-wide searches usually take longer and can cost more; maxResults remains the global limit.

## `queries` (type: `array`):

Search terms to use on Google Maps (e.g. restaurants, dentists, hotels). Each query runs in every location.

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

Language Google Maps uses to return results. Choose from 100 commonly used languages. Applied to all locations in this run.

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

Country used to disambiguate and constrain every location. Choose from 100 commonly searched countries and markets.

## `maxResults` (type: `integer`):

Maximum number of unique businesses written to the dataset across all locations and queries. Each successful result costs $0.001. Set to 0 for unlimited and use Apify's Maximum cost per run option as a safety cap.

## Actor input object example

```json
{
  "locations": [
    "Madrid"
  ],
  "queries": [
    "restaurants"
  ],
  "language": "es",
  "countryCode": "ES",
  "maxResults": 20
}
```

# Actor output Schema

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

Unique Google Maps business listings, deduplicated by Place ID.

# 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 = {
    "locations": [
        "Madrid"
    ],
    "queries": [
        "restaurants"
    ],
    "language": "es",
    "countryCode": "ES",
    "maxResults": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascraperes/actor-google-maps").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 = {
    "locations": ["Madrid"],
    "queries": ["restaurants"],
    "language": "es",
    "countryCode": "ES",
    "maxResults": 20,
}

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

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

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

```

## CLI example

```bash
echo '{
  "locations": [
    "Madrid"
  ],
  "queries": [
    "restaurants"
  ],
  "language": "es",
  "countryCode": "ES",
  "maxResults": 20
}' |
apify call datascraperes/actor-google-maps --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=datascraperes/actor-google-maps",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Google Maps Business Scraper | $1 per 1,000",
        "description": "Scrape unique Google Maps business listings by city, region, or country. Export names, addresses, phones, websites, ratings, review counts, opening hours, photos, and coordinates. Fast, API-ready, and priced at $1 per 1,000 successful results.",
        "version": "1.0",
        "x-build-id": "Ulnx1iQoeFYz1XO3Q"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/datascraperes~actor-google-maps/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-datascraperes-actor-google-maps",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/datascraperes~actor-google-maps/runs": {
            "post": {
                "operationId": "runs-sync-datascraperes-actor-google-maps",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/datascraperes~actor-google-maps/run-sync": {
            "post": {
                "operationId": "run-sync-datascraperes-actor-google-maps",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "locations",
                    "queries",
                    "language",
                    "countryCode"
                ],
                "properties": {
                    "locations": {
                        "title": "Locations",
                        "minItems": 1,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Cities, regions, or countries to search, one per line. For the widest coverage and highest potential number of results, enter the country name itself (for example Spain) and select its matching country code. Country-wide searches usually take longer and can cost more; maxResults remains the global limit.",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "queries": {
                        "title": "Search Queries",
                        "minItems": 1,
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Search terms to use on Google Maps (e.g. restaurants, dentists, hotels). Each query runs in every location.",
                        "items": {
                            "type": "string",
                            "minLength": 1
                        }
                    },
                    "language": {
                        "title": "Language",
                        "enum": [
                            "es",
                            "en",
                            "pt",
                            "fr",
                            "de",
                            "it",
                            "zh",
                            "ja",
                            "ko",
                            "hi",
                            "ar",
                            "ru",
                            "id",
                            "tr",
                            "nl",
                            "pl",
                            "vi",
                            "th",
                            "uk",
                            "he",
                            "af",
                            "am",
                            "az",
                            "be",
                            "bg",
                            "bn",
                            "bs",
                            "ca",
                            "cs",
                            "cy",
                            "da",
                            "el",
                            "et",
                            "eu",
                            "fa",
                            "fi",
                            "fil",
                            "ga",
                            "gl",
                            "gu",
                            "ha",
                            "hr",
                            "hu",
                            "hy",
                            "ig",
                            "is",
                            "jv",
                            "ka",
                            "kk",
                            "km",
                            "kn",
                            "ku",
                            "ky",
                            "lb",
                            "lo",
                            "lt",
                            "lv",
                            "mg",
                            "mi",
                            "mk",
                            "ml",
                            "mn",
                            "mr",
                            "ms",
                            "mt",
                            "my",
                            "nb",
                            "ne",
                            "nn",
                            "no",
                            "ny",
                            "or",
                            "pa",
                            "ps",
                            "ro",
                            "rw",
                            "sd",
                            "si",
                            "sk",
                            "sl",
                            "sm",
                            "sn",
                            "so",
                            "sq",
                            "sr",
                            "st",
                            "su",
                            "sv",
                            "sw",
                            "ta",
                            "te",
                            "tg",
                            "tk",
                            "tl",
                            "tt",
                            "ur",
                            "uz",
                            "xh",
                            "yo",
                            "zu"
                        ],
                        "type": "string",
                        "description": "Language Google Maps uses to return results. Choose from 100 commonly used languages. Applied to all locations in this run.",
                        "default": "es"
                    },
                    "countryCode": {
                        "title": "Country code",
                        "enum": [
                            "ES",
                            "US",
                            "GB",
                            "DE",
                            "FR",
                            "IT",
                            "PT",
                            "BR",
                            "MX",
                            "CA",
                            "AU",
                            "IN",
                            "JP",
                            "CN",
                            "KR",
                            "ID",
                            "NL",
                            "PL",
                            "TR",
                            "SA",
                            "AE",
                            "CH",
                            "AT",
                            "BE",
                            "SE",
                            "NO",
                            "DK",
                            "FI",
                            "IE",
                            "CZ",
                            "RO",
                            "GR",
                            "HU",
                            "UA",
                            "RU",
                            "ZA",
                            "EG",
                            "NG",
                            "KE",
                            "MA",
                            "DZ",
                            "GH",
                            "TN",
                            "ET",
                            "TZ",
                            "UG",
                            "SN",
                            "CI",
                            "CM",
                            "AO",
                            "MZ",
                            "ZM",
                            "ZW",
                            "BW",
                            "NA",
                            "RW",
                            "IL",
                            "JO",
                            "LB",
                            "QA",
                            "KW",
                            "OM",
                            "BH",
                            "IQ",
                            "PK",
                            "BD",
                            "LK",
                            "NP",
                            "TH",
                            "VN",
                            "MY",
                            "SG",
                            "PH",
                            "NZ",
                            "AR",
                            "CL",
                            "CO",
                            "PE",
                            "VE",
                            "EC",
                            "UY",
                            "PY",
                            "BO",
                            "CR",
                            "PA",
                            "GT",
                            "DO",
                            "HN",
                            "SV",
                            "NI",
                            "JM",
                            "TT",
                            "CU",
                            "KZ",
                            "UZ",
                            "AZ",
                            "GE",
                            "AM",
                            "RS",
                            "HR"
                        ],
                        "type": "string",
                        "description": "Country used to disambiguate and constrain every location. Choose from 100 commonly searched countries and markets.",
                        "default": "ES"
                    },
                    "maxResults": {
                        "title": "Max Results",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum number of unique businesses written to the dataset across all locations and queries. Each successful result costs $0.001. Set to 0 for unlimited and use Apify's Maximum cost per run option as a safety cap.",
                        "default": 1000
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
