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

Hotel lists for any destination and per-site prices for the hotels you pick, from Google Hotels. Check many dates at once and see how each price moved since the last run.

- **URL**: https://apify.com/lyklo/google-hotels-scraper.md
- **Developed by:** [Lyklo](https://apify.com/lyklo) (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 $2.00 / 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.

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

Get hotel prices from Google Hotels in two ways:

- **Destinations**: type a place such as *Kyoto* or *hotels near Times Square* and get the hotels Google lists there, with the lowest price, stars, rating and location.
- **Hotels you pick**: give the hotels you care about and get every booking site's price for them (Booking.com, Expedia, Agoda, the hotel's own site and more), for as many check-in dates as you need.

Turn on **Compare with the last run** and schedule it, and each result also says whether the price went down, went up, sold out or came back since the previous run.

The data comes from the public Google Hotels pages at google.com/travel. This is an independent tool. It is not made, endorsed or sponsored by Google.

### Who it's for

- **Hotel revenue managers** who check their competitors' rates every morning. List your own hotel and 5 to 15 competitors, check the next 30 check-in dates, and schedule a daily run. You see each competitor's price per date, which site sells it cheapest, and what moved overnight, for a small part of what rate-shopping software costs.
- **Travel and data teams** who need hotel lists for a city with prices, ratings and coordinates: price comparison, vacation-rental pricing, market research, or an AI agent that answers travel questions.

### How to use it

1. Put places under **Destinations**, or hotels under **Hotels**, or both. A hotel can be a Google Hotels link, a hotel ID from an earlier run, or its name.
2. Pick the check-in date (or leave it empty for 14 days after each run), the number of nights, and how many check-in dates to check in a row.
3. Run it. To watch prices, turn on **Compare with the last run**, save the input as a task, and give it a schedule in Apify. Use a different **Watch name** for each task.
4. Send the results where you work with Apify's integrations: a Google Sheet, Slack, a webhook, or the API.

Example: price two hotels for each night of December, comparing with yesterday.

```json
{
    "hotels": ["Hotel Granvia Kyoto", "https://www.google.com/travel/hotels/entity/ChkI8oXIy_mdvvdPGg0vZy8xMWg4MWhkd3FjEAE"],
    "checkInDate": "2026-12-01",
    "checkInDays": 31,
    "adults": 2,
    "currency": "USD",
    "trackChanges": true,
    "watchName": "kyoto-station"
}
```

### What you get

One row per hotel and check-in date.

| Field | What it is |
| --- | --- |
| `name`, `hotelId`, `url` | The hotel, its Google Hotels ID (reuse it under Hotels) and its Google Hotels page |
| `checkIn`, `checkOut`, `nights`, `adults` | The stay the price is for |
| `pricePerNight`, `totalPrice`, `currency` | Google's lowest price, taxes and fees included, and the total for the stay |
| `totalPriceBreakdown` | The total split into base price, taxes and fees |
| `offers` | Each booking site's price per night and for the stay, whether it is the hotel's own site, free cancellation and its deadline, and notes such as member rates. Cheapest first |
| `lowestOffer` | The cheapest site, for quick filtering |
| `change`, `previousPricePerNight`, `priceChange`, `priceChangePercent` | With **Compare with the last run**: `down`, `up`, `same`, `soldOut`, `available` (back after being sold out) or `new` |
| `hotelClass`, `rating`, `reviewCount`, `ratingBreakdown` | Stars, guest rating, number of reviews, and reviews per star |
| `latitude`, `longitude`, `address`, `phone`, `website` | Where it is and how to reach it. Full address and phone come with booking-site prices |
| `description`, `checkInTime`, `checkOutTime`, `thumbnail` | Google's short description, check-in and check-out times, one photo |
| `query`, `rank`, `source` | Which destination or hotel input the row came from, and its place in the destination list |

`offers`, `lowestOffer`, `address` and `phone` are on rows for the hotels you listed, and on destination rows when **Add prices from each booking site** is on.

### Pricing

You pay per result, and comparing with the last run is free.

| Event | Price |
| --- | --- |
| Run start | $0.003 per run (with the default memory) |
| Hotel result: one hotel for one check-in date | $2.00 per 1,000 |
| Booking-site prices added to a result | $3.00 per 1,000 results that have at least one price |

Some examples:

- 100 hotels in a city for one date: $0.20.
- Your hotel and 9 competitors, 30 check-in dates, every day: 300 results with booking-site prices a day, $1.50 a day or about $45 a month.

Set a maximum cost per run in Apify if you want a hard limit. The run stops when it is reached, and only the results you were charged for are saved.

### Good to know

- **Currency.** Booking-site prices come in the currency you choose. Destination lists without booking-site prices come in US dollars. Every row has a `currency` field.
- **Guests.** Booking-site prices use the number of adults you set. Destination lists without booking-site prices are for Google's default of 2 guests. Children are not supported yet.
- **Destination lists change order.** Google reorders hotels between pages and between runs, so a destination list is a snapshot, and a hotel can show up as `new` on the next run. To track prices, list the hotels under **Hotels**.
- **Dates.** Google sometimes cannot price a date (sold out, or too far ahead). Such hotels show a `null` price or are skipped, and the run log says so.
- **Failed runs.** If errors keep the run from returning any result (Google refusing requests, or answers in a format the scraper cannot read), the run fails instead of finishing empty, so a scheduled task shows the problem. A hotel ID that Google does not know only adds a warning.
- **Watching.** The previous prices for each watch name are kept in a key-value store in your Apify account named `google-hotels-scraper-<watch name>`. Two runs with the same watch name cannot run at once; the second one stops with a message.
- **Booking links.** Rows link to the hotel's Google Hotels page rather than to booking sites, because Google's booking links are ad clicks.

# Actor input Schema

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

One destination per line, such as Kyoto, Paris 11th arrondissement or hotels near Times Square. Leave the dates out: they come from the date settings below. Each destination gives a list of hotels with Google's lowest price.

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

Specific hotels to price, one per line: a Google Hotels link, a hotel ID from an earlier run (hotelId, starts with Ch), or the hotel's name. A name is looked up and must match a hotel's name on Google. If none matches, the run log lists the closest hotels and their IDs. These hotels always come with prices from each booking site.

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

First check-in date. Leave empty to use the day 14 days after each run, which keeps scheduled runs on future dates.

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

Length of each stay.

## `checkInDays` (type: `integer`):

How many check-in dates to check, one day apart, starting from the check-in date. 30 gives a month of prices for every hotel. Each date is a separate result.

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

Guests per room. Applies to the prices from each booking site. Destination lists without booking-site prices use Google's default of 2 guests.

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

Three-letter code such as USD, EUR or JPY, for the prices from each booking site. Destination lists without booking-site prices come in US dollars. Every result says its currency.

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

Most hotels to return for each destination and check-in date. Google shows about 20 per page.

## `includePrices` (type: `boolean`):

Also get every booking site's price (Booking.com, Expedia, the hotel's own site and others), the address and the phone number for each hotel in the destination lists. Charged as an add-on per result. Hotels you list under Hotels always have them.

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

Add how each price changed since the last run with the same watch name: down, up, same, sold out, available again, or new. Free. Use it with a schedule.

## `watchName` (type: `string`):

Keeps the previous prices apart for different hotel sets. Give each saved task its own name. The previous prices are kept in a named key-value store in your account (google-hotels-scraper-<name>).

## Actor input object example

```json
{
  "searchQueries": [
    "Kyoto"
  ],
  "nights": 1,
  "checkInDays": 1,
  "adults": 2,
  "currency": "USD",
  "maxHotelsPerSearch": 10,
  "includePrices": false,
  "trackChanges": false,
  "watchName": "default"
}
```

# Actor output Schema

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

One row per hotel and check-in date: Google's lowest price, rating, stars and location. Hotels you listed, and destination lists with booking-site prices turned on, also have each booking site's price, the address and the phone number. With Compare with the last run on, each row says how its price changed.

# 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 = {
    "searchQueries": [
        "Kyoto"
    ],
    "maxHotelsPerSearch": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("lyklo/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 = {
    "searchQueries": ["Kyoto"],
    "maxHotelsPerSearch": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("lyklo/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 '{
  "searchQueries": [
    "Kyoto"
  ],
  "maxHotelsPerSearch": 10
}' |
apify call lyklo/google-hotels-scraper --silent --output-dataset

```

## MCP server setup

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