# Google Maps Scraper (`dami_studio/google-maps-scraper`) Actor

Google Maps scraper API for places from a search: name, category, address, star rating, review count, GPS coordinates and Google's place IDs, one row per place. Add place links for their newest reviews. A town Google can't find gets a free row, not places from elsewhere. $0.27 per 1,000 rows.

- **URL**: https://apify.com/dami_studio/google-maps-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Lead generation, Automation, Integrations
- **Features:** Limited permissions
- **Stats:** 49 total users, 9 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.26 / 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

**Google Maps scraper for the searches you would type into Google Maps, one row per place**: name, category,
address, phone, website, star rating, coordinates and Google's own identifiers. Hand it place links
instead and it reads the newest reviews on each one.

The awkward bit first. Phone and website are empty when the business never listed them. There are no e-mail addresses.

| | |
|---|---|
| **Input** | Google Maps searches with the place in the text, copied search links, or place links to read reviews from |
| **Output** | One row per place: phone, website, full address, categories, opening hours, Google's place ID. One row per review when you ask for reviews |
| **Ceiling** | 500 places per search, 500 reviews per place |
| **Speed** | About 30 seconds for one search of 50 to 60 places. Ten searches of 5 places took 80 seconds |
| **Account needed** | None, and no Google API key |
| **Price** | $0.27 per 1,000 rows on the free plan, down to $0.264 on Business. The free plan's $5 a month covers about 18,000. Each search after the first that finds places adds $0.0025 on every plan |

### 🔍 What Google Maps Scraper does

**Search.** Give it searches with the location in the text, like `coffee in Brooklyn`, and it scrolls
the results feed until it reaches your limit or the feed runs dry. Fill in `city` or `county` and
every search runs there instead; `locations` runs every search in each of several places.

**Filters.** Optional add-ons leave out places under a star rating, with or without a website,
outside your categories, outside the area you named, or permanently closed.

**Place links.** Paste place links or `ChIJ…` place IDs and you get their place rows, with the same fields as a search row.

**Reviews.** Give it place links and it returns each place's newest reviews: who wrote it, the stars,
the text, Google's relative date, the owner's reply and any photos. Tick `includeReviews` and a
search collects reviews for every place it found.

**It checks where Google searched.** A misspelt town
gets a free `BAD_INPUT` row instead of a page of coffee shops two states away.

### 📋 What data you get from each Google Maps place

| What you get | Field |
|---|---|
| Name and category, as the card prints them | `name`, `category` |
| Street address | `address` |
| Star rating and number of reviews | `rating`, `reviewCount` |
| Coordinates | `lat`, `lng` |
| Google's feature id and the numeric id | `placeId`, `cid` |
| The full place link, ready for a review run | `placeUrl` |
| Phone and website, when the business has given them to Google | `phone`, `website` |
| The search that found the place | `searchQuery` |
| Google's place ID and knowledge-graph id | `googlePlaceId`, `kgmid` |
| Position in Google's list | `rank` |
| Every category, and a code that reads the same in every language | `categories`, `categoryCode` |
| The address in one line and in parts | `fullAddress`, `street`, `neighborhood`, `city`, `postalCode`, `state`, `countryCode` |
| Plus code and time zone | `plusCode`, `timeZone` |
| Opening hours for the week, and whether it is open now | `openingHours`, `openStatus` |
| Closed for good, ads, businesses with no street address | `permanentlyClosed`, `sponsored`, `serviceArea` |
| Phone with the country code, and digits only | `phoneInternational`, `phoneDigits` |
| Website domain and "Book online" links | `websiteDomain`, `bookingLinks` |
| Accessibility, Google's short description, price band | `accessibility`, `description`, `priceLevel` |
| Photo count and the main photo's link | `photoCount`, `mainPhotoUrl` |
| The Maps link searched, the language and when the row was read | `searchUrl`, `language`, `scrapedAt` |
| Ordering services, an optional add-on | `orderLinks` |
| With place details, an optional add-on: the words reviewers repeat, places inside it, the owner's description | `reviewTopics`, `placesInside`, `ownerDescription` |
| The place link or ID a place row came from | `placeLink` |
| With legal-notice details, an optional add-on for German, Austrian and Swiss websites: company name, the directors or owners named, VAT id, register number and court | `legalNotice` |
| Per photo, when asked for: the link, its size and when it was posted | `photoId`, `mediaType`, `photoUrl`, `width`, `height`, `uploadedAt` |
| Per review: the reviewer, stars, text, relative date, owner reply and photos | `reviewerName`, `rating`, `text`, `relativeDate`, `ownerReply`, `photoUrls` |
| Per review: the exact date, language, translation, reply date and link | `publishedAt`, `language`, `textTranslated`, `originalText`, `ownerReplyRelativeDate`, `reviewUrl` |
| Per review, when asked for: the reviewer's profile | `reviewerUrl`, `reviewerPhotoUrl`, `reviewerReviewsCount`, `reviewerPhotosCount`, `isLocalGuide` |
| A stable id per review | `reviewId` |

### ▶️ How to scrape Google Maps places

1. Open [Google Maps Scraper](https://apify.com/dami_studio/google-maps-scraper) and click **Try for
   free**.
2. Put your searches into **Search queries**, with the location in the text. Delete the example
   first.
3. Set **Max places per query**. Start around 10 to see what the rows look like.
4. For reviews, paste place links into **Google Maps place URLs for reviews**, or tick **Include
   reviews for search results**, then click **Start**.
5. Download the dataset as JSON, CSV or Excel, or read it from the Apify API.

Start it empty and you get one labelled sample row, not charged.

### 💰 How much does it cost to scrape Google Maps?

**$0.27 per 1,000 rows.** Paid plans: Starter $0.268, Scale $0.266, Business $0.264. On the free plan, the $5 Apify
gives you each month covers about 18,000 rows.

| Searches | Search charge, the same on every plan |
|---|---|
| The first search in a run that finds places | none |
| Each later search that finds at least one place | $0.0025 |
| A search that brings back no places, whatever the reason | none |
| Place links and review links | none, they are not searches |

| Order online links, an optional add-on | Charge, the same on every plan |
|---|---|
| A place from a search whose check finished, with or without ordering links | $0.0017 |
| A check that did not finish | none |
| Place links and review links | none, they are not checked |

Tick it for restaurants. A place with no ordering links, like a dentist, still counts as checked.

A review row counts the same as a place row. With **Include reviews** on, a 60-place search at the
default of 50 reviews a place comes to 3,060 rows, so lower `maxReviewsPerPlace` if a few are enough.

Sample rows, diagnostic rows, a search that finds nothing, a place with no reviews and a search
refused as `BAD_INPUT` are all free.

### 📥 What you give it

```json
{
  "searchQueries": ["coffee in Brooklyn", "bakeries in Williamsburg"],
  "maxItems": 60,
  "includeReviews": false,
  "language": "en"
}
```

| Field | Default | What it is |
|---|---|---|
| `searchQueries` | none, the box starts at `coffee in Brooklyn` | Searches with the place in the text, like `dentists near Eiffel Tower`, or search links copied from Google Maps, which run at the part of the map they show. |
| `searchQuery` | none | One search instead of a list. Read only when `searchQueries` is empty, and that list starts prefilled, so clear it first. |
| `reviewUrls` | none | Place links to read reviews from. `placeUrls` is an alias for the same list. |
| `placeUrls` | none | The same as `reviewUrls`, merged with it. |
| `maxItems` | `60` | Places per search, up to 500. |
| `maxReviewsPerPlace` | `50` | Reviews per place, up to 5,000. |
| `includeReviews` | off | After a search, also collect the newest reviews of every place found, up to `maxReviewsPerPlace` each. |
| `includeOwnerReplies` | on | Include the owner's visible reply on a review row. |
| `reviewsSort` | `newest` | `newest`, `mostRelevant`, `highest` or `lowest`. |
| `reviewsSince` | none | Only reviews newer than a date like `2026-09-01`, or a span like `8 days`. Newest order only. Needs a paid Apify plan. |
| `reviewKeywords` | none | Optional add-on. Only reviews whose text, or Google's translation of it, holds one of these words. With rare words a place can stop early, with a free `PARTIAL` row. Needs a paid Apify plan. |
| `includeReviewerDetails` | off | Adds the reviewer's profile link, photo, counts and Local Guide flag. |
| `skipReviewerNames` | off | Review rows without the reviewer's name. |
| `state` | none | Added to `city` and `county`, like `TX`. |
| `postalCode` | none | Runs every search in this postal code. |
| `locations` | none | Several places, like `Austin, TX` and `Denver, CO`: every search runs in each. Up to 50 places and 200 searches. `city` and the fields above are then not used. |
| `minRating` | `any` | Optional add-on. `3`, `3.5`, `4` or `4.5` stars and up. Unrated places are left out too. Needs a paid Apify plan. |
| `websiteFilter` | `allPlaces` | Optional add-on. `withWebsite` or `withoutWebsite`. Needs a paid Apify plan. |
| `categoryFilterWords` | none | Optional add-on. Keeps places whose categories hold one of these words. Needs a paid Apify plan. |
| `nameMatch` | `all` | Optional add-on. `contains` or `exact`: the name against your search without its place. Needs a paid Apify plan. |
| `onlyInsideArea` | off | Optional add-on. Leaves out places outside the city, county, state, postal code or location you named. Needs a paid Apify plan. |
| `skipClosed` | off | Optional add-on. Leaves out places Google marks permanently closed. Needs a paid Apify plan. |
| `includeOrderLinks` | off | Optional add-on, charged per place checked. The ordering services Google lists for each place a search finds. Not for place links. |
| `fields` | none | Keep only these fields in each row, like `name` and `phone`. |
| `placeLinks` | none | Optional add-on. Place links, `?cid=` links, short links or `ChIJ…` place IDs: one place row each. Needs a paid Apify plan. |
| `includePlaceDetails` | off | Optional add-on. Adds `reviewTopics`, `placesInside` and `ownerDescription`. Needs a paid Apify plan. |
| `includeLegalNotice` | off | Optional add-on. For a German, Austrian or Swiss website, the company details from its legal notice (Impressum), never an e-mail or phone. Needs a paid Apify plan. |
| `maxPhotosPerPlace` | `0` | Photo links per place, one `photo` row each, links only, up to 10. Google sends a handful with each place (3 or 4 seen), not the whole gallery. Needs a paid Apify plan. |
| `language` | `en` | The language Google should answer in. Any code Google takes works. |
| `countryCode` | none | Two-letter country, like `GB` or `DE`. Leave it empty unless you need one country's view of a search. |
| `city` | none | Runs every search in this city, so `coffee` becomes `coffee in Austin, TX`. Add the state or country when the name is common, and leave the place out of the searches. |
| `county` | none | The same for a county, like `Travis County, TX`. Works on its own or with `city`. For a search that goes straight to one business, fill in `city` too. |
| `notionConnector` | none | Optional. Write each place into your Notion when the run finishes. |
| `notionParentId` | none | Optional. The Notion data source to write into. |
| `proxyConfiguration` | leave it alone | Optional. Your own servers, used exactly as given. |

### 📤 What you get back

A real place row from a run on 25 October 2026, trimmed: the long link cut, two of the seven days shown, some
fields left out:

```json
{
  "ok": true,
  "type": "place",
  "searchQuery": "coffee in Brooklyn",
  "name": "Moka & Co",
  "category": "Coffee shop",
  "address": "725 Fulton St",
  "rating": 4.7,
  "reviewCount": 1524,
  "phone": "(347) 689-2303",
  "website": "https://mokanco.com/fort-greene/",
  "lat": 40.6872946,
  "lng": -73.9762997,
  "placeId": "0x89c25bd0cf1340c9:0x2dff5312c14e5a81",
  "cid": "3314459190785628801",
  "placeUrl": "https://www.google.com/maps/place/Moka+%26+Co/data=!4m7!3m6!1s0x89c25bd0cf1340c9...",
  "rank": 1,
  "googlePlaceId": "ChIJyUATz9BbwokRgVpOwRJT_y0",
  "kgmid": "/g/11wndpb1kr",
  "categories": ["Coffee shop"],
  "fullAddress": "725 Fulton St, Brooklyn, NY 11217",
  "neighborhood": "Fort Greene",
  "city": "Brooklyn",
  "postalCode": "11217",
  "state": "New York",
  "countryCode": "US",
  "plusCode": "87G8M2PF+WF",
  "timeZone": "America/New_York",
  "openStatus": "Open · Closes 11 PM",
  "openingHours": [{ "day": "Saturday", "hours": "8 AM–11 PM" }, { "day": "Sunday", "hours": "8 AM–9 PM" }],
  "phoneDigits": "+13476892303",
  "websiteDomain": "mokanco.com",
  "accessibility": ["Wheelchair accessible entrance", "Wheelchair accessible seating"],
  "photoCount": 525,
  "sponsored": false
}
```

| Field | How to read it |
|---|---|
| `type` | `place` or `review`. Both kinds land in the same dataset. |
| `placeId` | Google's hex feature id, the `0x…:0x…` form. The `ChIJ…` place ID other Google tools take is `googlePlaceId`. |
| `cid` | The numeric id, taken from the second half of `placeId`. Both are always filled. |
| `phone` | Written the way the country writes it, without the country code: `(512) 717-3147` in Austin, `030 2833530` in Berlin. `null` when the business gave Google no number. |
| `website` | The link the business gave Google, tracking tags included. `null` when there is none. |
| `reviewCount` | Present on about three rows in four. `null` when Google leaves the count off the card, which happened to this same place on another run that day. |
| `placeUrl` | The full link with its `data=` segment. Keep it whole: that segment is what a review run needs. |
| Review rows | `placeId`, `placeName`, `placeUrl`, `reviewId`, `reviewerName`, `rating`, `relativeDate`, `text`, `ownerReply`, `photoUrls`. `placeId` and `placeName` are filled on reviews from a search and empty on reviews from a link. |
| `relativeDate` | Google's own wording, like `3 months ago` or `Edited 2 weeks ago`. The exact time is `publishedAt`. |
| `openingHours` | The week as Google lists it, starting today, as `{ day, hours }`. `null` when the business gave no hours. `openStatus` is the line Google shows at the minute of the run, like `Open · Closes 11 PM`. |
| `rank` | The place's position in Google's list for that search. Google ranks from where the map sits, so it moves between runs. |
| `permanentlyClosed` | `true` when Google marks the place closed for good. |
| `sponsored` | `true` on an ad card. Ads are kept and charged like any other place unless you filter them out yourself. |
| `orderLinks` | With `includeOrderLinks`, the ordering services Google lists, each as `{ provider, url }`. `[]` when it lists none. `null` when the check did not finish or the row came from a place link, and then it is not charged. Run the search again to fill in a check that did not finish. |
| `serviceArea` | `true` for a business with no street address, like a mobile plumber; its coordinates are only roughly where it works. |
| `priceLevel` | The price band the card prints, like `$10–20` or `20–30 €`. Empty when the card prints none. |
| `plusCode` | The global plus code, worked out from the coordinates. Google Maps shows a shorter local form with the town. |
| `text` on a review | `null` when the reviewer left stars and no words. |
| `photoUrls` | Photos attached to the review, up to 10. |

### 🧾 Reading the output

Three kinds of row can land in your dataset.

| Row | How to spot it | Charged |
|---|---|---|
| A place or a review | `ok: true` and `type` of `place` or `review` | yes |
| A photo link | `ok: true` and `type: "photo"` | yes |
| The sample row | `_sample: true` and `type: "sample"` | no |
| A diagnostic | `ok: false` and an `errorCode` | no |

Filter on `ok` being `true` and `_sample` being absent to keep only real rows.

| Code | What it means |
|---|---|
| `NO_RESULTS` | That search returned nothing usable, went straight to one business outside the place you named, or no place matched your filters. It also covers a place page that would not load, so a re-run is worth one try. |
| `NOT_SERVED` | This request was not served this run. Re-run it later. Runs before 13 October 2026 wrote `BLOCKED` here. |
| `NETWORK` | Google was unreachable or answered badly. |
| `BAD_INPUT` | Google Maps could not find the place you named, or found only the wider area around it, like the state beside a misspelt town. Checked in `city`, `county`, `state`, `postalCode` and `locations`, after "in" or "near" in a search, and after "à", "en", "près de" or "cerca de" when the place starts with a capital letter. Nothing from that search was charged. With `city` or `county`, a first search that fails stops the run; with `locations`, that place is skipped. Also an option the run cannot use, like a date it cannot read, before anything is searched. |
| `ORDER_LINKS_NOT_YET` | Order online links could not run this time, so nothing was searched or charged. Run it again, or run it without them. |
| `OPTION_UNAVAILABLE` | An add-on could not run this time, so the run stopped before searching and nothing was charged. Run it again without it. |
| `PARTIAL` | A filter or add-on stopped early: few reviews held your words, few places matched your filters, or an add-on ran out of room on this run. The rows before it are complete, and only they were charged. |
| `OPTION_OFF` | A filter or add-on that needs a paid Apify plan did not run. Nothing was read or charged for it, and the rest of the run went ahead. |
| `CHARGE_LIMIT` | The run's maximum cost was too low to cover a single row, with its check if you asked for order links, so it stopped before starting. |
| `COST_LIMIT` | The run reached the maximum cost you set and stopped there. The places and reviews before this row are complete and charged. When some of your searches were not run, the row says how many. Raise the maximum cost to get more. |
| `TIME_LIMIT` | The run got close to its time limit and stopped on its own. The places and reviews delivered before that are complete and charged. Give the run more time, or ask for fewer results, to get the rest. If nothing had come back yet, the run still ends as succeeded, with an amber status message. |
| `UNEXPECTED_ERROR` | The run stopped early on an unexpected error. The results before this row are kept. |

A diagnostic row never fails the run, `TIME_LIMIT` included: a run the time limit stopped before anything came back still ends as succeeded, with an amber status message. Without `city` or
`county`, one bad search never stops the others.

### 💡 What people use it for

- Building a list of local businesses, phones and websites included, then joining it to your own data on `placeId`.
- Mapping how many of a chain's branches sit in one city, with coordinates ready for a map.
- Pulling the newest reviews for a list of place links on a schedule.
- Comparing ratings and review counts across a category in one area before picking a site.

From a search to a watch on the places that matter:

1. Search `dentists in Austin, TX` here and keep the `placeUrl` of the places you care about.
2. Put your own branches into [Google Reviews Monitor](https://apify.com/dami_studio/google-reviews-monitor)'s
   `locations`, and each later run reports only what changed.

### 🚧 What it does not do

- **No e-mail addresses.** [Contact Details Scraper](https://apify.com/dami_studio/contact-details-scraper)
  reads them off the websites this one returns.
- **Ads are not removed.** A sponsored place comes through like any other, marked `sponsored: true`.
- **Duplicates are removed inside one search, not across searches.** A place matching two of your
  searches comes back as two rows, and both count.
- **Short links and cut links are looked up first.** A link cut before its `data=` part can take half
  a minute, and when its name matches several places it gets a free `NO_RESULTS` row.
- **500 per search is the ceiling, not a promise.** Long feeds stop producing new places before
  that on many searches. You pay for what arrives.
- **The place check is about where Google searched, not each row.** With the city right, a dentist
  Google files under Denver can still sit in a suburb next door, unless you tick `onlyInsideArea`.
- **Rows are a snapshot.** Ratings and review counts move, and a place can close.
- It is not an official Google tool. Dami's Studio is independent and is not affiliated with or endorsed by Google, or by any other company named on this page.

### 🧭 Which Google Maps scraper do you need?

| If you want | Use |
|---|---|
| Places from a search, with reviews optional | This one |
| Every review for a place you can link or name, with exact dates | [Google Maps Reviews Scraper](https://apify.com/dami_studio/google-maps-reviews-scraper) |
| The photos and videos on a place | [Google Maps Place Photos Scraper](https://apify.com/dami_studio/google-maps-place-photos-scraper) |
| Only what changed in your own locations' reviews, on a schedule | [Google Reviews Monitor](https://apify.com/dami_studio/google-reviews-monitor) |
| Businesses in Russia and the CIS, from Yandex Maps | [Yandex Maps Scraper](https://apify.com/dami_studio/yandex-maps-scraper) |

### ❓ Questions people ask

#### Do I need a Google API key or a Google account?

No. Nothing to apply for, nothing to sign in to and no quota to watch.

#### Why are phone or website empty on some rows?

The business listed none.

#### Why do my results differ from what I see on Google Maps?

Google ranks a search from where the map sits. A search with no place in it follows the previous
search's town, so put the place in every search or fill `city`. To compare, search in a private
browser window: what a logged-out visitor sees there is what this actor reads.

#### Can I call it from code or connect it to an AI assistant?

The [API tab](https://apify.com/dami_studio/google-maps-scraper/api/python) has code for Python, JavaScript and the
CLI. MCP clients like Claude and ChatGPT use
`https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/google-maps-scraper`; coding assistants can load [our
skill file](https://api.apify.com/v2/key-value-stores/BTBHU3DdiuoF4JOsK/records/apify-maps-places-reviews-SKILL.md).
All three bill your Apify account at the same price.

#### Is scraping Google Maps legal?

These are public listings and public reviews. Reviews carry personal data, which GDPR and similar
laws cover, so have a reason for collecting it. Cold calls and e-mails to businesses are regulated in
many countries, so check the rules where you work. Apify's write-up on
[the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) is a good starting
point, and we are not lawyers.

### 🆘 If something breaks

Open the **Issues** tab on the actor page. Send the search or the place link and the run ID. The
`errorCode` on the diagnostic row usually names the problem on its own.

# Actor input Schema

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

One or more Google Maps searches. Include the location in the text, e.g. "coffee in Brooklyn", "dentists near Eiffel Tower", "hotels Lisbon". You can also paste a search link copied from Google Maps; it runs at the part of the map the link shows. If Google Maps can't find the place after "in" or "near", or after "à", "en", "près de" or "cerca de" when the place starts with a capital letter, that search gets a free BAD_INPUT row instead of places from somewhere else. The same goes for a town it can't find next to a state it can.

## `searchQuery` (type: `string`):

A single search, if you prefer one box instead of the list above.

## `reviewUrls` (type: `array`):

Place links to read reviews from, newest first. placeUrls is accepted as an alias.

## `placeUrls` (type: `array`):

Optional alias for reviewUrls.

## `placeLinks` (type: `array`):

Optional add-on. Google Maps place links, ?cid= links, short maps.app.goo.gl links or ChIJ place IDs: one place row each, with the same fields as a search row. For reviews from a link, use the field above. Needs a paid Apify plan.

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

Google Maps interface language code (e.g. en, de, fr, es).

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

Optional two-letter country, for example US, GB or DE. Leave it empty for the default.

## `city` (type: `string`):

Optional. Runs every search in this city, so "coffee" becomes "coffee in Austin, TX". Add the state or country when the name is common, like Austin, TX or Lyon, France, and leave the place out of the searches themselves. If Google Maps can't find the city, the run stops with a free BAD_INPUT row instead of returning places from somewhere else.

## `county` (type: `string`):

Optional. Runs every search in this county, like Travis County, TX. Works on its own or together with City, and is checked the same way. For a search that goes straight to one business, fill in City too.

## `state` (type: `string`):

Optional. Added to City and County, like TX or Bavaria, and checked the same way.

## `postalCode` (type: `string`):

Optional. Runs every search in this postal code, like 78704, alone or with the fields above. The place check catches a code Google cannot find.

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

Optional. Several places in one run, like "Austin, TX" and "Denver, CO": every search runs in every place, and each pair counts as its own search. Up to 50 places and 200 searches a run. When this is filled, City, County, State and Postal code are not used. A place Google Maps can't find gets a free BAD_INPUT row and is skipped; the other places still run.

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

How many places to collect per search (the scraper scrolls the results feed to reach this). Website, phone, rating, reviewCount, category and address can be null when the card omits them.

## `maxReviewsPerPlace` (type: `integer`):

Maximum reviews to return per place URL or discovered place, up to 5,000.

## `minRating` (type: `string`):

Optional add-on. Only places rated at least this. Places with no rating are left out too. Needs a paid Apify plan.

## `websiteFilter` (type: `string`):

Optional add-on. Only places with a website, or only places without one. Needs a paid Apify plan.

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

Optional add-on. Keeps a place when one of its Google categories contains one of these words, like "dentist" or "pizza". Google has thousands of categories and some go by other names, so a word can miss a place you wanted; check a first run. Needs a paid Apify plan.

## `nameMatch` (type: `string`):

Optional add-on. "Contains" keeps places whose name holds the words of your search (without the place part), "exact" only places named exactly that. Useful for a brand, where Google pads the list with lookalikes. Needs a paid Apify plan.

## `onlyInsideArea` (type: `boolean`):

Optional add-on. Leaves out places Google lists for your City, County, State, Postal code or Locations, or for the place in a search's text, that sit outside it, like a dentist in a suburb next door. Businesses with no street address are kept and marked with serviceArea. Needs a paid Apify plan.

## `skipClosed` (type: `boolean`):

Optional add-on. Leaves out places Google marks as permanently closed. Needs a paid Apify plan.

## `includeReviews` (type: `boolean`):

After collecting places, also return each place's newest reviews, up to Max reviews per place. Every review is a row of its own.

## `includeOwnerReplies` (type: `boolean`):

Attempt to include the business owner's visible reply for each review.

## `reviewsSort` (type: `string`):

Which reviews come first, and so which ones you get when the cap is reached.

## `reviewsSince` (type: `string`):

Optional. A date like 2026-09-01, or a span like 8 days, 2 weeks or 3 months. Reading stops at the first older review. Works with the newest order only. Needs a paid Apify plan.

## `reviewKeywords` (type: `array`):

Optional add-on. Keeps reviews whose text, or Google's translation of it, holds one of these words, matched at the start of a word ("tea" finds "teapot", not "steak"). Reviews left out are not written as rows. Needs a paid Apify plan.

## `includeReviewerDetails` (type: `boolean`):

Adds each reviewer's profile link, photo, review and photo counts, and Local Guide flag to review rows.

## `skipReviewerNames` (type: `boolean`):

Review rows come without the reviewer's name, for when you only need the ratings and text.

## `includeOrderLinks` (type: `boolean`):

Optional add-on, charged per place checked. For each place found by a search, the ordering services Google lists for it. A place with none still counts as checked, so tick it for restaurants.

## `includePlaceDetails` (type: `boolean`):

Optional add-on. Adds reviewTopics (the words reviewers repeat, with how often), placesInside (the places inside this one, like the restaurants in a hotel) and ownerDescription (the text the business wrote about itself) to each place row. One more request a place. Needs a paid Apify plan.

## `includeLegalNotice` (type: `boolean`):

Optional add-on. For places whose website is German, Austrian or Swiss, reads the legal notice (Impressum) that site publishes and adds legalNotice: the company name, the directors or owners it names, the VAT id and the register number. Never an e-mail address or phone number from the page. Up to two requests to each business website. Needs a paid Apify plan.

## `maxPhotosPerPlace` (type: `integer`):

Optional. Photo links for each place found, one row each (type "photo"), links only, up to this many. Google sends a handful with each place (3 or 4 seen), not its whole gallery. 0 for none. Every photo row counts as a row. Needs a paid Apify plan.

## `fields` (type: `array`):

Optional. Field names to keep in each row, like name, phone and website; ok and type always stay. Leave empty for every field.

## `notionConnector` (type: `string`):

Optional. Write each place as a page into your Notion when the run finishes. Authorize a Notion connector once in Settings → API & Integrations → MCP connectors, then pick it here. Leave empty to skip (default), results are always saved to the dataset regardless.

## `notionParentId` (type: `string`):

Optional. The Notion data source ID of the database to write into (only used if a Notion connector is set). Leave empty to create the pages privately in your workspace instead.

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

Optional. Leave this alone unless you need the run to go out through a particular network. Your own proxy servers are used exactly as given.

## Actor input object example

```json
{
  "searchQueries": [
    "coffee in Brooklyn"
  ],
  "language": "en",
  "maxItems": 60,
  "maxReviewsPerPlace": 50,
  "minRating": "any",
  "websiteFilter": "allPlaces",
  "nameMatch": "all",
  "onlyInsideArea": false,
  "skipClosed": false,
  "includeReviews": false,
  "includeOwnerReplies": true,
  "reviewsSort": "newest",
  "includeReviewerDetails": false,
  "skipReviewerNames": false,
  "includeOrderLinks": false,
  "includePlaceDetails": false,
  "includeLegalNotice": false,
  "maxPhotosPerPlace": 0
}
```

# Actor output Schema

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

Scraped place and review rows are stored in the default dataset. Review rows use type=review and include reviewerName, rating, relativeDate, text, ownerReply, and photoUrls. Blocked/empty/error runs return a single uncharged diagnostic row instead.

# 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 in Brooklyn"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/google-maps-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 in Brooklyn"] }

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/google-maps-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 in Brooklyn"
  ]
}' |
apify call dami_studio/google-maps-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/google-maps-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/Eu5YDxpcZq4z7wjKw/builds/xv3HgeNWpyDu5Qg6A/openapi.json
