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

Compare Google Hotels prices and organic booking offers for your dates, adults and currency. Search destinations or use hotel links for hotel price monitoring. $1.95/1,000 hotels plus $0.001/start at default memory; provider offers included. Maintained by CleanScrape.

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

## Pricing

from $1.56 / 1,000 hotel results

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 API

Collect hotel prices for a specific stay, together with the organic booking offers available through Google Hotels, part of Google Travel. Each result identifies the property, dates, guest count and currency, so you can use it in a spreadsheet or your own price-monitoring workflow.

Maintained by CleanScrape. Questions or unexpected results: contact.cleanscrape@gmail.com. Include your run ID and a brief description; never send API tokens.

The main form shows the destination, stay preset, nights, adults, currency and **Maximum hotels**. Open **Specific hotels or dates (optional)** for property links or exact check-in and check-out dates. Filters and scan limits are below that; connection controls are in **Advanced connection settings**.

### Watch a real run

Let's use a two-night trip to London as an example. This short walkthrough shows the stay controls, hotel prices, included provider offers and spreadsheet export using a real Actor run.

https://www.youtube.com/watch?v=QrzboGuj05o

[Open the London example](https://apify.com/cleanscrape/google-hotels-scraper/examples/google-hotels-london-price-comparison), then change the destination and stay to suit your search. The video uses recorded prices, not current booking quotes. Place searches cover the first source results page, not every hotel in a city.

For a provider spreadsheet, choose **Export**, select **Provider offers** in the dialog, and then choose **Excel** or **CSV**. Provider offers are included in each hotel result rather than billed as additional results. Check room and cancellation terms before comparing quotes.

### Try a small example

Suppose you are comparing accommodation in London for a two-night trip next month.

The form opens with this search, so you can start it as it is. The [London example](https://apify.com/cleanscrape/google-hotels-scraper/examples/google-hotels-london-price-comparison) has the same settings. Both use relative dates, so they work again for a later trip.

1. Keep `hotels in London` under **Place searches**, or enter your own destination.
2. Keep **In 30 days**, **2 nights**, **2 adults** and **British pound**, or change them.
3. Leave **Maximum hotels** at **5** and start the run.
4. Open the **Hotel prices** table for headline nightly and stay totals. Switch to **Provider offers** to compare collected booking-provider quotes in separate display rows.
5. Read the **Run report** alongside the results. It explains source errors, filtering and coverage limits.

For exact properties, clear the prefilled Place searches entry and paste Google Hotels URLs under Exact Google Hotels properties. You can also keep both inputs to combine discovery with specific properties. The Actor checks that the returned property ID matches. Place searches are discovery, not exact hotel-name matching. Words such as "four-star" or a neighborhood name are search hints, not verified filters or geographic boundaries.

```json
{
  "queries": ["hotels in London"],
  "datePreset": "in_30_days",
  "nights": 2,
  "currency": "GBP",
  "adults": 2,
  "maxResults": 5
}
```

<a id="compare-specific-properties"></a>

### Compare hotel prices for the same stay

Open a property in Google Hotels and copy its full property-page URL. Paste one link per entry under **Exact Google Hotels properties (optional)**, then clear **Place searches** if you do not want additional discovery results. Set the dates, adults and currency in this form; values embedded in a pasted link do not replace those settings.

For a reusable example, this link to The Waldorf Hilton, London requests a new stay in 30 days:

```json
{
  "queries": [],
  "hotelUrls": [
    "https://www.google.com/travel/hotels/entity/ChUI3_-FnbCxhLlLGgkvbS8wNmNna3EQAQ/prices"
  ],
  "datePreset": "in_30_days",
  "nights": 2,
  "adults": 2,
  "currency": "GBP",
  "maxResults": 1
}
```

Availability and quotes can change. Use your own property link for your comparison. To switch back to a place search, remove the property links and enter a destination. To switch from exact dates to a preset, clear both date fields as well.

### Dates without manual formatting

Use tomorrow, next Friday, in seven days or in thirty days. Presets are calculated from the run's UTC date and work with schedules. Dates are saved when a run starts and stay fixed if that same run restarts. A new scheduled run calculates a new stay. If saved dates have become past, start a new run instead. For a fixed trip, select **Choose exact dates** under **When is the stay?**, then open **Specific hotels or dates (optional)** and select both calendar dates. Explicit check-in and check-out values take precedence over a preset.

The Actor supports one requested room and 1-6 adults. Children, multiple rooms and date grids are not supported yet. It does not silently ignore unsupported input fields.

### What you receive

One dataset row represents one property and stay, including the collected organic provider offers. Dates, currency, adult count and property identity must pass source checks before a row is delivered.

| Field | Meaning |
| --- | --- |
| `name`, `hotelId`, `googleHotelsUrl` | Property identity and a link with the requested stay |
| `checkIn`, `checkOut`, `nights`, `adults`, `currency` | Source-verified stay context |
| `nightlyPrice`, `totalPrice` | Google's displayed headline amounts, preserved separately |
| `offers` | Supported organic provider quotes, amounts, source terms and Google booking redirects |
| `offerCount`, `offersStatus`, `warnings` | Collected coverage and relevant limitations |
| `rating`, `reviewCount`, `address` | Property information when the supported source supplies it |
| `verification`, `fetchedAt`, `recordKey` | Quality checks, collection time and stable property/stay key |

The stay total is not calculated by multiplying a rounded nightly price. Provider quotes can differ from Google's headline offer. A missing field means it was not available in a supported source structure, not that the property lacks that feature.

#### Export to a spreadsheet or use the API

Use the Output tab's export option for CSV or Excel, selecting **Hotel prices** for one row per hotel or **Provider offers** for individual quotes. For integrations, use JSON to keep each hotel's nested `offers` array. Expanding the provider view does not create extra hotel results or hotel-result charges. A hotel without supported offers may have an empty provider cell; its headline price remains in the Hotel prices view.

The provider table leaves out long booking URLs and internal provider IDs to keep comparisons readable. They remain available in **All fields** and the full JSON export. Numeric provider prices preserve the source precision; the corresponding `nightlyPriceText` and `totalPriceText` fields retain Google's rounded display strings.

In the export dialog, select the view again before downloading; it may not match the table currently open. Apify's CSV and Excel exports can retain empty columns for fields hidden by a view. These do not mean that hotel prices are missing. Use the JSON export when preserving the complete nested records is important.

You can schedule the same input for repeat collection. Use explicit dates to track one particular trip, or a relative preset for a rolling stay. A fresh run collects a fresh snapshot; this Actor does not calculate historical price changes or send alerts.

### Comparing prices responsibly

A cheaper offer may be a dorm bed rather than a private room, or have different cancellation and meal terms. Room equivalence is **not verified** by this Actor. The lowest observed provider is not a rate-parity finding or a guarantee of the cheapest equivalent booking.

Google can map hostel occupancy to multiple beds or bookable units. `requestedRooms: 1` describes the request, not independent confirmation that every provider is selling one ordinary hotel room. `taxesIncludedInHeadline` is currently null: the parser cannot reliably attribute tax wording to the headline quote. Do not assume taxes or local charges are included.

Booking links can expire, and checkout prices can change. The Actor does not open booking destinations, make reservations or verify checkout availability. It does not return paid advertising placements as organic offers.

### Coverage and limits

- The Actor discovers up to 20 properties from the first source results page per place search. It is not a complete city export.
- Maximum results is a run-wide upper limit, not a promise of that many available prices.
- Rating filtering happens after lookup, so a restrictive filter can produce fewer results.
- Provider counts vary by property and stay. Offers are bounded by Maximum offers per hotel.
- Source blocks stop the workflow. No CAPTCHA bypass or automatic residential fallback is included.
- Direct requests and Apify datacenter proxy are the supported connection modes. Custom proxy URLs, residential groups and country-targeted proxy settings are rejected rather than silently ignored.
- A failed lookup or absent quote does not mean a hotel is sold out. Diagnostics belong in the run report, not fabricated price rows.
- Interrupted runs retain completed rows. An ambiguous charging/storage interruption stops safely for investigation rather than risking duplicate charges.

### Pricing

The base price is **$1.95 per 1,000 delivered hotel/stay results**, plus **$0.001 per Actor start** at the default 256 MB of memory. Collected organic provider offers and platform usage are included. Expanding or exporting provider offers does not create another billable hotel result.

| Delivered hotel results | Base cost, including one start at default memory |
| --- | --- |
| 1 | $0.00295 |
| 5 | $0.01075 |
| 20 | $0.04000 |
| 50 | $0.09850 |

Bronze subscribers receive 10% off base event prices, Silver 15%, and Gold 20%. The same 20% reduction applies to Platinum and Diamond. Apify applies the subscription-tier price automatically; see the Pricing tab for your applicable rate.

The start event is charged automatically by Apify: one event for up to 1 GB of allocated memory, then one for each additional GB. Keep the default memory unless your workload requires more. A start can be charged even when no quote is returned. Failed lookups, rejected source contexts and filtered-out properties are not hotel-result events.

**Restart costs:** Apify can charge another start event when a finished or interrupted run is resurrected. The cost examples above assume one start, not repeated restarts. The Actor cannot prevent this platform-managed event before its code starts. Check the run's accumulated charges before resurrecting it with an already exhausted budget.

Set a positive maximum run cost to control spending. When there is not enough budget for another result, the Actor stops delivery and reports `charge_limit`. A maximum result count is also a cap, not a prepaid package or a guaranteed number of quotes. Resuming an interrupted run does not intentionally re-export or re-charge already saved hotel rows.

### If a run returns fewer results than expected

- Check **Run report** for the effective dates, currency and adult count. A maximum is a cap, not a guaranteed result count.
- A source-layout or context-mismatch error means the Actor could not safely verify that response. It does not substitute a price for a different stay.
- For a source block, wait before trying a small run again. Increasing concurrency or repeatedly restarting is not a reliable fix.
- If a broad place search is not specific enough, open the property in Google Hotels and paste its full `/travel/hotels/entity/` URL. Short Maps links and booking-site links are not supported.
- For API use, submit arrays of search strings or property URLs. No Google account, hotel ID lookup or additional source API key is needed when you use place searches.

### Support and independence

We welcome specific bug reports and examples of missing coverage. Maintenance is ongoing, but source changes can cause interruptions; there is no uptime guarantee or promise that every property always has a quote.

This Actor is an independent tool and is not affiliated with, endorsed by or sponsored by Google or the booking providers shown in its results. All trademarks belong to their respective owners.

# Actor input Schema

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

Enter up to five searches, such as hotels in London. For exact property links only, clear this field. Place searches read the first results page, not every hotel in a city.

## `datePreset` (type: `string`):

Choose when the stay starts. Presets use the UTC date when the run begins. For Choose exact dates, open Specific hotels or dates and select both calendar dates; these override the preset.

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

Used with date presets. For exact dates, the dates determine the stay length.

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

One requested room. Children and multiple rooms are not supported by this Actor.

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

All delivered headline and provider prices must match this currency.

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

Total hotel limit across all searches and property links, not a guaranteed count. Booking-provider offers are included inside each hotel result.

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

Paste full Google Hotels property links containing /travel/hotels/entity/. For links only, clear Place searches. Keep both to combine them. The stay, guest count and currency come from the form, not the pasted URL. Booking-site and shortened links are not supported.

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

Select with Check-out date for a fixed stay. Dates override the preset. To return to relative dates, clear both calendar fields and choose a stay preset.

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

Select a date 1-30 nights after check-in. The stay must end within the next 365 days.

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

0 disables filtering. Applied after property lookup; missing ratings do not pass a positive threshold.

## `maxHotelsPerQuery` (type: `integer`):

How many hotels to check on the first results page for each search. Filters and unavailable prices can reduce the output.

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

Supported organic offers, ordered by total price. Different rooms may not be comparable.

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

Leave proxy disabled for direct requests. For Apify datacenter proxy choose Automatic (no named group). Residential, country-targeted and custom proxies are not supported.

## Actor input object example

```json
{
  "queries": [
    "hotels in London"
  ],
  "datePreset": "in_30_days",
  "nights": 2,
  "adults": 2,
  "currency": "GBP",
  "maxResults": 5,
  "minRating": 0,
  "maxHotelsPerQuery": 10,
  "maxOffersPerHotel": 30,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

No description

## `report` (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 = {
    "queries": [
        "hotels in London"
    ],
    "currency": "GBP"
};

// Run the Actor and wait for it to finish
const run = await client.actor("cleanscrape/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": ["hotels in London"],
    "currency": "GBP",
}

# Run the Actor and wait for it to finish
run = client.actor("cleanscrape/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": [
    "hotels in London"
  ],
  "currency": "GBP"
}' |
apify call cleanscrape/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

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