# Google Hotels Scraper (`finaldynamics/google-hotels-scraper`) Actor

Google Hotels API for hotel prices by city and dates: nightly rate, stay total, star class, rating, reviews and deals, checked against the dates you asked for.

- **URL**: https://apify.com/finaldynamics/google-hotels-scraper.md
- **Developed by:** [Final Dynamics](https://apify.com/finaldynamics) (community)
- **Categories:** Travel, E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.99 / 1,000 hotels

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 Hotels Scraper

A Google Hotels API for hotel prices. Search cities, or name the hotels you track by ID, Google
Hotels or Google Maps link, or plain name. You get nightly rates and stay totals for your dates,
currency and guests, plus booking sites' prices, room rates, guest reviews and a day-by-day price
calendar when you ask for them.

Use it to check competitor rates every morning, fill a price comparison page, or see when a market
gets cheap. Each hotel row carries the dates, currency and guests Google actually quoted, and the
actor checks them against what you asked for. If Google answers for a different stay, that page is
discarded. You keep the verified rows from earlier pages and get a note saying why the search
stopped.

### What you get

A real run for Miami, December 5 to 7, 2026: 4 stars and up, free cancellation, lowest price first.

| Hotel                                         | Class | Rating | Reviews | Per night | Stay total | Deal                |
| --------------------------------------------- | ----: | -----: | ------: | --------: | ---------: | ------------------- |
| Four Points by Sheraton Coral Gables          |     4 |    4.2 |     871 |   $219.59 |       $439 |                     |
| Pullman Miami Airport                         |     4 |    4.0 |   4,539 |   $232.00 |       $464 | 20% less than usual |
| Sheraton Miami Airport Hotel & Executive M... |     4 |    3.9 |   5,230 |   $234.89 |       $470 |                     |
| DoubleTree by Hilton Miami North I-95         |     4 |    3.7 |   1,036 |   $249.11 |       $498 | 39% less than usual |
| Beach Park Hotel                              |     4 |    3.2 |     708 |   $250.84 |       $502 |                     |

Every row in that run had free cancellation confirmed in Google's quote. Vacation rentals come back
too, marked in `propertyType`, unless you leave them out.

### Quick start

1. Open the **Miami hotel prices, two weeks out** example on this page and click **Try for free**.
2. Change the location to your city, or add several. To follow set hotels, fill **Hotel names** or
   **Specific hotel IDs** instead.
3. Click **Start**. Larger searches need more requests. If you clear every location and hotel, the
   run does a sample search for Miami and says so in its status.
4. Open the **Output** tab to see the table, then click **Export** for CSV, Excel or JSON.
5. To work in Google Sheets, open the CSV there with **File > Import**.

### Input

```json
{
  "locations": ["Paris"],
  "checkInDate": "2026-12-05",
  "checkOutDate": "2026-12-07",
  "adults": 3,
  "children": 2,
  "childrenAges": [5, 9],
  "currency": "EUR",
  "maxResults": 20,
  "includeBookingSources": true,
  "includeRoomRates": true
}
```

#### What to search

- **Locations**: up to 100 cities or areas, such as `Miami` or `Moab, Utah`. Add the state or
  country when a name is common. If Google can't find a place, that search returns no rows and a
  warning, so you never get another town's hotels by mistake.
- **Specific hotels**: put Google IDs from the `hotelId` output in `hotelIds`, paste property links
  into `hotelUrls`, or type names into `hotelNames`, such as `Hotel Plaza Athenee Paris`. Google's
  own search picks the hotel for a name, and the row shows the name it matched. Each hotel returns
  one row for your stay. A hotel returned earlier in the run isn't charged twice. Up to 100 hotels.
- **Google Maps links**: `hotelUrls` also takes a hotel's Google Maps link, a Maps share link such
  as `https://maps.app.goo.gl/...`, or a Maps place ID that starts with `ChIJ`. A share link costs
  one extra request to see where it points. A Maps link without a place in it, such as a map view,
  is refused before the run starts. A place that isn't a hotel, like a restaurant, returns an error
  for that line and isn't charged.
- **Maximum hotels per location**: 1 to 1,000. The default is 20, which reads one page. Higher
  values read more pages until Google runs out. In a Paris test Google stopped after position 722,
  which held 552 different properties once repeats were removed.
- **No target**: a run with no location and no hotel, such as Apify's own test with an empty input,
  searches Miami with your other settings. The log, status and `OUTPUT` say it was a sample.

#### Dates and guests

- **Check-in and check-out**: `YYYY-MM-DD`. Leave both empty and the actor searches a 2-night stay
  starting 14 days from today, which suits a daily schedule. Stays can be up to 30 nights.
- **Price calendar**: set `priceWindowEnd` and the actor reprices the same length of stay for every
  check-in day up to that date, at most 60 days after check-in. Each day is its own row with its own
  dates, and `calendarDay` says how many days after your check-in it starts. It works for locations
  and specific hotels. Filters apply to the first stay only.
- **Guests**: `adults` from 1 to 12, `children` with one age from 0 to 17 in `childrenAges` for each
  child. This actor caps the group at 12 guests.
- **Currency**: a three-letter code Google accepts. USD is the default. EUR, GBP and JPY have been
  checked live. Every quote must confirm your currency, and the actor never converts prices.

#### Filters and sorting

Google applies all of these, and each results page must confirm them before any row is saved.
Amenities, hotel types and the rental filters work on location searches. Specific hotels come back
as you asked for them, with price, rating, stars and cancellation still checked.

- **Sort**: Google's order, or Google's own sort by lowest price, highest rating or most reviews.
- **Price**: `minPrice` and `maxPrice` per night in your currency. Zero means no limit.
- **Guest rating**: `minRating` on Google's 0 to 5 scale. Every row is checked against your exact
  number. At 3.5, 4.0 or 4.5 and up Google filters too, so more pages hold matches.
- **Stars**: `hotelClass` for a minimum, or `hotelClasses` for exact classes such as 3 and 4.
- **Hotel amenities**: the 19 options in Google's filter panel, such as `freeWifi`, `pool`,
  `freeBreakfast`, `petFriendly`, `evCharger` or `allInclusive`. A hotel must have all you pick.
  `airportShuttle` works too, but Google's panel doesn't have it, so the actor checks it itself: it
  keeps hotels whose amenity list names an airport shuttle. Pages can then hold fewer hotels.
- **Hotel types**: `beachHotels`, `hostels`, `inns`, `motels`, `resorts`, `spaHotels`,
  `bedAndBreakfasts`, and for Japan `minshuku`, `japaneseBusinessHotels` and `ryokan`. These are the
  types this actor checked against live results, by name or by each result's Google Maps category.
  Boutique hotels, apartment hotels and "other" aren't offered: Google didn't apply the first two in
  a Paris test, and "other" returned ordinary hotels.
- **Free cancellation**: asks Google for cancellable rates. Booking sites without free cancellation
  are left out, and each shows its deadline when Google gives one.
- **Vacation rentals**: `include` mixes them with hotels as Google does, `only` asks Google for
  rentals, and `exclude` leaves them out. With `only` you can also set `rentalTypes` (apartments,
  houses, villas, cottages, cabins, chalets, gites, holidayVillages, houseboats, other),
  `rentalAmenities` (such as `kitchen` or `hotTub`), and minimum `bedrooms` and `bathrooms`. With a
  room minimum, a rental that doesn't state its count is left out. Counts are read from English
  labels, so room minimums need `languageCode` `en`. Bungalows aren't offered: Google dropped that
  filter in Gatlinburg and Tulum.
- `exclude` is the actor's own check on each row. Google mixes rentals into later pages, and none of
  the request settings tried in a test turned that off. So a page can hold fewer than 20 hotels.

#### Extra data

- **Booking sites**: set `includeBookingSources` to `true`. Each row lists the booking sites Google
  shows for your stay that come with a rate and a booking link. You get the site's logo, whether
  it's sponsored or the hotel's own site, nightly rate, stay total, both with taxes, the guests the
  price covers, free cancellation and the booking link. A site without a rate or link is left out
  with a warning, and so is one without free cancellation when you ask for it. A location result
  needs one extra request per hotel.
- **Hotel details**: set `includeHotelDetails` to `true` to look up each hotel from a location on
  its own Google page, as specific hotels are. You get more photos (13 to 28 in tests instead of 9),
  the neighborhood, the Maps place ID, other review sites' scores and the typical price range. It
  takes one extra request per hotel and costs nothing extra. Booking sites include it already.
- **Photos**: each row has `photos`, up to `maxPhotos` (25 by default, 0 to 100). Each photo has its
  link and, when Google has them, the original image link, size, caption, source and date. The actor
  reads the photos in the data it already fetches. It doesn't open Google's full gallery, which
  holds hundreds of photos for a big hotel.
- **Room rates**: set `includeRoomRates` to `true` as well. Each booking site then lists its rooms
  with every rate: room name, photos, prices with and without taxes, breakfast, cancellation
  deadline and booking link. Google gives rooms for the sites that send them to it.
- **Reviews**: set `includeReviews` to `true`. Each hotel row then has a `reviews` list with up to
  `maxReviews` reviews, and `reviewsExtracted` says how many it holds. Pick the order with
  `reviewsSort` (most helpful, newest, highest or lowest score), and narrow to one topic from
  `reviewsBreakdown` with `reviewsTopic`, such as `Service`. Reviews come from Google and partner
  sites such as Tripadvisor. To keep one source, list it in `reviewsSources`, such as `Tripadvisor`.
  The actor reads Google's review pages and keeps the matches, reading at most 500 reviews per
  hotel, because the request behind Google's own source menu wasn't found.
- **Text summary**: `includeMarkdown` adds `markdownContent`, a readable summary of each row and its
  reviews for search indexes and AI tools.

#### Market and requests

- **Language and country**: Google's interface language and search region. The defaults are `en` and
  `us`.
- **Device**: `desktop` or `mobile`. In a live test Google showed a phone offers a desktop didn't
  get, such as a lower Vio.com rate and a Tripadvisor.com offer.
- **Request timeout**: seconds to wait for each Google response before a retry, 5 to 120.
- **Proxies**: none. Requests go straight to Google from Apify's servers. If you paste an input from
  another actor, its `proxyConfiguration` is accepted and ignored, and the log says so.

### Output

This is a real row from the Paris run above, 3 adults and 2 children. You get one row like it for
each property.

```json
{
  "position": 3,
  "location": "Paris",
  "name": "JO&JOE Paris Gentilly",
  "hotelId": "ChkIy5q-tZ-KsLYZGg0vZy8xMWd5MXR3Y2d6EAE",
  "propertyType": "hotel",
  "rating": 4.4,
  "reviewCount": 5100,
  "pricePerNight": 117,
  "priceDisplay": "€117",
  "pricePerNightWithTaxes": 134,
  "totalPrice": 234,
  "totalPriceDisplay": "€234",
  "currency": "EUR",
  "checkInDate": "2026-12-05",
  "checkOutDate": "2026-12-07",
  "nights": 2,
  "adults": 3,
  "children": 2,
  "childrenAges": [5, 9],
  "calendarDay": 0
}
```

Its first booking site, with one of its rooms, shortened:

```json
{
  "vendorName": "Booking.com",
  "vendorIcon": "https://www.gstatic.com/travel-hotels/branding/icon_184.png",
  "isSponsored": true,
  "isOfficial": false,
  "ratePerNight": 117,
  "ratePerNightDisplay": "€117",
  "ratePerNightWithTaxes": 133.8,
  "totalRate": 234,
  "totalRateDisplay": "€234",
  "totalRateWithTaxes": 267.59,
  "currency": "EUR",
  "numGuests": 5,
  "coversAllGuests": true,
  "freeCancellation": false,
  "freeCancellationUntil": null,
  "rooms": [
    {
      "roomName": "Private Bedroom for 5 people with a bathroom",
      "offers": [{ "ratePerNight": 117, "totalRateWithTaxes": 267.6, "breakfastIncluded": false }]
    }
  ]
}
```

Rows also include, when Google supplies them: `address`, `neighborhood`, `phone`, `website`,
coordinates, `hotelClassLabel`, `hotelDescription`, check-in and check-out times, readable
`amenities`, `excludedAmenities`, `images`, `ratingsBreakdown`, `reviewsBreakdown`,
`otherReviewSites` (such as Tripadvisor's score), `nearbyPlaces`, `deal`, `googleHotelsUrl`,
`googleMapsUrl`, `placeId`, `mapsFeatureId` and `mapsCid`. Vacation rentals add `essentialInfo`,
`sleeps`, `bedrooms`, `bathrooms` and `beds`. Unknown fields are null and absent lists are empty.

- `locationRating` is Google's hotel location score from 1 to 5. `locationRatings` has its four
  parts: `thingsToDo`, `restaurants`, `transit` and `airportAccess`.

- `mapsCategory` is the property's main Google Maps category, such as `hotel`, `hostel` or
  `japanese_inns`, and `mapsCategories` lists all of them. Most vacation rentals have none.

- `mapsCid` opens the place at `https://maps.google.com/?cid=` plus this number.

- `pricePerNight` is Google's exact nightly rate. `priceDisplay` is the rounded figure Google shows.
  Prices with taxes are Google's displayed figures, rounded as shown.

- `typicalPriceLow` and `typicalPriceHigh` are Google's price insight: the range this hotel usually
  costs per night for these dates. They come with property lookups, so fill them by using specific
  hotels, booking sites or room rates.

- A booking site's `numGuests` is the number of guests its price covers, as the site tells Google.
  Some sites quote for fewer or more guests than you asked for. `coversAllGuests` is true when the
  price covers exactly the adults and children you asked for.

- `hotelId` stays the same between runs, so you can join today's prices to yesterday's.

- The actor doesn't follow booking links or make reservations. Google may reset the dates when you
  open `googleHotelsUrl`. The dataset dates are checked separately.

- `nearbyPlaces` keeps Google's transportation codes without guessing their meanings.

With reviews on, each row's `reviews` list holds entries like this one, shortened:

```json
{
  "source": "Google",
  "reviewerName": "Patriek Dob",
  "rating": 5,
  "bestRating": 5,
  "relativeDate": "5 days ago",
  "publishedDateEstimate": "2026-09-20",
  "visited": "Visited in September",
  "visitedMonth": "2026-09",
  "ownerResponse": "Dear Mr Patriek,\n\nThank you for your rating and for visiting us..."
}
```

Each review also has `subRatings`, the reviewer's aspect scores, each with Google's category number,
`rating` and `bestRating`. Google's data doesn't name the categories, so they come as numbers.
`publishedDateEstimate` subtracts Google's relative date from the scrape time, so "3 weeks ago" is
as precise as a week. Google Hotels sends no exact review date.

### Automate it

1. Open your saved task, or save one from the example with **Save as a new task**.
2. On the task, click **Schedules > Create schedule** and pick a time, such as 7:00 every morning.
3. Leave the dates empty. Each run then searches two weeks ahead of that day.
4. To land the rows in Google Sheets, build an n8n workflow. Start it with an **Apify Trigger** node
   on "task run succeeded", add an Apify **Get Dataset Items** node for that run, then a **Google
   Sheets** node that appends the rows.

Each row has a `scrapedAt` time, so the sheet keeps a dated price history for your market.

### Pricing

There's no start fee. You pay for each hotel row saved to your dataset, and that price drops on
higher Apify plans. Reviews cost extra, and only when you turn them on.

| You pay for | Free plan |   Bronze |   Silver | Gold and up | When you pay                                    |
| ----------- | --------: | -------: | -------: | ----------: | ----------------------------------------------- |
| Hotel row   |  $0.00499 | $0.00432 | $0.00366 |    $0.00299 | Apify charges it as the row is saved            |
| Review      |   $0.0005 |  $0.0005 |  $0.0005 |     $0.0005 | After the hotel row holding the review is saved |

On the free plan, a search that returns 18 hotels costs about $0.09. A daily run over 5 cities is
about 90 hotels, or $0.45 a day and about $13.50 a month. On Gold it's $0.27 a day. Booking sites,
room rates, photos and hotel details are included in the hotel row. Each price-calendar day is one
more row: 10 hotels over 7 check-in days is 70 rows, or about $0.35 on the free plan. Twenty reviews
for each of those 10 hotels add 200 reviews, or $0.10.

You never pay for a row you don't get. Apify charges a hotel row only when it's saved in your
dataset, so a run that stops early charges only for the rows it saved. Reviews are charged after the
row holding them is saved. If Apify refuses the review charge, you keep those reviews for free. If
Apify does not confirm a charge, the reviews may or may not have been charged. `OUTPUT` reports free
and uncertain reviews separately. Uncertain charges still count toward your maximum charge.

Set a maximum charge on the run and the actor stops before the next row would go over it. Before it
fetches a hotel's reviews, it checks what's left. If your maximum covers the row but not all its
reviews, it fetches fewer reviews for that hotel, or none, and says so in `OUTPUT`. So the review
charge never takes you past your maximum.

A hotel is saved and charged once per run, even when several of your locations or pages list it. The
price calendar adds its own rows, one per check-in day. If Apify's dataset doesn't answer a save,
the actor reads the dataset back before it tries again, so a row is never saved, or charged, twice.
If Apify moves your run to another server mid-run, the actor reads back the rows already saved and
doesn't save or charge them again, and it doesn't charge their reviews twice.

### Good to know

- After every run, the `OUTPUT` record in the key-value store lists each search with its status,
  hotel and review counts, and any warning or error. `events` counts hotel rows and reviews against
  the charge cap, including review charges that did not confirm. `reviewsCharged`, `reviewsFree` and
  `reviewsUncertain` separate the review outcomes. `maxChargedUsd` is the most this run can have
  cost, at the Free-plan price. Paid Apify plans pay less; the exact amount is in the run's Apify
  billing. For a location it also has `searchMetadata`: Google's result count, the brands its brand
  filter lists, and the filter chips it suggests.
- If Google refuses a search, the actor waits and retries it at most twice. It never solves or works
  around a CAPTCHA. After three refused searches in a row, the run stops.
- Every page must match your dates, currency, guests, resolved place and filters. A continuation
  with different dates gets one retry with the verified selection. If it still fails, you keep
  earlier rows and see a `partial` status with a warning.
- A run can finish **Succeeded** with no matching rows. Check `OUTPUT` for empty searches and
  warnings. A failed later search doesn't discard rows from earlier ones.
- Requests go out at least two seconds apart, with at most two in flight. So 1,000 requests take at
  least 33 minutes. Booking sites, hotel details, price calendars and reviews add requests per
  hotel. The actor sizes its request limit from your input, from 1,000 up to 10,000 requests,
  including retries and redirects. If your input needs more than that, or more time than the run's
  timeout allows, the run says so when it starts. It then stops before the limit or the timeout,
  keeps the rows it has and says why in its status. Raise the run timeout or split the input to get
  the rest.
- Room counts aren't offered. Google's guest picker has adults and children only. In the one hotel
  tested, a 2-room request got the same offers and prices as 1 room.
- Eco-certified filtering isn't offered. With Google's own eco-certified switch on, Google returned
  no certified properties in the four markets tested (Paris, Amsterdam, Miami and Copenhagen,
  September 2026).

### FAQ

#### Is there an official Google Hotels API?

Google's hotel APIs take in rates from hotels and booking sites. They don't give you the prices
Google shows travellers. This actor reads those prices from Google Hotels and returns them as data.

#### How do I get hotel prices for specific dates?

Set `checkInDate` and `checkOutDate`. Every row returns the dates Google quoted. Pages with other
dates are never saved or charged. For many check-in days at once, set `priceWindowEnd`.

#### Can I track a fixed list of competitor hotels?

Yes. Put their names in `hotelNames` once, copy the `hotelId` values from the first run into
`hotelIds`, and schedule the task. IDs skip the name lookup and always hit the same property.

#### Can I track hotel rates over time?

Schedule a saved task to run every day with the dates left empty, and send each run's rows to a
sheet or database. Use `hotelId` and `scrapedAt` to line up the same hotel across days.

#### Why do I get fewer hotels than requested?

The default reads one page. Set `maxResults` above 20 to continue through more pages. Google may run
out of results or repeat properties. Filters can remove rows from a page. Your charge budget, the
request limit and the run timeout can also stop a run. Check `OUTPUT` and the status message for
your location's status and warnings.

# Actor input Schema

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

Cities or areas to search, such as Miami or Moab, Utah. Add the state or country when a name is common. You can mix locations with specific hotels below. If you give no location, hotel ID, hotel link or hotel name, the run does a sample search for Miami (up to Maximum hotels per location) and says so in its status.

## `hotelIds` (type: `array`):

Google hotel IDs from the hotelId output, or Google Maps place IDs that start with ChIJ. You get one row per hotel for your stay. Use this to track a fixed set of competitors.

## `hotelUrls` (type: `array`):

Paste Google Hotels property links (https://www.google.com/travel/hotels/entity/...), Google Maps links to the hotel, or Maps share links (https://maps.app.goo.gl/...). A share link takes one extra request to see where it points. The actor uses your dates and guests, not the ones in the link. A Maps place that isn't a hotel returns an error for that line.

## `hotelNames` (type: `array`):

Type a hotel's name, with the city for common names, such as Hotel Plaza Athenee Paris. Google's search picks the hotel and the row shows the name it matched. A city name alone isn't a hotel and returns an error for that line.

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

Most hotels to return for each location, from 1 to 1,000. Up to 20 reads one results page. Higher values read more pages until Google runs out. In a Paris test Google stopped after 552 different properties. Specific hotels always return one row each. Big inputs take time: requests go out at least 2 seconds apart, and booking sites, hotel details, reviews and the price calendar each add requests per hotel. A run allows up to 10,000 Google requests and stops before its timeout. If it can't finish, it says so up front and in its status, and keeps the rows it has.

## `checkInDate` (type: `string`):

YYYY-MM-DD. Leave empty to search 14 days from today, which suits a daily schedule. Past dates aren't allowed.

## `checkOutDate` (type: `string`):

YYYY-MM-DD. Leave empty for a 2-night stay. Stays can be up to 30 nights.

## `priceWindowEnd` (type: `string`):

Optional. Reprices the same length of stay for every check-in day from your check-in date up to this date, at most 60 days later. Each extra check-in day is one more row per hotel, charged as a normal hotel row. Best with a short list of specific hotels. Leave empty for one stay.

## `adults` (type: `integer`):

Number of adults, from 1 to 12. Google's quote is checked against your guest count.

## `children` (type: `integer`):

Number of children. Give one age per child in Children ages. The actor accepts up to 12 guests in total.

## `childrenAges` (type: `array`):

Each child's age at check-in, from 0 to 17. For two children aged 7 and 10, enter \[7, 10]. The count must match Children.

## `currency` (type: `string`):

Three-letter code Google accepts, such as USD, EUR, GBP or JPY. Every quote must confirm this currency. The actor never converts prices.

## `sortBy` (type: `string`):

Google's own order, or Google's sort by lowest price, highest rating or most reviews. Google sorts its whole list, and the actor keeps the rows it collected in that order.

## `minPrice` (type: `number`):

Lowest nightly rate in your currency. Zero means no minimum. Google applies it and each row is checked again. Hotels without a price are left out when you set a limit.

## `maxPrice` (type: `number`):

Highest nightly rate in your currency. Zero means no maximum. It compares the base rate, which may leave out taxes.

## `minRating` (type: `number`):

Lowest guest rating on Google's 0 to 5 scale. Zero means any. Values of 3.5, 4.0 or 4.5 and up also use Google's own rating filter, so more pages hold matches. Every row is checked against your exact number.

## `hotelClass` (type: `integer`):

Lowest published star class: 2, 3, 4 or 5, or 0 for any class. Google has no 1-star filter, so 1 is refused. Google applies it and each row is checked. Properties with no star class are left out. Use this or Exact hotel classes, not both.

## `hotelClasses` (type: `array`):

Pick one or more star classes, such as 3 and 4 without 5. Google applies them and each row is checked. From the API, send them as strings, such as \["3", "4"].

## `amenities` (type: `array`):

Keep hotels that have all the amenities you pick. All but Airport shuttle are the options in Google's own filter panel: Google applies them, and each results page must confirm the filter before rows are saved. Google's panel has no airport shuttle, so the actor keeps only hotels whose amenity list names one, which can mean fewer rows per page. Applies to location searches, not to specific hotels.

## `propertyTypes` (type: `array`):

Narrow hotels to these types. Google applies the filter and each page must confirm it. Only types whose live results matched are offered, checked by name or by the Google Maps category of every result. Minshuku, Japanese-style business hotels and ryokan are for Japan. Applies to location searches, not to specific hotels.

## `freeCancellation` (type: `boolean`):

Ask Google for rates you can cancel for free. Each quote must confirm the selection. Booking sites without free cancellation are left out, and each one shows its deadline when Google gives it.

## `vacationRentals` (type: `string`):

Include vacation rentals with hotels as Google mixes them, ask Google for vacation rentals only, or leave rentals out. Leaving them out is the actor's own check on each row, so a page can hold fewer than 20 hotels. Every row's property type is checked.

## `rentalTypes` (type: `array`):

With Vacation rentals set to only: the rental types to keep. Google applies them and each page must confirm the filter. Applies to location searches, not to specific hotels.

## `rentalAmenities` (type: `array`):

With Vacation rentals set to only: require these amenities from Google's rental filter panel. Applies to location searches, not to specific hotels.

## `bedrooms` (type: `integer`):

With Vacation rentals set to only: at least this many bedrooms, from 0 to 5. Google applies it and confirms it on each page, and each row is checked too. Rentals that don't state a bedroom count are left out. Needs language code en, because room counts are read from English labels.

## `bathrooms` (type: `integer`):

With Vacation rentals set to only: at least this many bathrooms, from 0 to 5. Google applies it and confirms it on each page, and each row is checked too. Rentals that don't state a bathroom count are left out. Needs language code en, because room counts are read from English labels.

## `includeBookingSources` (type: `boolean`):

Adds the booking sites Google lists for your stay that come with a rate and a booking link: name, logo, official-site flag, nightly rate, stay total, prices with taxes, guest count, free cancellation and booking link. A site without a rate or link, or without free cancellation when you ask for it, is left out with a warning. A location result needs one extra request per hotel. There's no extra charge.

## `includeRoomRates` (type: `boolean`):

Adds each booking site's rooms with every rate: room name, nightly and total price, taxes, breakfast, free cancellation deadline and booking link. Google gives rooms for the sites that send them. No extra request beyond booking sites and no extra charge. Rows get much larger.

## `includeHotelDetails` (type: `boolean`):

Looks up each hotel from a location search on its own Google page, like specific hotels get: more photos (13 to 28 in tests instead of 9), neighborhood, place ID, other review sites' scores and the typical price range. One extra request per hotel, no extra charge. Booking sites and room rates already include this.

## `maxPhotos` (type: `integer`):

Most entries to keep in each row's photos list, from 0 to 100. Each photo has its link and, when Google has them, the original image link, size, caption, source and date. The actor reads the photos in the data it already fetches; it doesn't open Google's full gallery.

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

Adds a reviews list to each hotel row. Each review costs $0.0005, charged after the row holding it is saved. If that charge doesn't go through, you keep the reviews for free. Each 50 reviews take one request.

## `maxReviews` (type: `integer`):

Most reviews to save for each hotel, from 1 to 1,000. If your run's maximum charge can't cover them all after the hotel row, the actor fetches fewer for that hotel, or none, and says so in OUTPUT.

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

Google's review order: most helpful, newest, highest score or lowest score.

## `reviewsTopic` (type: `string`):

Optional. Only reviews about one topic, using a name from the hotel's reviewsBreakdown, such as Service, Location or Breakfast. Leave empty for all reviews.

## `reviewsSources` (type: `array`):

Optional. Keep reviews from these sources only, such as Google or Tripadvisor, as named in each review's source. The actor reads Google's review pages and keeps the matches, reading at most 500 reviews per hotel. Leave empty for every source.

## `includeMarkdown` (type: `boolean`):

Adds markdownContent, a short readable summary of each hotel row and its reviews, handy for search indexes and AI tools.

## `languageCode` (type: `string`):

Google's interface language, such as en or fr. Room counts for vacation rentals are read from English labels only.

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

Google's search region, such as us or gb.

## `device` (type: `string`):

Desktop or mobile. In a live test Google showed a phone some offers a desktop didn't get, such as a lower Vio.com rate and a Tripadvisor.com offer.

## `requestTimeoutSecs` (type: `integer`):

How long to wait for each Google response, from 5 to 120 seconds, before retrying. Requests go straight to Google from Apify's servers, without proxies. A proxyConfiguration pasted from another actor's input is accepted, ignored and noted in the log.

## Actor input object example

```json
{
  "locations": [
    "Miami"
  ],
  "hotelIds": [],
  "hotelUrls": [],
  "hotelNames": [],
  "maxResults": 20,
  "checkInDate": "",
  "checkOutDate": "",
  "priceWindowEnd": "",
  "adults": 2,
  "children": 0,
  "childrenAges": [],
  "currency": "USD",
  "sortBy": "google",
  "minPrice": 0,
  "maxPrice": 0,
  "minRating": 0,
  "hotelClass": 0,
  "hotelClasses": [],
  "amenities": [],
  "propertyTypes": [],
  "freeCancellation": false,
  "vacationRentals": "include",
  "rentalTypes": [],
  "rentalAmenities": [],
  "bedrooms": 0,
  "bathrooms": 0,
  "includeBookingSources": false,
  "includeRoomRates": false,
  "includeHotelDetails": false,
  "maxPhotos": 25,
  "includeReviews": false,
  "maxReviews": 20,
  "reviewsSort": "mostHelpful",
  "reviewsTopic": "",
  "reviewsSources": [],
  "includeMarkdown": false,
  "languageCode": "en",
  "countryCode": "us",
  "device": "desktop",
  "requestTimeoutSecs": 45
}
```

# Actor output Schema

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

One row per hotel or vacation rental and stay. With reviews on, each row holds its reviews.

## `summary` (type: `string`):

Run status, saved hotel rows, confirmed, free and uncertain reviews, request count, and each query's status, counts, errors and warnings. maxChargedUsd is the most this run can have cost at the Free-plan price; paid Apify plans pay less. The exact amount is in the run's Apify billing. Read this even when the run succeeded with partial data.

# 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": [
        "Miami"
    ],
    "hotelIds": [],
    "hotelUrls": [],
    "hotelNames": [],
    "maxResults": 20,
    "checkInDate": "",
    "checkOutDate": "",
    "priceWindowEnd": "",
    "adults": 2,
    "children": 0,
    "childrenAges": [],
    "currency": "USD",
    "sortBy": "google",
    "minPrice": 0,
    "maxPrice": 0,
    "minRating": 0,
    "hotelClass": 0,
    "hotelClasses": [],
    "amenities": [],
    "propertyTypes": [],
    "freeCancellation": false,
    "vacationRentals": "include",
    "rentalTypes": [],
    "rentalAmenities": [],
    "bedrooms": 0,
    "bathrooms": 0,
    "includeBookingSources": false,
    "includeRoomRates": false,
    "includeHotelDetails": false,
    "maxPhotos": 25,
    "includeReviews": false,
    "maxReviews": 20,
    "reviewsSort": "mostHelpful",
    "reviewsTopic": "",
    "reviewsSources": [],
    "includeMarkdown": false,
    "languageCode": "en",
    "countryCode": "us",
    "device": "desktop",
    "requestTimeoutSecs": 45
};

// Run the Actor and wait for it to finish
const run = await client.actor("finaldynamics/google-hotels-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 = {
    "locations": ["Miami"],
    "hotelIds": [],
    "hotelUrls": [],
    "hotelNames": [],
    "maxResults": 20,
    "checkInDate": "",
    "checkOutDate": "",
    "priceWindowEnd": "",
    "adults": 2,
    "children": 0,
    "childrenAges": [],
    "currency": "USD",
    "sortBy": "google",
    "minPrice": 0,
    "maxPrice": 0,
    "minRating": 0,
    "hotelClass": 0,
    "hotelClasses": [],
    "amenities": [],
    "propertyTypes": [],
    "freeCancellation": False,
    "vacationRentals": "include",
    "rentalTypes": [],
    "rentalAmenities": [],
    "bedrooms": 0,
    "bathrooms": 0,
    "includeBookingSources": False,
    "includeRoomRates": False,
    "includeHotelDetails": False,
    "maxPhotos": 25,
    "includeReviews": False,
    "maxReviews": 20,
    "reviewsSort": "mostHelpful",
    "reviewsTopic": "",
    "reviewsSources": [],
    "includeMarkdown": False,
    "languageCode": "en",
    "countryCode": "us",
    "device": "desktop",
    "requestTimeoutSecs": 45,
}

# Run the Actor and wait for it to finish
run = client.actor("finaldynamics/google-hotels-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 '{
  "locations": [
    "Miami"
  ],
  "hotelIds": [],
  "hotelUrls": [],
  "hotelNames": [],
  "maxResults": 20,
  "checkInDate": "",
  "checkOutDate": "",
  "priceWindowEnd": "",
  "adults": 2,
  "children": 0,
  "childrenAges": [],
  "currency": "USD",
  "sortBy": "google",
  "minPrice": 0,
  "maxPrice": 0,
  "minRating": 0,
  "hotelClass": 0,
  "hotelClasses": [],
  "amenities": [],
  "propertyTypes": [],
  "freeCancellation": false,
  "vacationRentals": "include",
  "rentalTypes": [],
  "rentalAmenities": [],
  "bedrooms": 0,
  "bathrooms": 0,
  "includeBookingSources": false,
  "includeRoomRates": false,
  "includeHotelDetails": false,
  "maxPhotos": 25,
  "includeReviews": false,
  "maxReviews": 20,
  "reviewsSort": "mostHelpful",
  "reviewsTopic": "",
  "reviewsSources": [],
  "includeMarkdown": false,
  "languageCode": "en",
  "countryCode": "us",
  "device": "desktop",
  "requestTimeoutSecs": 45
}' |
apify call finaldynamics/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

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