# Google Hotels Scraper: OTA Prices & Rate Parity (`splashboard.labs/google-hotels-scraper`) Actor

Hotel prices from every booking site on Google Hotels (OTAs and the official site) for revenue managers, travel agencies and data teams. Rate-parity flag, 90-day price calendar, specific hotels or city search, any country. Free during launch.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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: prices from every booking site

**Google Hotels Scraper: OTA Prices & Rate Parity** returns every price Google Hotels shows for a hotel, **booking site by booking site**: Booking.com, Expedia, Agoda, Trip.com, dozens of other OTAs and **the hotel's official website**. Built for **revenue managers, hotel chains, travel agencies and travel-data teams**, for any check-in date, country and currency.

▶️ **Try it in one click:** press **Try for free** above (the prefilled search returns real prices in about 35 s), or open a ready-made example: [Seville](https://apify.com/splashboard.labs/google-hotels-scraper/examples/seville-hotel-prices-by-channel) · [New York](https://apify.com/splashboard.labs/google-hotels-scraper/examples/new-york-hotel-prices-by-channel) · [London](https://apify.com/splashboard.labs/google-hotels-scraper/examples/london-hotel-prices-by-channel) · [Rate parity, 30 nights](https://apify.com/splashboard.labs/google-hotels-scraper/examples/madrid-hotel-rate-parity-30-nights).

![Demo: Google Hotels prices from every booking site, results table and one hotel's offers](https://api.apify.com/v2/key-value-stores/ZkIWJt1xjZQfQMoTP/records/demo-v3.gif)

🆓 **Free during launch**: you only pay Apify platform usage (~$0.07 per 100 hotel-dates). If it saves you time, a ⭐ review on this page helps a lot.

### Why this Google Hotels scraper?

- 💸 **Every booking site per hotel** (`offers[]`): typically 15–30 channels per hotel × date, sorted from cheapest to most expensive, with the official site marked.
- ⚖️ **Rate-parity flag**: the official site's price against the cheapest channel, the gap in money and percent, and `hasDisparity` when the gap is over 1 % and over 1 currency unit.
- 📅 **Price calendar**: 1–90 consecutive check-in dates in one run, 1–30 nights each.
- 🏨 **Specific hotels or city search**: monitor your own hotels and your compset by Google Hotels URL, Google Maps URL or Google ID, or discover hotels with a search such as "hotels in Seville".
- 🌍 **Search country as an input**: prices as visitors from that country see them, in the currency you ask for, with taxes included (see the FAQ for the few exceptions).
- ✅ **Nothing is silent**: one row per hotel × date with a status (`ok`, `no_results`, `failed`, `invalid_input`), so you always know what happened.
- ⚡ **Measured reliability**: on our 14 Oct 2026 benchmark of 50 hotel × date queries in Spain, the US and the UK, **100 % (50/50) succeeded** (`ok` or a genuine "no availability"), with 0 % blocked requests and ~2 s per query. No browser: lightweight requests only.

### What data does this hotel price API return?

| Field | Example | Notes |
|---|---|---|
| `hotel.name`, `stars`, `rating`, `reviewsCount`, `address`, `coordinates` | Meliá Sevilla · 4★ · 4.4 (7,023) | From Google Hotels |
| `hotel.cid` | `16724932617184247763` | Google Maps CID: stable key for time series |
| `hotel.entityId`, `hotel.googleHotelsUrl` | `ChkI0__x…` | Link opens the same dates, guests and currency |
| `stay.checkIn`, `checkOut`, `nights`, `guests` | 2026-11-20 → 2026-11-22, 2 nights, 2 adults | One row per check-in date |
| `offers[].provider` | Booking.com, Agoda, Meliá Sevilla… | OTAs, metasearch deals and the official site |
| `offers[].isOfficialSite` | `true` | The hotel's own website |
| `offers[].totalPrice`, `pricePerNight` | 365.00 / 182.50 | Whole stay and per night, taxes included |
| `offers[].taxesIncluded` | `true` | `null` if Google's data does not say (see FAQ) |
| `offers[].freeCancellation`, `roomType` | `true`, "Twin Room" | Only when Google provides them, never guessed |
| `offers[].bookingUrl` | `https://www.google.com/…` | Google's redirect to the channel |
| `pricingSummary` | cheapest 286.05 (Super.com) vs official 365.00 → +78.95 (21.63 %) | `hasDisparity` = gap > 1 % **and** > 1 currency unit |
| `status`, `error` | `ok` / `no_results` / `failed` / `invalid_input` | Every requested hotel × date gets a row |
| `chargedResults` | `1` | `1` for rows with prices, otherwise `0`. Informative only: **nothing is charged during the launch period** |

### How to use it

#### Monitor specific hotels (best for daily tracking)

1. Open the hotel on [Google Hotels](https://www.google.com/travel/hotels) (or Google Maps) and copy the URL.
2. Paste one or more URLs into **Hotels to monitor**. You can also paste the hotel's Google ID (CID), e.g. `16724932617184247763`.
3. Set the **first check-in date**, the **number of nights** and the **number of check-in dates**.
4. Pick the **country**, **currency** and **language** of the Google edition you want to see.
5. Run it, then open the **Summary** view (one line per hotel × date) or the **Offers** view (one line per channel).

#### Discover hotels in a destination

Add a **search term** like `hotels in Seville` or `hoteles en Madrid centro` and choose how many hotels to take, up to 200 per search. Hotels come in Google's order; vacation rentals are skipped.

#### Track a date range

Set **Number of check-in dates** to e.g. 30 to price every night of the next month. Use a relative first check-in date like `"7 days"`, so a scheduled run always looks ahead from the day it runs.

### Input example

```json
{
  "hotelUrls": ["https://www.google.com/travel/hotels/entity/ChkI0__xnKWzuY3oARoML2cvMWhjNDJ6dmNfEAE"],
  "checkInDate": "2026-11-20",
  "stayNights": 2,
  "dateRangeDays": 1,
  "adults": 2,
  "countryCode": "ES",
  "currency": "EUR",
  "language": "en"
}
```

### Output example

Real output of the input above. The row had 32 offers; 4 are shown, and the long Google URLs are shortened with "…".

```json
{
  "status": "ok",
  "error": null,
  "source": {
    "type": "hotelUrl",
    "value": "https://www.google.com/travel/hotels/entity/ChkI0__xnKWzuY3oARoML2cvMWhjNDJ6dmNfEAE"
  },
  "searchMetadata": {
    "scrapedAt": "2026-10-12T22:19:45.485Z",
    "searchCountry": "ES",
    "currency": "EUR",
    "language": "en"
  },
  "hotel": {
    "entityId": "ChkI0__xnKWzuY3oARoML2cvMWhjNDJ6dmNfEAE",
    "cid": "16724932617184247763",
    "name": "Meliá Sevilla",
    "stars": 4,
    "rating": 4.4,
    "reviewsCount": 7023,
    "address": "Calle Dr. Pedro de Castro, 1, 41004 Sevilla",
    "coordinates": { "lat": 37.378147999999996, "lng": -5.983174000000001 },
    "googleHotelsUrl": "https://www.google.com/travel/hotels/entity/ChkI0__xnKWzuY3oARoML2cvMW…"
  },
  "stay": {
    "checkIn": "2026-11-20",
    "checkOut": "2026-11-22",
    "nights": 2,
    "guests": { "adults": 2, "childrenAges": [] }
  },
  "pricingSummary": {
    "cheapestPrice": 286.05,
    "cheapestProvider": "Super.com",
    "officialPrice": 365,
    "disparityAmount": 78.95,
    "disparityPercent": 21.63,
    "hasDisparity": true
  },
  "offers": [
    {
      "provider": "Super.com",
      "isOfficialSite": false,
      "totalPrice": 286.05,
      "pricePerNight": 143.03,
      "taxesIncluded": true,
      "freeCancellation": false,
      "roomType": null,
      "bookingUrl": "https://www.google.com/travel/lodging/clk?pc=AA80OszGJ7oohvGcLDGLOVIe9…"
    },
    {
      "provider": "Traveluro",
      "isOfficialSite": false,
      "totalPrice": 304,
      "pricePerNight": 152,
      "taxesIncluded": true,
      "freeCancellation": null,
      "roomType": null,
      "bookingUrl": "https://www.google.com/travel/lodging/clk?pc=AA80Osyyj0_Nk7v8U_zs-yXl2…"
    },
    {
      "provider": "Meliá Sevilla",
      "isOfficialSite": true,
      "totalPrice": 365,
      "pricePerNight": 182.5,
      "taxesIncluded": true,
      "freeCancellation": false,
      "roomType": null,
      "bookingUrl": "https://www.google.com/travel/lodging/clk?pc=AA80OsweoyRtXJ4fLGxxDOOVG…"
    },
    {
      "provider": "Booking.com",
      "isOfficialSite": false,
      "totalPrice": 365.5,
      "pricePerNight": 182.75,
      "taxesIncluded": true,
      "freeCancellation": false,
      "roomType": null,
      "bookingUrl": "https://www.google.com/aclk?sa=l&ai=DChsSEwjv2ujJwbWXAxWKtWgJHR1ODWwYA…"
    }
  ],
  "chargedResults": 1
}
```

### How much does it cost?

**Free during launch.** We charge nothing for this Actor: no rental fee and no per-result fee. You only pay the normal Apify platform usage of your own runs (residential proxy traffic and compute), which Apify bills to your account: **about $0.07 per 100 hotel-dates**, measured on our 14 Oct 2026 benchmark at Apify Free plan prices.

| What you monitor | Results (hotel-dates) | Estimated platform usage |
|---|---|---|
| 10 hotels × 30 nights | 300 | ≈ $0.21 |
| 20 hotels × 90 check-in dates (a quarter) | 1,800 | ≈ $1.28 |
| 50 hotels × 30 nights, every day for a month | 45,000 | ≈ $32 |

- The $5 of free monthly credit on the Apify Free plan covers **about 7,000 hotel-dates a month**. Paid Apify plans have cheaper proxy traffic.
- ⭐ **Enjoying it?** A short review on this page is the best way to support the free launch.
- Later we may move to simple pay-per-result pricing. It will be announced in advance on this page, and Apify notifies existing users before any price change takes effect.

### Use cases: rate parity, revenue management, agencies and AI agents

#### Rate parity monitoring for revenue managers

Check every day whether OTAs sell your rooms below your official rate. Filter on `pricingSummary.hasDisparity = true` to get a daily list of hotel × date × channel violations, with the exact gap in money and percent. Send it to your OTA account managers.

#### Rate shopping and price calendars

Price your hotel and your compset for the next 30–90 check-in dates, every morning. The `cid` stays the same over time, so you can build price curves, spot compression nights and see how competitors react to events.

#### Travel agencies and market intelligence

Discover the top hotels of any destination with a search term, then compare how prices and channel mix differ by country (`countryCode`) and currency. Run the same hotels from ES, US and GB to see geo-pricing.

#### AI agents through MCP

Give an AI assistant live hotel prices. Through the [Apify MCP server](https://docs.apify.com/mcp), agents such as Claude can call this Actor directly. Every input field has a plain description with an example. Example request: *"Compare the official price of Meliá Sevilla with OTAs for every Friday in November."*

### Integrations

#### Hotel price API

Run the Actor and fetch results from any language through the [Apify API](https://docs.apify.com/api/v2). The **Offers** dataset view gives one flat line per channel, ready for BI tools. Export as JSON, CSV or Excel.

#### Scheduling

Create a task with your hotels and a relative check-in date (`"1 day"`), then schedule it daily or hourly in Apify Console. Each run returns the next N nights automatically.

#### Google Sheets

Send every run to a spreadsheet with the [Google Sheets integration](https://apify.com/integrations/google-sheets), or import the **Offers** view as CSV. One line per channel makes pivot tables and parity charts easy.

#### n8n, Make and Zapier

Use the official Apify apps for [n8n](https://apify.com/integrations/n8n), [Make](https://apify.com/integrations/make) and [Zapier](https://apify.com/integrations/zapier) to push parity alerts to Slack or email when a run finishes.

#### MCP (AI agents)

Connect the [Apify MCP server](https://docs.apify.com/mcp) to your assistant and it can run this Actor and read the results; see *AI agents through MCP* above.

### FAQ

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

The Actor collects publicly available pricing information, the same as any visitor to Google Hotels sees, without logging in. It does not collect personal data. Always make sure your use complies with the applicable laws and terms in your jurisdiction.

#### Why do some offers have `taxesIncluded: null`?

All prices are reported **including taxes**. In editions where Google shows pre-tax prices (the US), most channels come as a "pre-tax / with taxes" pair and we use the tax-inclusive one. Some channels send a single amount. We mark it as tax-inclusive only when it matches another channel's tax-inclusive price. Otherwise `taxesIncluded` is `null`, and the offer is left out of `cheapestPrice` and the parity check. In our 13 Oct 2026 benchmark this affected 13.5 % of US offers and none elsewhere.

#### Why do I get fewer rows than hotels × dates?

If the same hotel arrives twice (for example, as a URL and from a search), it is priced only once per date.

#### Why can prices differ from what I see in my browser?

Google personalises prices by country, currency, language, device and login. The Actor searches from the country you choose, as a logged-out visitor. Prices also change minute by minute.

#### Can I choose the number of rooms?

No. Google Hotels prices a stay for a number of guests and has no "rooms" option. Set **Adults** and **Children's ages** instead.

#### Does it convert currencies?

No. It asks Google for your currency and returns exactly what Google gives. The currency Google actually used is in `searchMetadata.currency`.

#### Does it use a browser?

No. It reads Google Travel's own data endpoints over plain HTTP, through residential proxies in your chosen country. That keeps it fast and affordable.

### Feedback and support

Found a bug, a hotel that does not work, or missing data you need? Open an issue in the **Issues** tab of this Actor and include the run ID. We usually reply within one business day, and feedback during the launch period directly shapes the roadmap. If the Actor works well for you, please leave a ⭐ review.

### Limitations

- Check-in dates up to **330 days** ahead; Google shows no prices further out.
- Up to **10,000 hotel × date combinations per run** and **200 hotels per search**. Split bigger jobs into several runs or tasks.
- **Vacation rentals** (apartments listed by individuals) are not supported; hotels, hostels, guesthouses and aparthotels are.
- `freeCancellation` and `roomType` are filled only when Google provides them for that channel.
- `bookingUrl` is Google's redirect link to the channel; it can expire after some time.
- Short links such as `maps.app.goo.gl/…` must be opened first; paste the full Google Maps or Google Hotels URL.

# Changelog

This Actor's version history is a separate document: https://apify.com/splashboard.labs/google-hotels-scraper/changelog.md

# Actor input Schema

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

Hotels to track directly. Each entry can be a Google Hotels URL (e.g. "https://www.google.com/travel/hotels/entity/ChkI0__xnKWzuY3oARoML2cvMWhjNDJ6dmNfEAE"), a Google Maps place URL of the hotel, or the hotel's Google ID (CID, e.g. "16724932617184247763"). An entry that cannot be recognised produces a row with status "invalid_input".

## `searchTerms` (type: `array`):

Searches to run on Google Hotels to discover hotels, e.g. "hotels in Seville" or "hoteles en Madrid centro". Up to maxHotelsPerSearch hotels are taken from each search (vacation rentals are skipped).

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

How many hotels to take from each search term, in Google's order, e.g. 20. Each hotel produces one row per check-in date.

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

First check-in date, either absolute (e.g. "2026-11-02") or relative to the day of the run (e.g. "14 days", "2 weeks"). Relative dates keep scheduled runs always looking ahead. It cannot be in the past or more than 330 days ahead. Empty = 14 days from today.

## `stayNights` (type: `integer`):

Length of each stay in nights, e.g. 1 (check-out the next day) or 3. Prices are returned for the whole stay (totalPrice) and per night (pricePerNight).

## `dateRangeDays` (type: `integer`):

How many consecutive check-in dates to price, starting at the first check-in date. E.g. 30 with 10 hotels gives 300 rows (one per hotel per day), ideal for rate shopping across a month.

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

Number of adult guests, e.g. 2.

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

Age of each child at check-in (0–17), as a list, e.g. \[5, 9] for two children aged 5 and 9. Leave empty for no children. Google Hotels prices per stay and guests; it has no 'number of rooms' option.

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

Two-letter ISO 3166-1 country the search is made from, e.g. "ES" (Spain) or "US". It sets the Google edition and the proxy country. Note: prices are always reported including taxes; in the US edition Google's tax-inclusive price is used.

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

Three-letter ISO 4217 currency to ask Google for, e.g. "EUR" or "USD". Prices are returned exactly as Google gives them (no conversion by us); the currency Google actually used is in each row.

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

Language of Google's interface, e.g. "es", "en" or "en-GB". It affects texts such as room names, not prices.

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

How many proxy sessions work in parallel, e.g. 5. Higher is faster for large runs; the Actor lowers it automatically if Google starts blocking.

## `maxAttempts` (type: `integer`):

How many times to try each hotel × date before reporting it as "failed", e.g. 5.

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

Proxy used to reach Google, e.g. Apify Proxy with the RESIDENTIAL group (recommended). With Apify Proxy, the proxy country is always set to the country above.

## `auditTaxes` (type: `boolean`):

Internal diagnostic. When true, editions that show prices without taxes (e.g. US) store a TAX_AUDIT record in the key-value store with the price basis of every offer. It does not change the output rows.

## Actor input object example

```json
{
  "searchTerms": [
    "hotels in Seville"
  ],
  "maxHotelsPerSearch": 20,
  "checkInDate": "14 days",
  "stayNights": 1,
  "dateRangeDays": 1,
  "adults": 2,
  "childrenAges": [],
  "countryCode": "ES",
  "currency": "EUR",
  "language": "es",
  "maxConcurrency": 5,
  "maxAttempts": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "auditTaxes": false
}
```

# Actor output Schema

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

Cheapest channel, official site price and rate parity for each hotel and check-in date.

## `offers` (type: `string`):

Every channel's price (OTAs and the official site) for each hotel and check-in date, flat and ready for spreadsheets or BI tools.

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

Complete rows with hotel details, stay, pricingSummary and the offers\[] array, including status and error for every requested hotel × date.

## `runStats` (type: `string`):

RUN_STATS record: rows by status, requests, blocks, sessions, KB downloaded and seconds per hotel × date.

# 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 = {
    "searchTerms": [
        "hotels in Seville"
    ],
    "checkInDate": "14 days",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("splashboard.labs/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 = {
    "searchTerms": ["hotels in Seville"],
    "checkInDate": "14 days",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("splashboard.labs/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 '{
  "searchTerms": [
    "hotels in Seville"
  ],
  "checkInDate": "14 days",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call splashboard.labs/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

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