# Google Hotels Scraper - Nightly Rates & OTA Price Comparison (`mitul_kheni/google-hotels-scraper`) Actor

Hotel rates from Google Hotels for any city or hotel, by date, guests and currency - with the price from Booking.com, Expedia, Agoda, the hotel's own site and more for every hotel.

- **URL**: https://apify.com/mitul_kheni/google-hotels-scraper.md
- **Developed by:** [Mitul Kheni](https://apify.com/mitul_kheni) (community)
- **Categories:** Travel
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $2.80 / 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 - Nightly Rates & OTA Price Comparison

Get hotel prices from Google Hotels for any city or hotel as a spreadsheet: the nightly rate for **your** dates, guests and currency,
plus what Booking.com, Expedia, Agoda, the hotel's own site and other booking sites charge for the same stay. No coding, no browser, no login.

### What you can do with this

- **Rate-shop competitors every day** and see exactly which hotels changed price since yesterday
- **Compare booking sites for one hotel**: who is cheapest, and how much more the official site costs
- **Build a price history** per hotel and stay, with a stable key that never changes between runs
- **Feed a spreadsheet, dashboard or alert** with clean rows: price per night, taxes and fees split out, ratings, location

### What you get

| name | class | rating | price / night | total for the stay | cheapest site | official site |
| --- | --- | --- | --- | --- | --- | --- |
| Glint Paris | - | 4.5 | 61.06 | 72.99 | Booking.com 61 | 104 |
| Avre Hotel | 3 | 4.4 | 128.08 | 142.23 | KAYAK.com 128 | 140 |
| The Hoxton, Paris | 4 | 4.4 | 309.60 | 338.61 | Super.com 310 | - |
| Grand Hôtel du Palais Royal | 5 | 4.7 | 516.41 | 565.50 | Traveluro 516 | 685 |
| Four Seasons Hotel George V, Paris | 5 | 4.8 | 1937.06 | 2127.02 | Super.com 1937 | 2105 |

*(real output through the default US proxy, Paris, 1 night, 2 adults, USD; there `price / night` is the price Google shows, without taxes, and `total for the stay` includes taxes and fees - see "Prices and taxes" below)* - every hotel also has its full list of booking sites, address, coordinates, photos,
tax/fee breakdown, review counts and more. Download as Excel, CSV, JSON or pull it through the API.

### How to use it

1. Type one or more **destinations or hotel names** ("Paris", "Hyatt Regency Paris Etoile").
2. Choose **check-in dates** (`2026-12-24`, or `+30` = 30 days from today, which keeps a daily schedule working forever), **nights**, **guests** and **currency**.
3. Set **Max hotels per search** to control your cost, then click **Start**.

### Pricing

**$3.50 per 1,000 hotels** - you pay per hotel saved, not per booking site and not per page. A 20-hotel search costs about 7 cents.
Every run also pays Apify's standard start fee of $0.00005 per GB of memory (the default 1 GB run pays $0.00005, which is $0.05 per 1,000 runs).
Hotels that Google shows without a price are not returned (and not charged) unless you ask for them. If the run's spending limit is reached,
it stops cleanly and never charges past it.

### What makes the data trustworthy

- **Exact dates, currency, guests.** Every response is checked against what you asked for. If Google silently moves your dates, switches the
  currency or prices different guests, you get a clear error for that search - never wrong data.
- **No "close enough" hotels.** If your filters match nothing you are told which filters to loosen, not shown unrelated results.
- **Honest empties.** A run that finds nothing explains why (unknown place, no prices for these dates, language problem...) instead of finishing silently empty.
- **Changes since last run.** `changedSinceLastRun`, `previousPrice` and `priceChange` are filled automatically on scheduled runs. `changedSinceLastRun` is `true` when the headline price **or any booking-site price** changed, so it can be `true` while `priceChange` is 0; `priceChange` and `priceChangePercent` compare the headline price only.
- **Stable keys.** `stayKey` = hotel + dates + guests + currency, identical on every run, ready for upserts.

### Settings

| Setting | What it does |
| --- | --- |
| Destinations or hotel names | Places or specific hotels, exactly as you would type them in Google Hotels |
| Check-in dates, Nights | Every destination is searched for every check-in date (1-30 nights; prices exist up to about 330 days ahead) |
| Adults, Children's ages | Prices are for this group (1-12 adults, ages 0-17) |
| Currency, Language, Country | `USD`, `EUR`, `INR`...; names/labels language; Google's country site |
| Max hotels per search | Hard cap per destination and date (1-500) |
| Include the price from each booking site | One extra request per hotel; switch off for a faster, cheaper run |
| Sort, Star ratings, Guest rating, Price range, Free cancellation, Special offers | Applied by Google itself (the price range applies to `price`, which may not include taxes: see "Prices and taxes" below) |
| Flag changes since the last run | Keeps the last prices in a storage in your account (name configurable) |
| Include vacation rentals / hotels without a price | Off by default |
| Proxy configuration | Datacenter proxies in the US by default; use the RESIDENTIAL group for another country (see below) |

### Output fields

| Field | Meaning |
| --- | --- |
| `name`, `hotelId`, `propertyType` | Hotel name; Google's stable id; `hotel` or `vacation_rental` |
| `hotelClass`, `hotelClassLabel`, `rating`, `reviewCount`, `reviewsByStars` | Stars (null for hostels), guest rating, review counts per star |
| `address`, `latitude`, `longitude`, `countryCode` | Location (address needs the booking-site option) |
| `description`, `websiteUrl`, `checkInTime`, `checkOutTime`, `thumbnailUrl`, `imageUrls` | Details |
| `price`, `currency`, `priceDisplay` | The **average nightly price exactly as Google shows it**. Whether it includes taxes depends on the proxy's country: see "Prices and taxes" below |
| `priceIncludesTaxesAndFees`, `priceBasis` | `true` when `price` includes taxes and fees, `false` when it does not, `null` when Google gave no breakdown; `priceBasis` says the same in words |
| `totalPrice` | The whole stay **including taxes and fees** (Google's breakdown total; if Google gives no breakdown it is `price` x `nights`) |
| `priceBase`, `priceTaxes`, `priceFees` | Nightly room rate, taxes and fees; together they make `totalPrice` / `nights` |
| `dealText`, `dealPercent` | Google's "17% less than usual" badge, when present |
| `offers[]` | Per booking site: `provider`, `price`, `isOfficialSite`, `isLowest`, `rank`; cheapest first |
| `cheapestOffer`, `officialSiteOffer`, `offersCount`, `offersStatus` | Shortcuts; `ok`, `unavailable` (Google lists none), `failed`, `not_requested` |
| `offersMatchHeadlinePrice` | Cheapest booking site equals Google's headline price (some sites omit fees, so this can be `false`) |
| `checkIn`, `checkOut`, `nights`, `adults`, `childrenAges` | The stay that was priced |
| `stayKey` | Stable key: `hotelId|checkIn|checkOut|guests|currency` |
| `changedSinceLastRun`, `previousPrice`, `priceChange`, `priceChangePercent` | Difference to the previous run for the same `stayKey` (`null` = first time). `changedSinceLastRun` is `true` if the headline price or any booking-site price changed; `priceChange` / `priceChangePercent` are for the headline price only |
| `searchQuery`, `destinationName`, `position`, `page`, `sortBy` | Where the hotel came from and its rank in Google's list |
| `requestedLanguage`, `responseLanguage`, `languageFallback` | Language bookkeeping |
| `scrapedAt` | UTC timestamp |

### Good to know

- **Prices and taxes: check `priceIncludesTaxesAndFees`.** `price` is the nightly price exactly as Google shows it, and what it contains depends on
  the country Google sees. With the default US proxy it is usually the room rate plus mandatory fees and does **not** include taxes (for example a
  Paris hotel: 128.08 per night, 142.23 for the stay with taxes); in our test from an Indian IP it included taxes, and other countries were not
  tested. Every row says which case it is: `priceIncludesTaxesAndFees` is `true` or `false`, and `priceBasis` says it in words. **`totalPrice` is the
  whole stay including taxes and fees**, so use it (or `totalPrice` / `nights`) when you need numbers that are comparable across runs and countries.
  The price range filter works on `price`, not on `totalPrice`. Booking-site prices are per night, shown to the whole currency unit, and some
  sites leave out taxes or fees.
- **Which booking sites appear depends on the proxy country**, not on the Country field: US proxies list US sites (Booking.com, Expedia...),
  other countries list local ones. The default - Apify datacenter proxies in the US - is the cheapest and was not blocked in our tests.
  Datacenter pools do not cover every country: in our tests only the US had datacenter IPs, and asking for another country stopped the run
  at once with `PROXY_ERROR` ("no usable proxies from country ..."). For another market's booking sites select the **RESIDENTIAL** proxy
  group in *Proxy configuration* (more expensive: roughly 70 MB of proxy traffic per 1,000 hotels with booking-site prices).
- **About 200-250 hotels per search is the most Google exposes** (a search for Paris stops around 190-245 hotels). To cover a bigger area, split it
  with star ratings or price ranges. Sorting by *Lowest price* gives the most stable lists.
- **Some destination + language pairs return nothing at Google** (e.g. "Paris" in Spanish). The Actor retries in English and marks those rows `languageFallback: true`.
- Stays are limited to **30 nights** and check-in to about **330 days** ahead - Google has no prices beyond that.
- Amenity lists are not included (Google does not expose their labels). Vacation rentals are experimental and have no booking-site list.

### Support

Found a problem or a missing field? Open an issue on the Issues tab - issues are answered within 24 hours on weekdays (Monday to Friday; weekends are excluded). When Google changes its response format, the fix is made as soon as possible.
Need a custom field, a different destination type or a scheduled export? Ask for custom work on the profile.

### Notes

This Actor reads only publicly visible hotel names, locations, ratings and prices - no login, no personal data. It requests a single data endpoint,
checks Google's `robots.txt` at the start of every run and stops if that endpoint is ever disallowed.

If Google ever changes its response format, the Actor stops instead of guessing prices, and keeps a copy of the answer that confused it in the run's key-value store (the records `FAILURE_SAMPLE_1` and `FAILURE_SAMPLE_1_BODY`, at most 3 per run, only when something like this happens). Attach them when you report the problem and the fix is much faster. They contain only Google's answer and your search settings.

### Responsible use

- **Independent tool, not affiliated with Google.** "Google" and "Google Hotels" are trademarks of Google LLC. This Actor is not endorsed by, or connected to, Google or any hotel or booking site.
- **The data belongs to others.** Hotel names, descriptions, photos and prices originate with hotels and booking sites (shown via Google Hotels). You are responsible for having the right to use them for your purpose, for example before you publish photos or descriptions or resell the data.
- **You are responsible for how you use the Actor and its data**, including the laws that apply to you and the terms of the services involved. The Actor checks `robots.txt`, never logs in and does not solve CAPTCHAs, but that does not replace your own compliance check.
- **Prices are a snapshot, not an offer.** They are what Google showed when the request was made, for the dates and guests you chose. Availability and the final price on the booking site can differ, so check before you book or quote.

# Actor input Schema

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

One or more cities, regions, landmarks or specific hotels, exactly as you would type them into Google Hotels. Examples: <code>Paris</code>, <code>Bali</code>, <code>Hotels near JFK airport</code>, <code>Hyatt Regency Paris Etoile</code>. A hotel name returns that one hotel; a place returns up to <b>Max hotels per search</b> hotels. Coordinates and URLs are not supported.

## `checkInDates` (type: `array`):

Dates as <code>YYYY-MM-DD</code> (e.g. <code>2026-12-24</code>), <code>today</code>, <code>tomorrow</code>, or <code>+N</code> = N days from today (e.g. <code>+30</code>). Relative dates keep scheduled daily runs working forever. Google has prices up to about <b>330 days</b> ahead; later dates are rejected.

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

Length of stay, 1 to 30 nights (Google returns no prices for longer stays). Prices are always the average nightly price.

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

Number of adults (1-12). Prices are for this group size; more guests usually means more rooms.

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

One age per child, 0-17 (0 = under 1 year), up to 8 children. Example: <code>\[5, 9]</code>. Leave empty for no children.

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

ISO 4217 code, e.g. <code>USD</code>, <code>EUR</code>, <code>GBP</code>, <code>INR</code>, <code>JPY</code>. Prices come back in exactly this currency, or the search fails with a clear message - they are never silently converted to another currency.

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

Language of hotel names and labels (Google's <code>hl</code>), e.g. <code>en</code>, <code>fr</code>, <code>pt-BR</code>. Some destinations return nothing in some languages (e.g. "Paris" in Spanish); the Actor then retries in English and marks the rows with <code>languageFallback</code> (switch off below).

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

Two-letter country code sent to Google (<code>gl</code>), e.g. <code>us</code>, <code>gb</code>, <code>in</code>. Note: <b>which booking sites are listed (Expedia, Hotels.com, Goibibo...) depends on the country of the proxy IP</b>, not on this field - choose the proxy country below to match your market.

## `maxHotelsPerSearch` (type: `integer`):

Upper bound of hotels taken from each destination and date (1-500). You are charged only for hotels actually saved, so this also caps your cost: a 20-hotel search costs about 20 x the per-hotel price.

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

For every hotel, also list what each booking site charges (Booking.com, Expedia, Agoda, the hotel's own site, ...), cheapest first. Needs one extra request per hotel; switch off for a faster run that only returns Google's headline price.

## `includeVacationRentals` (type: `boolean`):

Google sometimes mixes apartments and private rentals into hotel results. Off by default so you only get hotels. Experimental: rentals have no booking-site price list and are rare in results.

## `includeUnavailable` (type: `boolean`):

Also return hotels that are sold out or have no price for these dates (price = null, isAvailable = false). Off by default so you are only charged for hotels you can actually price.

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

<b>Lowest price</b> is recommended for long lists: its order is stable, so no hotel is missed or repeated across pages. <b>Relevance</b> (Google's default ranking) changes slightly between requests, so very long relevance lists can contain gaps.

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

Only these hotel classes, e.g. <code>\[4, 5]</code>. Leave empty for all.

## `minGuestRating` (type: `string`):

Only hotels rated at least this high by guests.

## `minPricePerNight` (type: `number`):

In the currency above. Google applies it to the nightly price it shows (the 'price' field), which with the default US proxy does not include taxes. Leave empty for no minimum.

## `maxPricePerNight` (type: `number`):

In the currency above. Google applies it to the nightly price it shows (the 'price' field), which with the default US proxy does not include taxes. Leave empty for no maximum.

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

Only hotels with a free-cancellation rate.

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

Only hotels Google marks as a deal.

## `trackChanges` (type: `boolean`):

Compare every hotel with the same stay (hotel, dates, guests, currency) in your previous run and fill <code>changedSinceLastRun</code>, <code>previousPrice</code> and <code>priceChange</code>. Needs no setup: the last prices are kept in a storage in your account.

## `snapshotStoreName` (type: `string`):

Name of the key-value store that remembers the previous prices (3-63 letters, digits and hyphens). Use a different name per monitoring job so jobs do not overwrite each other's history.

## `allowLanguageFallback` (type: `boolean`):

Google returns no hotels for some destination and language combinations (e.g. "Paris" in Spanish). With this on, the Actor retries in English and marks those rows <code>languageFallback: true</code>; off = report the empty result instead.

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

How many requests run at the same time (1-20). Lower is gentler on Google and less likely to be blocked; higher is faster.

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

How often a failed or blocked request is retried from a new IP address (0-10).

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

Datacenter proxies in the United States are used by default (cheapest). The country of the proxy IP decides which booking sites Google lists. <b>Datacenter proxies do not exist in every country</b> (the US worked in our tests, other countries failed with "no usable proxies"): for another country's booking sites, or if Google blocks datacenter IPs, select the <b>RESIDENTIAL</b> proxy group (more expensive).

## Actor input object example

```json
{
  "queries": [
    "Paris"
  ],
  "checkInDates": [
    "+30"
  ],
  "nights": 1,
  "adults": 2,
  "childrenAges": [],
  "currency": "USD",
  "languageCode": "en",
  "countryCode": "us",
  "maxHotelsPerSearch": 10,
  "includeOffers": true,
  "includeVacationRentals": false,
  "includeUnavailable": false,
  "sortBy": "relevance",
  "hotelClasses": [],
  "minGuestRating": "0",
  "freeCancellationOnly": false,
  "specialOffersOnly": false,
  "trackChanges": true,
  "snapshotStoreName": "google-hotels-price-snapshots",
  "allowLanguageFallback": true,
  "maxConcurrency": 5,
  "maxRequestRetries": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

## `hotels` (type: `string`):

One row per hotel and stay: the nightly price as Google shows it, the total for the stay, rating and the cheapest booking site.

## `priceBreakdown` (type: `string`):

The nightly price split into room rate, taxes and fees, and the price of the whole stay.

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

Address, coordinates, check-in and check-out times, website and photos.

## `problems` (type: `string`):

Searches that returned nothing or failed, with the reason.

## `runSummary` (type: `string`):

Totals, request statistics and warnings of this run.

# 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 = {
    "queries": [
        "Paris"
    ],
    "checkInDates": [
        "+30"
    ],
    "nights": 1,
    "adults": 2,
    "childrenAges": [],
    "currency": "USD",
    "languageCode": "en",
    "countryCode": "us",
    "maxHotelsPerSearch": 10,
    "includeOffers": true,
    "hotelClasses": [],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("mitul_kheni/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 = {
    "queries": ["Paris"],
    "checkInDates": ["+30"],
    "nights": 1,
    "adults": 2,
    "childrenAges": [],
    "currency": "USD",
    "languageCode": "en",
    "countryCode": "us",
    "maxHotelsPerSearch": 10,
    "includeOffers": True,
    "hotelClasses": [],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("mitul_kheni/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 '{
  "queries": [
    "Paris"
  ],
  "checkInDates": [
    "+30"
  ],
  "nights": 1,
  "adults": 2,
  "childrenAges": [],
  "currency": "USD",
  "languageCode": "en",
  "countryCode": "us",
  "maxHotelsPerSearch": 10,
  "includeOffers": true,
  "hotelClasses": [],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyCountry": "US"
  }
}' |
apify call mitul_kheni/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

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