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

Scrape Google Hotels by place and dates: nightly price with and without taxes, rating, reviews summary, amenities, location. Every booking site's price, room rates, reviews and price calendar on demand. Export to JSON, CSV or Excel.

- **URL**: https://apify.com/nice_dev/google-hotels-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Travel, E-commerce, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

### 🏨 What is Google Hotels Scraper?

**Google Hotels Scraper** extracts **hotels and vacation rentals from [Google Hotels](https://www.google.com/travel/hotels)**: **name, price per night for your dates with and without taxes, Google's deal versus the usual price, star class, guest rating, rating breakdown, review topics, amenities, GPS position, travel times to the nearest station and airport, and photos**, for a destination, a map area, a brand, a list of hotel names or ids, or any Google Hotels link you paste. Tick the options you need to add the **full hotel profile (address, phone, long description), the price on every booking site Google compares, every room rate, the full guest reviews and a day-by-day price calendar**. It works as a **Google Hotels API alternative**: run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.

Type a **destination** (`Paris`), pick your dates, guests and currency, click **Start**, and download the hotels in JSON, CSV or Excel. No login, nothing to set up. Dates can be relative (`14 days` from the run date), so a saved task always looks the same distance ahead, and several destinations, search texts, hotel names, ids and links can run together in one run.

### 📋 What data can you extract from Google Hotels?

One item per hotel, 92 fields. The rows marked **option** are filled only when you tick the matching option; each option is charged on its own, only when ticked (see Pricing).

| Category                                   | What you get                                                                                                                                                                         |
| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| 🏨 **Hotel**                               | name, Google Hotels link and id, Google Maps link and ids, type (hotel, hostel, resort…), star class, sponsored or not — `Novotel Suites Paris Montreuil Vincennes`, `4-star hotel`  |
| 💰 **Price and taxes**                     | lowest price per night for your stay as Google shows it, the same before taxes, taxes and fees, price with taxes, whole-stay price, currency — `US$106`, `79.53 + 26.91 taxes`      |
| 🔖 **Deals**                               | Google's comparison with the hotel's usual price and its deal badge — `23% less than usual`, `DEAL`                                                                                 |
| 🗓️ **Stay**                                | check-in and check-out dates the prices are for, nights, adults, children's ages, check-in and check-out times — `2:00 PM`                                                          |
| ⭐ **Ratings and review topics**           | guest rating out of 5, number of reviews, breakdown by stars, what guests talk about (breakfast, service, cleanliness…) with positive and negative mentions — `4.0`, `2,982 reviews` |
| 🛎️ **Amenities**                           | amenities offered and those marked as not offered, in English or French (any other language reads English), with Google's stable codes — `Free Wi-Fi`, `Breakfast ($)`, `Pool`                                            |
| 📍 **Location and travel times**           | GPS position, country, Google's location score (transit, restaurants, things to do, airport access), nearby station, airport and places with walk, drive and transit times — `Porte de Montreuil, 9 min walk` |
| 🖼️ **Photos**                              | main photo and the photos of the search result (about 9)                                                                                                                             |
| 🏡 **Vacation rentals**                    | rental type, guests it sleeps, bedrooms, bathrooms, beds, floor area — `Entire apartment`, `323 sq ft`                                                                              |
| 🔎 **Search**                              | position in the results, the search text or name it was found for, the place Google settled on, the search link                                                                     |
| 🧾 **Full hotel profile** (option)         | full address, phone number, long description, neighborhood portrait, highlights, review excerpts, similar hotels nearby, ratings on other review sites, amenities by group, every photo with its author |
| 🏷️ **Price on every booking site** (option) | each booking site Google compares (Booking.com, Expedia, the hotel's own site…): price per night and for the stay, before and after taxes, free cancellation and its deadline, booking link, member price; the cheapest site, the official site's price, the usual price range, a cheaper stay Google points to |
| 🛏️ **Room rates** (option)                 | every room rate: room type, booking site, guests it is for, price per night and for the stay, breakfast, free cancellation, room features                                           |
| 💬 **Full guest reviews** (option)         | rating, date as Google writes it and month of the stay, full text, author, source site (Google, Tripadvisor, Trip.com…), trip type, ratings for rooms / service / location, photos, the hotel's reply |
| 📅 **Price calendar** (option)             | day by day, the lowest price per night for a stay starting that day, before and after taxes, and the days without a price                                                          |

Every field, with an example, is listed in the **Output** section below.

A field of an option you did not tick is `null` (lists included: `offers`, `roomOffers`, `reviews`, `calendar`), never missing, so every row has the same columns.

### ✅ Why use Google Hotels Scraper?

- 🌍 **Many sources in one run**: destinations, search texts, a map area, hotel names, hotel ids and pasted links, each search with its own cap if you want one.
- 🎯 **Google's own filters**: price per night, stars, guest rating, amenities, property types, brands and hotel groups, free cancellation, special offers, eco-certified, and the vacation rental filters (bedrooms, bathrooms, rental amenities).
- 💶 **Prices with and without taxes**: the nightly price as shown in the market you pick, plus the price before taxes, the taxes and fees, and Google's "X% less than usual".
- 🗺️ **Past Google's limit of a search**: a map area cut into a grid reaches every hotel of a big city.
- 📅 **Relative dates**: `14 days` from the run date and a number of nights, so a scheduled task never goes out of date.
- 🧩 **Pay for what you use**: the base row already carries ratings, review topics, amenities and travel times; the profile, booking-site prices, room rates, reviews and calendar are options, unticked by default.
- 🔔 **Monitoring built in**: tick **Only new hotels**, schedule the Actor, and each run saves (and charges) only the hotels it has never delivered before. Add **Price changes** to get a delivered hotel again when its price moves.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…), proxy rotation and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Google Hotels

1. Create a free Apify account.
2. Open **Google Hotels Scraper** and type a **Destination** (a city, region, district or landmark, e.g. `Paris`).
3. Or paste your own Google Hotels links into **Google Hotels links** (search pages: their dates, guests, currency, sort and filters are kept; or single hotel pages), or fill **Hotel names**, **Hotel IDs** or a **Map area**.
4. Pick the stay (**Check-in date**, **Nights**, **Adults**, **Currency**) and set how many hotel listings to save — **Max hotels** (100 by default, 0 = no limit) — and **Max hotels per search** when you run several searches, then click **Start**.
5. Tick the options you want (profile, booking-site prices, room rates, reviews, calendar) and download the dataset in JSON, CSV, Excel or via API.

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

This Actor uses **pay per event** pricing: a price per hotel saved (`apify-default-dataset-item`) plus a small fee per run start (`apify-actor-start`). The exact amounts, for every Apify plan, are on the **Pricing** tab of this page. Platform usage (compute, proxy) is included in the price.

Every option is **unticked by default** and charged only when ticked, per unit it delivers:

| Option                                     | Event          | Charged per                                                              |
| ------------------------------------------ | -------------- | ------------------------------------------------------------------------ |
| **Extract full hotel profile**             | `hotel-details` | hotel whose profile is read                                             |
| **Prices of every booking site**           | `offer`        | booking-site price saved (cap it with **Max booking sites per hotel**)   |
| **Room rates (every room on every site)**  | `room-offer`   | room rate saved (cap it with **Max room rates per hotel**)               |
| **Include reviews**                        | `review`       | review saved (cap it with **Max reviews per hotel**)                     |
| **Price calendar**                         | `calendar-day` | day with a price saved (days with no price are listed free; set the number with **Calendar days**) |
| **Price changes**                          | `price-change` | hotel that comes back because its price moved                            |

A sold-out hotel has no booking-site price and no room rate: it costs nothing for these two options. Most filters are asked from Google Hotels itself, so the hotels they leave out are never read nor charged. A hotel dropped by a check the Actor runs itself (exact rating, minimum number of reviews, price or stars checked again, hotels with a price only, excluded words or ids) costs a small filter fee (`filter-check`) instead of a hotel price, see Pricing. Set the run option **maximum cost per run** to cap what a run can spend: the Actor stops saving rows when the cap is reached.

### ⚙️ Input

Search one destination for a 2-night stay that starts in 30 days:

```json
{
    "location": "Paris",
    "checkIn": "30 days",
    "nights": 2,
    "adults": 2,
    "currency": "EUR",
    "maxItems": 100
}
```

Several destinations × search texts, a cap per search, 4 and 5 stars rated 4.5 or more, free cancellation only:

```json
{
    "locations": ["Rome", "Florence"],
    "searchQueries": ["boutique hotels", "hotels with pool"],
    "maxItemsPerQuery": 50,
    "hotelClass": ["4", "5"],
    "minRating": 4.5,
    "freeCancellationOnly": true
}
```

Every hotel of a map area, cut into a 2 × 2 grid:

```json
{
    "mapArea": { "south": 48.84, "west": 2.28, "north": 48.88, "east": 2.36 },
    "mapAreaGrid": 2,
    "checkIn": "14 days",
    "nights": 3,
    "maxItems": 500
}
```

One brand in a city, cheapest first:

```json
{
    "location": "London",
    "brands": ["Hilton"],
    "sortBy": "lowest_price",
    "maxItems": 100
}
```

Given hotels (by name, id and link) with every option ticked:

```json
{
    "hotelNames": ["Hotel Plaza Athenee Paris"],
    "hotelIds": ["ChkIvOHd86zKwZeBARoML2cvMTF4ZHB2Njd2EAE"],
    "startUrls": [{ "url": "https://www.google.com/travel/hotels/entity/ChcIzp-H4rLs0eRnGgsvZy8xdGYxbjN6OBAB" }],
    "checkIn": "7 days",
    "extractDetails": true,
    "includeOffers": true,
    "includeRoomOffers": true,
    "includeReviews": true,
    "maxReviewsPerHotel": 50,
    "reviewsSort": "newest",
    "includeCalendar": true,
    "calendarDays": 90
}
```

Vacation rentals for a family of four, and a daily monitor of the new hotels:

```json
{
    "location": "Lisbon",
    "stayType": "vacation_rentals",
    "minBedrooms": 2,
    "rentalAmenities": ["kitchen", "wifi"],
    "adults": 4,
    "nights": 5
}
```

```json
{
    "location": "Barcelona",
    "onlyNew": true,
    "stateKey": "barcelona-hotels"
}
```

| Field                                            | Notes                                                                                                                                                                                                                       |
| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `location`, `locations`                          | Destination as typed in the Google Hotels search box: `Paris`, `Tuscany`, `Times Square`. `locations` adds more, one search each (max 500 searches per run). A destination Google cannot find is reported in the log.   |
| `query`, `searchQueries`                         | Words sent before the destination: `boutique hotels`, `hotels near the Louvre`, `pet friendly hotels`. Every text is searched in every destination.                                                                       |
| `startUrls`                                      | Google Hotels search links (`https://www.google.com/travel/search?q=hotels+in+Rome`: dates, guests, currency, sort and filters kept) or hotel links (`https://www.google.com/travel/hotels/entity/ChkIvOHd86zKwZeBARoML2cvMTF4ZHB2Njd2EAE`). |
| `hotelNames`                                     | Hotels named as on Google: `Hotel Plaza Athenee Paris`. Add the city to avoid a namesake elsewhere.                                                                                                                       |
| `hotelIds`                                       | Google Hotels ids, the part of a hotel link after `/entity/`: `ChkIvOHd86zKwZeBARoML2cvMTF4ZHB2Njd2EAE`.                                                                                                                  |
| `mapArea`, `mapAreaGrid`                         | A box on the map, given by its south, west, north and east edges in decimal degrees (first example above); the grid cuts it into N × N boxes (1 to 10) searched one by one and merged without duplicates.             |
| `checkIn`                                        | First night: a date (`2026-12-20`) or a period from the run date (`7 days`, `2 weeks`, `3 months`). Empty = 30 days from the run date. Up to about 330 days ahead.                                                      |
| `checkOut`, `nights`                             | Departure day (`2026-12-23`), at most 30 nights after check-in; empty = check-in plus **Nights** (1 by default).                                                                                                          |
| `childrenAges`, `adults`                         | One age (0-17) per child: `4` and `9`. Adults: 2 by default; 6 guests at most in all, as in Google's guest picker.                                                                                                        |
| `currency`                                       | Currency of every price, among 72: `USD` (default), `EUR`, `JPY`.                                                                                                                                                            |
| `language`                                       | Language of the texts Google returns, among 31: `en` (default), `fr`, `de`.                                                                                                                                                  |
| `country`                                        | Market Google serves the results for, among 47: `us` (default), `gb`, `fr`. It decides whether prices are shown with or without taxes (`priceIncludesTaxes`).                                                              |
| `stayType`                                       | `hotels` (default) or `vacation_rentals`.                                                                                                                                                                                    |
| `sortBy`                                         | `relevance` (default), `lowest_price`, `highest_rating`, `most_reviewed`. With a cap, it picks which hotels are kept.                                                                                                       |
| `maxItems`, `maxItemsPerQuery`                   | Cap for the whole run (100 by default) and for each search; `0` = no limit.                                                                                                                                                 |
| `extractDetails`                                 | Option: full hotel profile (address, phone, long description, every photo, review excerpts).                                                                                                                               |
| `offerProviders`, `includeOffers`, `maxOffersPerHotel` | Option: the price on every booking site, cheapest first, with a cap per hotel; keep only some sites by name: `Booking.com`, `Expedia`, `official` (the hotel's own site).                                              |
| `includeRoomOffers`, `maxRoomOffersPerHotel`     | Option: every room rate, cheapest first, with a cap per hotel (0 = all).                                                                                                                                                    |
| `includeReviews`, `maxReviewsPerHotel`           | Option: full guest reviews, 20 per hotel by default (0 = every review Google serves).                                                                                                                                       |
| `reviewsSort`                                    | `most_relevant` (default), `newest`, `highest_rating`, `lowest_rating`.                                                                                                                                                     |
| `reviewsSource`                                  | `all` (default), `google`, `tripadvisor`, `trip_com`.                                                                                                                                                                        |
| `reviewsTopic`                                   | Only the reviews about one topic of the hotel's review topics: `Breakfast`, `Location`, `Cleanliness`.                                                                                                                      |
| `includeCalendar`, `calendarDays`                | Option: the price calendar, 30 check-in days by default, up to 365.                                                                                                                                                         |
| `minPrice`, `maxPrice`                           | Price per night in **Currency**; `0` = no filter.                                                                                                                                                                            |
| `hotelClass`                                     | Star classes, any of them: `4`, `5`.                                                                                                                                                                                         |
| `minRating`, `minReviewCount`                    | Minimum guest rating out of 5 (`4.5`) and minimum number of reviews.                                                                                                                                                         |
| `amenities`                                      | Hotels that have ALL of them: `free_wifi`, `free_breakfast`, `pool`, `pet_friendly`.                                                                                                                                        |
| `propertyTypes`                                  | Types of hotel, any of them: `boutique`, `resort`, `bed_and_breakfast`.                                                                                                                                                      |
| `freeCancellationOnly`, `specialOffersOnly`, `ecoCertifiedOnly` | Only hotels with free cancellation, with a special offer, or eco-certified.                                                                                                                                    |
| `brands`                                         | Brands or hotel groups named as on Google Hotels: `Hyatt`, `Marriott`, `Accor`, `ibis`. A name Google does not offer for a destination is reported in the log.                                                             |
| `rentalTypes`                                    | Vacation rentals only: `apartment`, `house`, `villa`.                                                                                                                                                                        |
| `minBedrooms`, `minBathrooms`                    | Vacation rentals only, 1 to 5.                                                                                                                                                                                               |
| `rentalAmenities`                                | Vacation rentals that have ALL of them: `kitchen`, `wifi`, `hot_tub`.                                                                                                                                                        |
| `availableOnly`                                  | Leave out the hotels Google lists without any price for your dates.                                                                                                                                                          |
| `excludeKeywords`                                | Drop the hotels whose name contains one of these words: `hostel` (case and accents ignored).                                                                                                                                |
| `excludeHotelIds`                                | Hotel ids to skip: `ChcIzp-H4rLs0eRnGgsvZy8xdGYxbjN6OBAB`.                                                                                                                                                                  |
| `stateKey`, `onlyNew`, `resetState`              | Monitoring: only the hotels never delivered under this memory key (`paris-hotels`); `resetState` forgets the memory.                                                                                                        |
| `trackPriceChanges`, `priceChangeThreshold`      | Price changes (option, needs `onlyNew`): a hotel already delivered comes back when its price per night moved by at least this percentage (default 3, from 0.1 to 100) for the same stay.                                    |
| Advanced                                         | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `minRequestIntervalMs`, `maxRequestRetries`, `debugLog`.        |

### 📦 Output

One real hotel of a Paris search, options off (shortened: lists cut to their first entries, a few fields left out):

```json
{
    "id": "ChcIzp-H4rLs0eRnGgsvZy8xdGYxbjN6OBAB",
    "entityId": "ChcIzp-H4rLs0eRnGgsvZy8xdGYxbjN6OBAB",
    "name": "Novotel Suites Paris Montreuil Vincennes",
    "url": "https://www.google.com/travel/hotels/entity/ChcIzp-H4rLs0eRnGgsvZy8xdGYxbjN6OBAB",
    "pricesUrl": "https://www.google.com/travel/hotels/entity/ChcIzp-H4rLs0eRnGgsvZy8xdGYxbjN6OBAB/prices?hl=en&gl=us&ts=CAESCgoCCAMKAggDEAAaHBIaEhQKBwjqDxALGA4SBwjqDxALGA8YATICEAAqCwoJOgNVU0RiAggB",
    "googleMapsUrl": "https://www.google.com/maps?cid=4135641162393528587",
    "cid": "4135641162393528587",
    "propertyType": "hotel",
    "hotelClass": 4,
    "hotelClassText": "4-star tourist hotel",
    "isVacationRental": false,
    "rating": 4,
    "reviewCount": 2982,
    "ratingBreakdown": [
        { "stars": 5, "percent": 47, "count": 1368 },
        { "stars": 4, "percent": 29, "count": 869 }
    ],
    "locationRating": 3.2,
    "reviewTopics": [
        { "topic": "Breakfast", "shortName": "Breakfast", "mentions": 72, "positive": 44, "negative": 19, "sentiment": 0 }
    ],
    "isAvailable": true,
    "pricePerNight": 106.44,
    "pricePerNightText": "US$106",
    "currency": "USD",
    "priceIncludesTaxes": true,
    "pricePerNightBeforeTaxes": 79.53,
    "taxesPerNight": 26.91,
    "feesPerNight": 18.96,
    "pricePerNightWithTaxes": 106.44,
    "totalPrice": 106.44,
    "deal": "23% less than usual",
    "dealLabel": "DEAL",
    "percentBelowUsual": 23,
    "checkIn": "2026-11-14",
    "checkOut": "2026-11-15",
    "nights": 1,
    "adults": 2,
    "childrenAges": [],
    "checkInTime": "2:00 PM",
    "checkOutTime": "12:00 PM",
    "latitude": 48.8560317,
    "longitude": 2.4152586,
    "countryCode": "FR",
    "description": "Informal all-suite hotel with a laid-back restaurant & a bar, plus an exercise room & free Wi-Fi.",
    "amenities": ["Breakfast ($)", "Free Wi-Fi", "Parking ($)", "Air conditioning", "Pet-friendly", "Fitness center"],
    "amenityCodes": [165, 29, 17, 2, 18, 8],
    "mainImage": "https://lh3.googleusercontent.com/grass-cs/AABkmLeQjiEsHkmer-skjxpL35G7_BYYxzaZCeawdcUxDoJvvVM7yiD-KiEDljF6QCCXrCeO0gvexBj_ZP0qeoqlfIIqesTq2mmTNgugQETOLDNsI4uBbsuTYAN9KUWT7epU84WORjYoxv-RZvE=s287-w287-h192-n-k-no-v1",
    "images": [
        "https://lh3.googleusercontent.com/grass-cs/AABkmLeQjiEsHkmer-skjxpL35G7_BYYxzaZCeawdcUxDoJvvVM7yiD-KiEDljF6QCCXrCeO0gvexBj_ZP0qeoqlfIIqesTq2mmTNgugQETOLDNsI4uBbsuTYAN9KUWT7epU84WORjYoxv-RZvE=s287-w287-h192-n-k-no-v1"
    ],
    "nearbyPlaces": [
        { "name": "Porte de Montreuil", "type": "transit", "travelTimes": [{ "mode": "walk", "text": "9 min", "minutes": 9 }] },
        {
            "name": "Aéroport de Paris-Charles de Gaulle",
            "type": "airport",
            "travelTimes": [
                { "mode": "drive", "text": "25 min", "minutes": 25 },
                { "mode": "transit", "text": "1 hr 23 min", "minutes": 83 }
            ]
        }
    ],
    "isSponsored": false,
    "position": 12,
    "searchQuery": "Paris",
    "resolvedLocation": "Paris",
    "searchUrl": "https://www.google.com/travel/search?q=Paris&ts=CAESCgoCCAMKAggDEAAaHBIaEhQKBwjqDxALGA4SBwjqDxALGA8YATICEAAqCwoJOgNVU0RiAggB&hl=en&gl=us",
    "address": null,
    "phone": null,
    "offers": null,
    "roomOffers": null,
    "reviews": null,
    "calendar": null,
    "scrapedAt": "2026-10-15T07:33:47.966Z"
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### All 92 fields

| Fields                                                                                                                                         | What you get                                                                                                                                                 |
| ---------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`, `entityId`, `name`, `url`, `pricesUrl`                                                                                                   | **Hotel**: Google Hotels id (`id` is a copy of `entityId`, stable from run to run), name, public page, prices page with your stay in the link                 |
| `googleMapsUrl`, `cid`, `featureId`, `kgmid`                                                                                                   | Google Maps link and Google's place ids — `4135641162393528587`, `0x47e66d7e3444894f:0x67c947632c41cfce`, `/g/1tf1n3z8`                                       |
| `propertyType`, `propertyTypes`, `hotelClass`, `hotelClassText`, `isSponsored`                                                                 | `hotel`, `["hotel"]`, `4`, `4-star tourist hotel`, shown as an ad or not                                                                                      |
| `isVacationRental`, `rentalType`, `maxGuests`, `bedrooms`, `bathrooms`, `beds`, `areaText`                                                     | **Vacation rentals**: `true`, `Entire apartment`, `4`, `2`, `1`, `3`, `323 sq ft` (null for a hotel)                                                          |
| `rating`, `reviewCount`, `ratingBreakdown`                                                                                                     | **Ratings**: `4`, `2982`, reviews per star (stars, percent, count)                                                                                           |
| `reviewTopics`                                                                                                                                 | topic, short name, mentions, positive, negative, sentiment — `Breakfast`: 44 positive, 19 negative                                                           |
| `categoryRatings`, `locationRating`                                                                                                            | Google's location score and its parts out of 5 (things to do, restaurants, transit, airport access) — `3.2`                                                  |
| `isAvailable`, `pricePerNight`, `pricePerNightText`, `currency`, `priceIncludesTaxes`                                                          | **Price**: `true`, `106.44`, `US$106`, `USD`, whether the shown price includes taxes                                                                          |
| `pricePerNightBeforeTaxes`, `taxesPerNight`, `feesPerNight`, `pricePerNightWithTaxes`, `totalPrice`                                            | `79.53`, `26.91`, `18.96`, `106.44`, `106.44` (whole stay)                                                                                                   |
| `deal`, `dealLabel`, `percentBelowUsual`                                                                                                       | **Deals**: `23% less than usual`, `DEAL`, `23`                                                                                                               |
| `checkIn`, `checkOut`, `nights`, `adults`, `childrenAges`, `checkInTime`, `checkOutTime`                                                       | **Stay**: `2026-11-14`, `2026-11-15`, `1`, `2`, `[]`, `2:00 PM`, `12:00 PM`                                                                                   |
| `latitude`, `longitude`, `countryCode`, `nearbyPlaces`                                                                                         | **Location**: `48.8560317`, `2.4152586`, `FR`, nearby station, airport and places with walk / drive / transit times                                          |
| `website`, `description`                                                                                                                       | the hotel's own website, Google's one-line summary                                                                                                            |
| `amenities`, `amenitiesUnavailable`, `amenityCodes`, `amenityGroups`                                                                           | **Amenities**: `Free Wi-Fi`, `Breakfast ($)`…, those not offered, Google's codes, every amenity by group (profile)                                           |
| `mainImage`, `images`, `imageDetails`                                                                                                          | **Photos**: first photo, photo URLs (about 9; every photo with the profile), each photo with its category, source and author (profile)                       |
| `position`, `searchQuery`, `resolvedLocation`, `searchUrl`                                                                                     | **Search**: `12`, `Paris`, `Paris`, the search page (null for a hotel given by link or id)                                                                   |
| `address`, `phone`, `descriptionLong`, `neighborhood`, `neighborhoodSummary`, `neighborhoodDescription`                                        | **Full hotel profile** (option): full address, phone number, long description, neighborhood name and Google's texts about it                                 |
| `reviewExcerpts`, `highlights`, `similarHotels`, `otherSiteRatings`                                                                            | **Full hotel profile** (option): review excerpts of the hotel page, highlights, similar hotels nearby, ratings on other review sites                         |
| `offers`, `offerCount`, `cheapestProvider`, `officialSitePricePerNight`                                                                        | **Booking-site prices** (option): one entry per site (provider, official site or not, prices, free cancellation, booking link, member price), how many sites, the cheapest, the official site's price |
| `typicalPriceLow`, `typicalPriceHigh`, `priceLevel`, `pricePosition`, `suggestedStay`                                                          | **Booking-site prices** (option): the usual price range, where your stay sits in it (0 = low end, 1 = high end), a cheaper stay Google points to                |
| `roomOffers`                                                                                                                                   | **Room rates** (option): room name, booking site, price per night and for the stay, guests, breakfast, free cancellation, features                            |
| `reviews`, `reviewsIncomplete`                                                                                                                 | **Full guest reviews** (option): rating and its scale, date, month of stay, text, author, source, trip type, sub-ratings, photos, the hotel's reply; `true` when some reviews could not be read |
| `calendar`                                                                                                                                     | **Price calendar** (option): date, lowest price per night, before taxes, taxes and fees, with taxes                                                          |
| `previousPrice`, `priceChange`, `priceChangePct`, `priceChangedAt` | **Price changes** (option, with Only new hotels): the price per night before, the change, the change in percent, when this run noticed it |
| `scrapedAt`                                                                                                                                    | ISO timestamp of the extraction                                                                                                                              |

### 💡 Tips

#### How to get more results

Google Hotels stops a search near 800 to 1,000 hotels. For a big city, draw a **Map area** around it and set **Split the map area into a grid** (`mapAreaGrid`) to 3 or more: each box is searched on its own and the hotels are merged without duplicates. The **Market** (`country`) of the destination often gives the longest list.

#### How to reduce costs

The price is per hotel saved, so the levers are `maxItems`, `maxItemsPerQuery`, the filters (asked from Google, so the other hotels are never read) and `onlyNew` for recurring runs (you never pay twice for the same hotel). For the options, cap what each hotel brings: `maxOffersPerHotel` or `offerProviders` for the booking sites (`offers` only, not `roomOffers`), `maxRoomOffersPerHotel`, `maxReviewsPerHotel` and `calendarDays`.

#### Several searches in one run

Fill `searchQueries` and / or `locations`: the Actor runs one search per text × destination (3 texts × 4 destinations = 12 searches, up to 500 per run). The single `query` and `location` fields still work and are added to the lists, and hotel names, ids, links and the map area run in the same run. A hotel found by several searches is saved — and charged — once. Set `maxItemsPerQuery` to give every search its own cap: without it the first searches can use up the whole `maxItems` budget.

#### Monitoring: only the new hotels

Tick **Only new hotels** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the hotels already delivered: they are not saved, not charged, and the page of a hotel found by a search is not even opened (a hotel given by id, link or name is read before it is known as delivered, then neither saved nor charged). The memory lives in a named key-value store of your account (`google-hotels-scraper-seen`, up to 150,000 listings per key) and is only updated with hotels that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's hotels), and tick `resetState` once to start over.

Tick **Price changes** (`trackPriceChanges`) as well and a hotel already delivered comes back, whole, when its price per night has moved by at least **Price change threshold (%)** (3 % by default) since the run that delivered it, for the same stay (same dates, guests, currency and market). The row carries `previousPrice`, `priceChange`, `priceChangePct` and `priceChangedAt`; it is charged the hotel price plus the `price-change` event, a hotel whose price did not move enough is skipped free, and a hotel with no price is never a change. The first run after you tick it learns the prices and reports no change. Use fixed dates (for example `2026-12-20`): a relative check-in such as `14 days` moves the stay at every run, so its prices are learned again instead of compared. Because any hotel of a search can change its price, each search is read to its last page (1,000 hotels per search at most), where **Only new hotels** alone stops after 20 pages with nothing new: such a run takes longer. The prices are kept next to the ids, in the same store (up to 150,000 prices per key).

#### Follow prices over time

To be told only when a price moves, tick **Only new hotels** and **Price changes** (above). To keep the whole series instead, leave **Only new hotels** off and schedule a task with a relative check-in (`14 days`) and a number of nights: every run prices the same stay length the same distance ahead, and each row carries its price and `scrapedAt`. Tick **Price calendar** to get, for each hotel, the price of every check-in day of the coming weeks or months in one row.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Google Hotels hotel. Actor id: `nice_dev/google-hotels-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/google-hotels-scraper`.

Smallest input, for a cheap first call:

```json
{
    "location": "Paris",
    "maxItems": 10
}
```

Key output fields: `name`, `pricePerNight`, `currency`, `rating`, `reviewCount`, `hotelClass`, `latitude`, `longitude`.

Cost: a price per hotel saved plus a small fee per run start, and the options per unit delivered, see the pricing section above and the **Pricing** tab. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Google Hotels?

The Actor only reads what Google Hotels shows publicly to any anonymous visitor. It logs in to nothing and solves no captcha. Results are mostly business data about hotels; with **Include reviews** they also contain the public name, profile link and photos of the reviewers, which are personal data protected by GDPR: do not store them without a legitimate reason. You are responsible for using the data in compliance with Google's Terms of Service and applicable law. This Actor is not affiliated with Google.

#### Does it need a login or a proxy?

No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).

#### Are the prices the ones I see on Google Hotels?

They are the prices Google Hotels shows to a visitor who is not logged in, for the stay, guests, currency and market you asked for. The market (`country`) decides how the nightly price is shown — before taxes in the United States, taxes included in most other countries — and `priceIncludesTaxes` tells which; `pricePerNightBeforeTaxes`, `taxesPerNight` and `pricePerNightWithTaxes` give both sides when Google gives them. Prices are live: two runs a few minutes apart can differ.

#### Is the data safe to open in Excel or to show on a web page?

Names, descriptions and review texts are written by hotels and guests, copied as they are. A text can begin with `-`, `+`, `=` or `@`: Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import the text columns as text. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- **Dates**: with no check-in date the stay starts 30 days after the run date and lasts 1 night (or the **Nights** you set). Google Hotels prices stays up to about 330 days ahead and up to 30 nights: a later date is refused. Calendar days past that horizon come without a price.
- **One row per hotel and per run**: the same hotel given twice in **Google Hotels links** with two stays, or found by two searches with different dates, comes out once, with the stay of the first link or search that reads it (the log names a link left out). To compare two stays, run twice.
- **Pasted links and dates**: a Google Hotels link keeps the dates it was copied with, and a link whose check-in date is past is refused (the whole run stops with that message): in a scheduled task, use **Check-in** `14 days` or paste a fresh link.
- **Guests**: 6 guests at most (adults + children), at least 1 adult, as in Google's guest picker. Google Hotels has no number of rooms.
- **Reviews**: Google gives the date of a review as it writes it (`2 months ago`) and the month of the stay, not an exact date. One hotel row holds about 6,000 reviews at most (a larger row could not be saved), whatever **Max reviews per hotel** says: read a bigger hotel in several runs with `reviewsSource` or `reviewsTopic`. `reviewsIncomplete` is `true` when some of the reviews asked for were left out: a page that could not be read, the row full, or the run's maximum cost reached.
- **Hotel by name**: the hotel Google settles on for the name is read; add the city to avoid a namesake elsewhere. A hotel given by link or id has no `position` nor `searchUrl`; a hotel given by name has `position` 1 and the `searchUrl` of its name search.
- **Hotels and vacation rentals**: hotel filters are ignored in a vacation rental search and the other way round (the log warns).
- **Brands**: a brand is matched against the brands Google offers for the destination; one it does not offer is reported in the log and the search runs without it.
- **Hotels without a price** (sold out, no booking site) are saved with `isAvailable: false` and no price, unless `availableOnly` is ticked. Google Hotels shows no price at all for Cuba, Iran, North Korea, Sudan and Syria: a search there is not a failure, its hotels come without a price.
- **Order of the rows**: with hotel details on (any option ticked), rows are saved as each page finishes: sort by `position` to get Google's order.
- **Price changes** compares a hotel with the price it had when it was delivered, for the same stay only: a different stay (dates, guests, currency, market) is learned again, not compared, and a hotel with no price is never a change. `onlyNew` alone does not look at prices.
- Two runs sharing the same `stateKey` at the same time may both return the same new hotel.

**A run that reaches its timeout** stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with `onlyNew`, remembered, and the run ends *Succeeded* with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).

**A run the platform stops without warning** (out of memory)

- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the hotels already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the hotels it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the hotels of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the hotels saved, filtered out and no longer on Google Hotels, and the requests that failed after every retry. Those requests are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A destination, hotel name or hotel id Google does not know is reported as a source of the input not found, and the other sources are read. A run that saved nothing and had failed requests fails, and its last message gives the cause.

If Google Hotels changes its pages, you are told instead of paying for blank rows. If the first 20 listings read all lack their name, their GPS position, their main photo, the rating of a hotel that has reviews or — with **Extract full hotel profile** — the address of a hotel, or if not one of them has a price per night (a sold-out hotel has none, but not all 20; the hotels of Cuba, Iran, North Korea, Sudan and Syria, where Google Hotels shows no price at all, are not counted), the run saves nothing more, stops and fails, and its last message names the missing field: at most those first hotels are charged. A hotel that `minRating` or `minReviewCount` drops because it has no rating at all counts among those 20. A run of fewer hotels (a scheduled `onlyNew` run that finds a few new ones, a small **Max hotels**) is checked at its end, from 5 listings (the price from 20): its hotels are already saved, and the run fails with the missing field instead of ending green.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly which requests failed and why.

# Actor input Schema

## `location` (type: `string`):

A city, region, district or landmark, as typed in the Google Hotels search box (e.g. `Paris`, `Tuscany`, `Times Square`). Google resolves it the way its own search does; the place it settled on is in `resolvedLocation`, and a destination Google cannot find is reported in the log instead of returning hotels from somewhere else. Empty = no destination from this field.

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

Several destinations in one run: one search per destination (times each search text below; destinations × search texts max 500). Added to **Destination**. Hotels found by several searches are saved once.

## `query` (type: `string`):

Optional words sent to Google Hotels before the destination, exactly as you would type them (e.g. `boutique hotels`, `hotels near the Louvre`, `pet friendly hotels`). With a destination, the search is `<search text> <destination>`; alone, it is sent as is. Empty = hotels of the destination.

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

Several search texts in one run: every text is searched in every destination (3 texts × 4 destinations = 12 searches, max 500). Added to **Search text**.

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

Google Hotels search links copied from the address bar (`https://www.google.com/travel/search?q=...&ts=...`): their search text, dates, guests, currency, sort and filters are kept and pagination is automatic - or single hotel links (`https://www.google.com/travel/hotels/entity/<id>`, with or without `/prices`, `/reviews`). Added to the destinations and hotels of this form: all of them run together. Max 1 000 links.

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

Hotels named as you would type them on Google (e.g. `Hotel Plaza Athenee Paris`): each name is looked up on Google Hotels and the hotel it settles on is read, with its price for your dates. Add the city to the name to avoid a namesake elsewhere. Added to the other sources.

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

Google Hotels ids (the `entityId` of a result, e.g. `ChkIvOHd86zKwZeBARoML2cvMTF4ZHB2Njd2EAE`, the part of a hotel link after `/entity/`): each hotel is read with its price for your dates. Added to the other sources.

## `mapArea` (type: `object`):

Search the hotels inside a box drawn on the map, like moving the Google Hotels map and pressing **Update list**: `{"south": 48.876, "west": 2.326, "north": 48.896, "east": 2.356}` (decimal degrees). Used alone, it searches every hotel of the box; with a **Destination** or **Search text**, the box wins over the place named in the text. Empty = no box.

## `mapAreaGrid` (type: `integer`):

Cut the **Map area** into N × N smaller boxes searched one by one, then merged without duplicates: Google stops a search near 800-1,000 hotels, so a big city needs a grid to reach every hotel. 1 = one search for the whole box.

## `checkIn` (type: `string`):

First night: a date (`2026-12-20`), or a period from the run date such as `7 days`, `2 weeks` or `3 months` - a saved task then always looks the same distance ahead. Empty = 30 days from the run date. Google Hotels shows prices up to about 330 days ahead: a later date is refused.

## `checkOut` (type: `string`):

Departure day, `YYYY-MM-DD`. Empty = check-in plus **Nights** (the way to keep the length of a stay whose check-in moves with the run date). Must be after the check-in date, at most 30 nights after it.

## `nights` (type: `integer`):

Length of stay, used when **Check-out date** is empty.

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

Adults for the stay, as in the Google Hotels guest picker: at most 6 guests in all (adults + children). The number of guests changes the prices.

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

One age (0-17) per child, e.g. `4` and `9` for two children. Empty = no children. Google prices the stay for these ages; adults + children = 6 at most.

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

Currency of every price (Google converts it). A search link pasted in **Google Hotels links** keeps its own currency.

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

Language of the texts Google returns (hotel type, descriptions, review topics, deal wording; amenity names come in English or French, any other language reads English). Field names and numbers do not change.

## `country` (type: `string`):

Country Google Hotels serves the results for (its `gl` market). It decides how prices are shown - in the United States before taxes, in most other countries with taxes included (`priceIncludesTaxes` tells which) - and can change how many hotels Google lists: the market of the destination often gives the longest list.

## `stayType` (type: `string`):

`hotels` = the Hotels tab of Google Hotels (hotels, hostels, B\&Bs, apartment hotels...); `vacation_rentals` = its Vacation rentals tab (apartments, houses, villas...), with bedrooms, bathrooms, beds and size on each row. Hotel names, ids and links are read whatever this is.

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

Order of the hotels, as on Google Hotels. With a cap on the number of hotels, it picks which ones are kept.

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

Maximum number of hotels to save for the whole run (after deduplication and filters). 0 = no limit. Google Hotels lists up to about 800-1 000 hotels per search.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH search (search text × destination, or search link), so that the first search cannot use up the whole **Max hotels** budget. 0 = no per-search cap.

## `extractDetails` (type: `boolean`):

Full address, phone number, long description, every photo with its author and the review excerpts Google shows on the hotel page. Off = search-result fields only (name, stars, price, rating, amenities, GPS, website, a few photos).

## `includeOffers` (type: `boolean`):

Add the price of the stay on every booking site Google compares for the hotel (`offers`, often 15-30 sites): site name, official hotel site or not, price per night and for the stay, before and after taxes, free cancellation and its deadline, booking link; plus Google's usual price range for the hotel (`typicalPriceLow` / `typicalPriceHigh`). Charged per site price saved.

## `maxOffersPerHotel` (type: `integer`):

Cap on the booking-site prices saved for each hotel, cheapest first. 0 = every site Google lists.

## `offerProviders` (type: `array`):

Keep only the prices of these booking sites (`Booking.com`, `Expedia`, `Hotels.com`, the hotel's own site as `official`...), as Google names them; case and accents ignored. Empty = every site. Fewer sites saved = fewer `offer` events charged. It applies to `offers` only: the room rates (`roomOffers`) keep every site.

## `includeRoomOffers` (type: `boolean`):

Add every room rate Google lists for the stay (`roomOffers`): room type, booking site, price, free cancellation deadline. Charged per room rate saved.

## `maxRoomOffersPerHotel` (type: `integer`):

Cap on the room rates saved for each hotel, cheapest first. 0 = every rate Google lists.

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

Add the guest reviews Google shows for each hotel (`reviews`): rating, date as Google writes it (`2 months ago`) and month of the stay, full text, author, source site (Google, Tripadvisor, Trip.com...), trip type, ratings for rooms / service / location, photos, and the hotel's reply. Charged per review saved. Off = only the rating, the review count, the rating breakdown and the review topics (always included).

## `maxReviewsPerHotel` (type: `integer`):

Cap on the reviews saved for each hotel. 0 = every review Google serves, up to about 6,000 reviews: one hotel row holds no more than that (a larger row could not be saved), whatever the number set here; the row then says reviewsIncomplete. Each review saved is charged on its own.

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

Order of the saved reviews: with the cap on reviews per hotel, it picks which ones are kept.

## `reviewsSource` (type: `string`):

Keep only the reviews from one site. `all` = every source Google gathers (Google, Tripadvisor, Trip.com...).

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

Keep only the reviews about one topic, named as in the hotel's `reviewTopics` (e.g. `Breakfast`, `Location`, `Cleanliness`). Empty = every review.

## `includeCalendar` (type: `boolean`):

Add, day by day from the check-in date, the lowest price Google shows for a stay of **Nights** starting that day, before and after taxes (`calendar`). The days that have no price (the hotel is full, or the date is past what Google prices) are listed too, and free. Up to a year in one request per hotel. Charged per day with a price saved.

## `calendarDays` (type: `integer`):

Number of check-in days of the price calendar, counted from the check-in date. Google prices up to about 330 days ahead: later days come without a price.

## `minPrice` (type: `integer`):

Keep hotels whose price per night is at least this, in **Currency**. 0 = no filter. Asked from Google Hotels.

## `maxPrice` (type: `integer`):

Keep hotels whose price per night is at most this, in **Currency**. 0 = no filter. Asked from Google Hotels.

## `hotelClass` (type: `array`):

Keep only hotels of these star classes (any of them). Asked from Google Hotels. Empty = every class, unrated places included.

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

Keep hotels whose guest rating (out of 5) is at least this. 0 = no filter. Google Hotels is asked for its step just below (3.5+, 4.0+ or 4.5+), then the exact rating is checked. Hotels without any review are dropped when this is set.

## `minReviewCount` (type: `integer`):

Keep hotels with at least this many reviews. 0 = no filter.

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

Keep only hotels that have ALL the ticked amenities (Google Hotels' own amenity filters). Asked from Google Hotels. Empty = no filter. Hotels search only (see **Rental amenities** for vacation rentals).

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

Keep only these types of hotel (any of them). Asked from Google Hotels. Empty = every type. Hotels search only (see **Rental types** for vacation rentals).

## `freeCancellationOnly` (type: `boolean`):

Keep only hotels with at least one offer that can be cancelled free of charge. Asked from Google Hotels.

## `specialOffersOnly` (type: `boolean`):

Keep only hotels with a special offer (deal, discount) for your dates. Asked from Google Hotels.

## `ecoCertifiedOnly` (type: `boolean`):

Keep only hotels with an eco-certification Google shows. Asked from Google Hotels.

## `brands` (type: `array`):

Keep only hotels of these brands or hotel groups, named as on Google Hotels (e.g. `Hyatt`, `Marriott`, `Accor`, `ibis`). Each name is matched against the brands Google offers for the search, then asked from Google Hotels; a name Google does not offer for a destination is reported in the log. Empty = every brand.

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

Vacation rentals only: keep these types of rental (any of them). Asked from Google Hotels. Empty = every type.

## `minBedrooms` (type: `integer`):

Vacation rentals only: at least this many bedrooms (Google's steps, 1 to 5). 0 = no filter. Asked from Google Hotels.

## `minBathrooms` (type: `integer`):

Vacation rentals only: at least this many bathrooms (1 to 5). 0 = no filter. Asked from Google Hotels.

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

Vacation rentals only: keep the rentals that have ALL the ticked amenities. Asked from Google Hotels. Empty = no filter.

## `availableOnly` (type: `boolean`):

Leave out the hotels Google lists without any price for your dates (sold out or no booking site). Off = they are saved with `isAvailable: false` and no price.

## `excludeKeywords` (type: `array`):

Drop the hotels whose name contains one of these words (case and accents ignored).

## `excludeHotelIds` (type: `array`):

Google Hotels ids (`entityId`) to skip, even when they match the search (e.g. your own hotels).

## `onlyNew` (type: `boolean`):

Skip the hotels that a previous run (same **Memory key**) already delivered: they are not saved and not charged, and the page of a hotel found by a search is not even opened (a hotel given by id, link or name is read before it is known as delivered). First run = everything is new. To follow prices, leave it off and schedule the task: every row carries its price and `scrapedAt`.

## `trackPriceChanges` (type: `boolean`):

Needs **Only new hotels**. A hotel already delivered under this **Memory key** comes back, whole, when its price per night has moved by at least the **Price change threshold (%)** since the run that delivered it, for the same stay (same dates, guests, currency and market): `previousPrice`, `priceChange`, `priceChangePct` and `priceChangedAt` are filled. Charged per hotel that comes back as **Price change**, on top of the hotel itself, see Pricing; a hotel whose price did not move enough is skipped and costs nothing, and a hotel with no price is never a change. Use fixed dates (for example `2026-12-20`): a relative check-in such as `14 days` moves the stay at every run, so its prices are learned again instead of compared. The first run after you tick it learns the prices and reports no change. Each search is read to its last page (1,000 hotels per search at most) because any hotel of it can change its price: a run takes longer than with **Only new hotels** alone, which stops after 20 pages with nothing new. Unticked (default) = the four columns are always null and nothing is charged.

## `priceChangeThreshold` (type: `number`):

Used with **Price changes**. How far a price per night must move, up or down, from the price delivered for the hotel to come back: 3 means a price that goes from 100 to 103 or to 97. From 0.1 to 100.

## `stateKey` (type: `string`):

Name of the memory used by **Only new hotels**. Give each schedule / task its own key (e.g. `paris-hotels`) so that they do not share their memory. Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every hotel again. Untick it afterwards.

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

Apify Proxy or your own proxies. Keep the default: it is included in the price. The residential Apify proxy is not available in this Actor.

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

Maximum number of requests processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Most requests to Google in any 60 seconds, all of them counted: result pages, hotel pages, review and calendar pages. A budget, not an even pace: up to this many can leave at once when the minute starts (spread them with the minimum delay below). Lower it if the log shows Google's "unusual traffic" page.

## `minRequestIntervalMs` (type: `integer`):

Smallest gap between two requests, in milliseconds. Unlike the per-minute rate, this spreads the requests evenly instead of letting them go out in a burst. 0 = no gap.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed. Behind a proxy, a request Google turns away is also retried on a new proxy session up to 10 times without using up these retries.

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "location": "Paris",
  "locations": [],
  "searchQueries": [],
  "startUrls": [],
  "hotelNames": [],
  "hotelIds": [],
  "mapArea": {
    "south": 48.876,
    "west": 2.326,
    "north": 48.896,
    "east": 2.356
  },
  "mapAreaGrid": 1,
  "nights": 1,
  "adults": 2,
  "childrenAges": [],
  "currency": "USD",
  "language": "en",
  "country": "us",
  "stayType": "hotels",
  "sortBy": "relevance",
  "maxItems": 20,
  "maxItemsPerQuery": 0,
  "extractDetails": false,
  "includeOffers": false,
  "maxOffersPerHotel": 0,
  "offerProviders": [],
  "includeRoomOffers": false,
  "maxRoomOffersPerHotel": 0,
  "includeReviews": false,
  "maxReviewsPerHotel": 20,
  "reviewsSort": "most_relevant",
  "reviewsSource": "all",
  "includeCalendar": false,
  "calendarDays": 30,
  "minPrice": 0,
  "maxPrice": 0,
  "hotelClass": [],
  "minRating": 0,
  "minReviewCount": 0,
  "amenities": [],
  "propertyTypes": [],
  "freeCancellationOnly": false,
  "specialOffersOnly": false,
  "ecoCertifiedOnly": false,
  "brands": [],
  "rentalTypes": [],
  "minBedrooms": 0,
  "minBathrooms": 0,
  "rentalAmenities": [],
  "availableOnly": false,
  "excludeKeywords": [],
  "excludeHotelIds": [],
  "onlyNew": false,
  "trackPriceChanges": false,
  "priceChangeThreshold": 3,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 8,
  "maxRequestsPerMinute": 120,
  "minRequestIntervalMs": 0,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

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

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "location": "Paris",
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/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 = {
    "location": "Paris",
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("nice_dev/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 '{
  "location": "Paris",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call nice_dev/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

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