# Google Hotels Scraper: Prices, Booking Sites & Rate Calendar (`jamie_developer/google-hotels-scraper`) Actor

Hotel prices from Google Hotels for any city or hotel and your dates, guests and currency: nightly and total price, rating, class, amenities, and optionally every booking site's price (Booking.com, Expedia, official site) for rate tracking.

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

## Pricing

from $2.30 / 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: Prices, Booking Sites & Rate Calendar

Get hotel prices from **Google Hotels** for any city, landmark or specific hotel, for your dates, guests and currency. Each row is one hotel for one stay: nightly price, total price with taxes and fees, star class, guest rating, review count, amenities, location and a link that opens the same search on Google. Turn on one switch to also get **every booking site's price** for each hotel (Booking.com, Expedia, Agoda, Trip.com, the hotel's own website and more) with free-cancellation dates.

The Actor reads the same public data the Google Hotels page loads in your browser. No login, no browser, no proxies, so runs are fast and cheap: 20 hotels take about 4 seconds.

### What you can do with it

| Goal | Input |
|---|---|
| List hotels in a city with prices | **Places to search**: `Zurich`, `Paris`, `Lisbon` |
| Hotels around a landmark | `Times Square`, `Eiffel Tower`, `Colosseum` |
| Compare booking sites for specific hotels | **Specific hotels**: a Google Hotels URL, its ID or the hotel's name with its city |
| Track a hotel's rate over the coming weeks | Specific hotel + **Also check the next N check-in days** = 29 → one row per check-in date |
| Market or competitor price checks | Places + filters (stars, rating, price, amenities) + a daily schedule |

### What you get for each hotel

| Field | Example |
|---|---|
| `name`, `hotelClass`, `rating`, `reviewCount` | Zurich Marriott Hotel, 5, 4.3, 3308 |
| `pricePerNight`, `totalPrice` | 509.58, 1528.74 (including taxes and fees) |
| `totalPriceBeforeTaxes`, `taxesAndFees` | 1442.94, 80.19 |
| `currency` | USD, EUR, CHF, JPY … (you choose) |
| `deal` | 20% less than usual (when Google shows one) |
| `checkIn`, `checkOut`, `nights`, `adults`, `children` | 2026-12-10, 2026-12-13, 3, 2, 0 |
| `amenities` | Free Wi-Fi, Indoor pool, Spa, Fitness center, Restaurant … |
| `latitude`, `longitude`, `website`, `checkInTime`, `checkOutTime`, `description`, `imageUrl` | |
| `position` | rank in Google's results for the search |
| `hotelId`, `googleHotelsUrl` | Google's hotel ID and a link to the hotel for the same dates and guests |
| `input`, `resolvedLocation`, `searchUrl` | your search, the place Google understood (e.g. "Zürich") and a link to the same search |

**With booking-site prices** (always on for *Specific hotels*, optional for place searches) each row also gets:

| Field | Example |
|---|---|
| `address`, `googlePlaceId` | Neumühlequai 42, 8006 Zürich, Switzerland |
| `cheapestSite`, `cheapestSitePricePerNight` | BusinessHotels.com, 507.71 |
| `officialSitePricePerNight` | the hotel's own website price, when Google lists it |
| `bookingSiteCount` | 19 |
| `bookingSites` | one entry per site: `site`, `pricePerNight`, `totalPrice`, `freeCancellation`, `freeCancellationUntil`, `isOfficialSite`, `url` |

#### Example output

```json
{
  "position": 1,
  "name": "Crowne Plaza Zurich by IHG",
  "hotelClass": 4,
  "rating": 4.0,
  "reviewCount": 3937,
  "pricePerNight": 140.95,
  "totalPrice": 140.95,
  "totalPriceBeforeTaxes": 127.77,
  "taxesAndFees": 13.18,
  "currency": "USD",
  "deal": "20% less than usual",
  "latitude": 47.3803,
  "longitude": 8.5063939,
  "website": "https://www.ihg.com/crowneplaza/hotels/gb/en/zurich/zrhha/hoteldetail",
  "checkInTime": "3:00 PM",
  "checkOutTime": "12:00 PM",
  "description": "Straightforward rooms & suites in a property with fine dining, a fitness center & meeting space.",
  "amenities": ["Air conditioning", "Bar", "Fitness center", "Free Wi-Fi", "Indoor pool", "Restaurant", "Spa"],
  "hotelId": "ChgIlJqDrZWz4_afARoLL2cvMXRrNnA3Z3MQAQ",
  "checkIn": "2026-11-14",
  "checkOut": "2026-11-15",
  "nights": 1,
  "adults": 2,
  "children": 0,
  "googleHotelsUrl": "https://www.google.com/travel/hotels/entity/ChgIlJqDrZWz4_afARoLL2cvMXRrNnA3Z3MQAQ?hl=en&gl=us&ts=…",
  "input": "Zurich",
  "inputType": "search",
  "resolvedLocation": "Zürich",
  "searchUrl": "https://www.google.com/travel/search?q=Zurich&hl=en&gl=us&ts=…",
  "scrapedAt": "2026-10-31T01:26:47Z"
}
```

One entry of `bookingSites`:

```json
{
  "site": "Trip.com",
  "pricePerNight": 509.58,
  "totalPrice": 1528.74,
  "freeCancellation": true,
  "freeCancellationUntil": "2026-11-01",
  "isOfficialSite": false,
  "url": "https://www.google.com/travel/lodging/clk?…"
}
```

### How to use it

1. Add places under **Places to search** and/or hotels under **Specific hotels**.
2. Set the **check-in date**, **nights**, **adults**, children's ages and **currency**.
3. Optional: filters (price per night, minimum rating, star class, amenities, free cancellation) and **Add every booking site's price**.
4. Click **Start**, then download the results as JSON, CSV or Excel, or connect them to Google Sheets, Make, Zapier, n8n or your own code via the API.

#### Example input

```json
{
  "locations": ["Paris", "Eiffel Tower"],
  "hotels": ["Hotel Arts Barcelona"],
  "checkIn": "2026-12-10",
  "nights": 2,
  "adults": 2,
  "childrenAges": ["8"],
  "currency": "EUR",
  "hotelClass": ["4", "5"],
  "minRating": "4.0",
  "maxPrice": 400,
  "includeBookingSites": true,
  "maxHotelsPerSearch": 50
}
```

#### Rate calendar for your own hotel or competitors

Add the hotels under **Specific hotels**, set the first check-in date and **Also check the next N check-in days**. With N = 29 you get 30 rows per hotel, one per check-in date, each with every booking site's price and whether its rate has free cancellation. Schedule it daily to see how rates move.

**Check-in date** also accepts a number of days from today (e.g. `30`), and an empty value means 14 days from today, so scheduled runs keep looking ahead instead of failing on a date in the past.

### Use cases

- **Hotel revenue management:** watch your own and your competitors' rates on every booking site, and check rate parity between your website and the online travel agencies.
- **Travel agencies and tour operators:** price stays for groups and packages across many destinations and dates.
- **Market research:** average prices, star mix, ratings and deals by city, neighbourhood or season.
- **Travel apps and content:** fill hotel lists with current prices, ratings and links.
- **Deal alerts:** run daily with a maximum price and notify yourself when a hotel drops below it.

### Pricing

You pay per hotel row saved. Rows with booking-site prices cost more than plain search rows because each needs an extra request. The exact prices per 1,000 rows are on the Pricing tab. Set a maximum cost per run in the run options and the Actor stops cleanly when it's reached.

### Tips

- **Places:** type them as you would on Google Hotels: a city, district or landmark. Google's own wording works as a filter too, e.g. `5 star hotels in Rome`. If a search like `hotels near X` finds nothing, the Actor retries once with just `X`. The `resolvedLocation` field and the run log show which place Google searched; a misspelled place can make Google fall back to a whole country.
- **Children:** Google prices one room for the whole party. With two or more children many hotels have no room for everyone, so their price fields stay empty (in a Bangkok test with 2 adults and 2 children, 4 of 20 hotels had a price; with 1 child almost all did).
- **Star class:** `hotelClass` is empty when Google shows no official star rating for a hotel. This is common in some countries (in our tests most hotels in Prague and Berlin had none) and for apartments and hostels.
- **No price:** some hotels show "Check availability" on Google with no prices for some dates. Those rows still appear, with the price fields empty, so you can see the hotel was checked.
- **Ranking:** Google orders results with its own ranking, which changes slightly between requests. Use `maxHotelsPerSearch` = 0 to get every hotel Google lists for a place.
- **Prices change by market:** set **Google country** and **Currency** to match the market you are interested in.
- A **SUMMARY** record in the run's key-value store lists every search and hotel with hotels found, rows saved and any error.

### FAQ

**Is this allowed?** The Actor reads the public hotel and price data Google Hotels shows to every visitor without logging in. It collects no personal data. Check your own use of the data against Google's terms.

**Why are prices slightly different from what I see?** Google personalises prices by country, currency, device and sometimes membership. Set the same currency and Google country you use in your browser, and compare with the `googleHotelsUrl` link, which opens the same dates and guests.

**Something is missing or broken.** Open an issue on the Issues tab with your input and I'll look at it.

This Actor is not affiliated with Google.

# Actor input Schema

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

One per line: a city, area or landmark as you would type it into Google Hotels, e.g. Zurich, Paris 8th arrondissement, hotels near Times Square, Lisbon. Google's own wording also works as a filter, e.g. 5 star hotels in Rome or hotels in Berlin under $150.

## `hotels` (type: `array`):

One per line: a Google Hotels hotel URL (https://www.google.com/travel/hotels/entity/ChcI…), its ID (starts with Ch…) or the hotel's name with its city, e.g. Hotel Schweizerhof Zurich. Each hotel row always includes every booking site's price.

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

YYYY-MM-DD (e.g. 2026-12-10), or a number of days from the day the run starts (e.g. 30). Empty = 14 days from today, which keeps scheduled runs looking ahead.

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

Length of stay, 1 to 30 nights.

## `additionalCheckInDays` (type: `integer`):

Rate calendar: repeat every search and hotel for the next N check-in dates with the same number of nights. 0 = only the check-in date above; 29 = 30 check-in dates.

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

Adults in one room. Google prices one room for the whole party.

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

One age per child (0 to 17), e.g. 5 and 9 for two children. Leave empty for no children.

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

3-letter currency code for all prices, e.g. USD, EUR, GBP, CHF, JPY.

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

Google language code for hotel names and descriptions, e.g. en, de, fr, es, ja.

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

2-letter country code of the Google market (gl), e.g. us, gb, de, ch. Booking sites and some prices differ by market.

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

In the currency above. 0 = no minimum. Applied by Google before results are returned.

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

In the currency above. 0 = no maximum.

## `minRating` (type: `string`):

Keep only hotels rated at least this on Google.

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

Keep only these star classes. Empty = all.

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

Keep only hotels that have all of these.

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

Keep only hotels with a free-cancellation rate for your dates.

## `includeBookingSites` (type: `boolean`):

For place searches: add each hotel's address, Google place ID and the price on every booking site (Booking.com, Expedia, Agoda, the hotel's own site …) with free-cancellation info. One extra request per hotel, so runs take longer. Rows from 'Specific hotels' always include this.

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

Stop each place search after this many hotels (Google lists 20 per page, in its own ranking). 0 = every hotel Google lists, which can be thousands for big cities.

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

Stop the whole run after this many rows. 0 = no limit.

## Actor input object example

```json
{
  "locations": [
    "Zurich"
  ],
  "nights": 1,
  "additionalCheckInDays": 0,
  "adults": 2,
  "currency": "USD",
  "language": "en",
  "country": "us",
  "minPrice": 0,
  "maxPrice": 0,
  "minRating": "",
  "freeCancellation": false,
  "includeBookingSites": false,
  "maxHotelsPerSearch": 20,
  "maxResults": 0
}
```

# Actor output Schema

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

One row per hotel and stay: prices, rating, class, amenities, location and links; with booking-site prices when requested.

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

One entry per search or hotel input with hotels found, rows saved and any error.

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "locations": [
        "Zurich"
    ],
    "maxHotelsPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("jamie_developer/google-hotels-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "locations": ["Zurich"],
    "maxHotelsPerSearch": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("jamie_developer/google-hotels-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "locations": [
    "Zurich"
  ],
  "maxHotelsPerSearch": 20
}' |
apify call jamie_developer/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

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