# Google Hotels Price Tracker — Hotel Prices by City & Dates (`northbell/google-hotels-price-tracker`) Actor

Hotel prices from Google Hotels for any city, dates and number of guests: price per night and total, stars, rating, reviews, amenities, the cheapest booking site and its price on other sites. Run it again or on a schedule to get the price change since the last run. Currency of your choice. No login.

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

## Pricing

from $1.60 / 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 Price Tracker — Hotel Prices by City & Dates

Give it a list of cities — with check-in and check-out dates and the number of guests if you like — and get one clean row per hotel from Google Hotels: **price per night, total for the stay, stars, rating, review count, amenities, the cheapest booking site** (and the price on other sites), address and a link. **$2 per 1,000 hotels**, no login, no API key, prices in the currency you choose.

Run it again — or put it on a schedule — and every hotel you have seen before also shows **what changed since the last run**: `previousPrice`, `priceChange` and `priceChangePercent`. Google only shows today's price; this Actor keeps the history for you, in your own Apify account.

### What you get

One row per hotel (`type: "hotel"`), one free summary row per search (`type: "summary"`), and a free error row for a search that could not be read (`type: "error"`).

| Field | What it is |
|---|---|
| `search`, `resolvedPlace` | the city you gave, and the place Google understood it as |
| `rank` | the order the hotels were found in. **Google reshuffles its list on every request, so this is not a stable ranking** (see Notes) |
| `id`, `name`, `propertyType`, `hotelClass` | the hotel, its type as Google files it (`hotel`, `hostel`, `guest house`, `resort hotel`…) and its stars (1–5) |
| `rating`, `reviewCount` | Google guest rating (out of 5) and number of reviews |
| `pricePerNight`, `totalPrice`, `currency` | the price Google shows for your dates: **total for the whole stay ÷ nights**, and the total, in the currency Google answered in |
| `priceInsight` | Google's own label when it shows one, e.g. "52% less than usual" |
| `checkIn`, `checkOut`, `nights`, `adults` | the stay that was priced |
| `lowestPriceSite`, `lowestPriceSitePerNight`, `priceBySite` | the site with the lowest price (often the hotel's own site), its price per night, and the price per night on up to 10 sites, cheapest first |
| `amenities` | what Google lists on the result: Free Wi-Fi, Pool, Free breakfast… |
| `address`, `latitude`, `longitude`, `googleHotelUrl` | where it is, and a link that opens the hotel on Google Hotels with your dates and guests |
| `previousPrice`, `priceChange`, `priceChangePercent` | the price when this hotel was last seen, and the difference (negative = cheaper). `null` the first time a hotel is seen |
| `previousCheckIn`, `previousObservedAt`, `stayMoved` | which stay that earlier price was for, when it was read, and whether the stay dates are different now (see Notes) |
| `observedAt` | when the row was read |

The summary row has `hotelsRead`, `medianPrice`, `cheapestName`, `cheapestPrice`, `highestPrice`, `hotelsComparedWithLastRun`, `priceDrops`, `priceRises` and `notes` (anything you should know about that search, such as Google answering in another currency).

### Run it again and again

- **On a schedule** — save your input as a task and add a **Schedule**: the same searches every day. Send each run to Google Sheets, Slack or email with an integration on the task.
- **Watch for changes** — Keep the same input on the schedule. Each run is its own dataset with the date it ran, so the series builds up run by run and you can compare one day with the last.
- **In bulk** — Put every city and date range in **Searches** in one run.

### Use it for

- **Trip and event price watching** — fix your dates, schedule a daily run and see which hotels got cheaper
- **Market snapshots** — the median and cheapest nightly price in a city for a weekend, a conference or a season
- **Price comparison across booking sites** — `priceBySite` shows where each hotel is cheapest
- **Hospitality and travel research** — stars, ratings, amenities and prices for a whole city in one table

### Input

```json
{
  "searches": [
    { "city": "Lisbon", "checkIn": "2026-11-10", "checkOut": "2026-11-12", "adults": 2 },
    "Paris"
  ],
  "currency": "EUR",
  "maxHotelsPerSearch": 50
}
```

- A plain name (`"Paris"`) is priced for a stay that starts **30 days after the run, for 2 nights**, for 2 adults.
- Use fixed dates (`checkIn` + `checkOut`, or `checkIn` + `nights`) when you want to **track one stay over time**.
- `city` can also be a phrase such as `"boutique hotels in Kyoto"` or `"hotels near Eiffel Tower"`.
- `adults` (1–10) can be set per search or once for all. `currency` is any of the 72 Google offers. `maxHotelsPerSearch` is 1–500.
- Put all your searches in one run: the run-start fee is charged once.

The history is kept per hotel in a named key-value store in your Apify account, so the second run of the same Actor already shows changes. Schedule it (Apify → Schedules) for a daily history.

### Pricing

**$2 per 1,000 hotels**, plus $0.01 per run. Error rows and summary rows are free. The $0.01 run-start fee is the one charge every run pays, even one that returns nothing.

### Notes

- **What the price is.** The price Google Hotels shows for one room for your guests, with the taxes and fees Google adds in. `totalPrice` is Google's total for the stay and `pricePerNight` is that total divided by the nights. Prices are read as an English-language visitor from the United States and the Actor has no country setting. (In a test on 8 October 2026 the market setting made no difference to the prices of 12 Lisbon hotels for the US, Germany, Japan and Brazil, but we only ran it from one place and do not claim prices are the same in every country.)
- **Currency.** You choose it and Google converts at its own rate. Every row carries the currency Google actually answered in. If that were ever different from your setting, the summary row says so. Price changes smaller than 0.5% are reported as `0`: they are currency conversion noise, not a new price.
- **Google shows a different slice of a city each time.** In our tests the same search returned about two thirds of the same hotels on a second call, in a different order. So `rank` is only the order of discovery, and a price change is only shown for a hotel that appears in both runs. The Actor remembers up to 1,500 hotels per search for 120 days and does not forget hotels that did not show up last time, so coverage grows with every run. For a steadier set, ask for more hotels (up to 500) or search something narrower, such as `"4 star hotels in Lisbon"`.
- **Fixed dates or rolling dates.** With fixed dates every change is like for like. With plain city names the stay starts 30 days after each run, so tomorrow's run prices a stay one day later; `stayMoved` is then `true` and `previousCheckIn` shows which stay the old price was for.
- **Dates Google accepts.** Check-in from today up to 320 days ahead (later than that Google shows almost no prices), 1–30 nights. For dates outside that Google quietly answers for other dates; the Actor notices and returns an error row instead of prices for the wrong stay.
- **Large groups.** Google prices one room for all the adults you give. From about 5 adults up, few hotels have a room that sleeps everyone and the rest come back without a price, so you get far fewer rows (in a test, Oslo for 2 nights with 6 adults gave 3 priced hotels in the first 14 pages of about 270 listings, and 8 adults gave 1). The summary row then says Google listed only that many hotels with a price. For a big group, search per room: 2 or 3 adults at a time.
- **Vacation rentals** (apartments Google mixes into the list) are left out unless you switch them on. Sponsored hotel ads are never included. Google also lists a few places that are not hotels but offer rooms (a ski resort, an RV park): `propertyType` tells you, so you can filter them out.
- **Headline price and site prices are read a moment apart.** `pricePerNight` comes from Google's results list and `priceBySite` from the hotel's own page. For roughly 1 hotel in 10 in our tests (11 of 165 in one, 10 of 75 in another) the cheapest site was more than 1% above or below the headline price, so compare `lowestPriceSitePerNight` with `pricePerNight` when the exact figure matters.
- **Fields that are only filled in some cases.** `hotelClass` is empty for the many hostels, capsule hotels, guest houses and inns that Google gives no star class (about a third of the rows in our test). `priceInsight` appears only when Google shows a "less than usual"-type label. `lowestPriceSite`, `lowestPriceSitePerNight`, `priceBySite` and `address` need *Read booking sites and address* (on by default; it costs one extra request, about 1.5 seconds, per hotel). They are empty when Google returns no page for that hotel, and `address` is often empty for vacation rentals. `amenities` lists the amenities Google puts on the result card, not every amenity the hotel has. `previousPrice`, `priceChange` and `priceChangePercent` are `null` for a hotel not seen before.
- **A misspelled place.** Google then guesses a wider area, often a whole country. The summary row says what Google understood (`resolvedPlace`) and adds a note when that does not look like what you typed.
- Public data only: what anyone sees on Google Hotels without signing in. No reviewer names, phone numbers or email addresses are returned.

Looking for stays and flights too? See [Airbnb Listings Tracker](https://apify.com/northbell/airbnb-listings-tracker) and [Google Flights Price Tracker](https://apify.com/northbell/google-flights-price-tracker).

### For AI agents

`{"searches": ["Lisbon"], "maxHotelsPerSearch": 5}` returns 5 hotel rows (`type: "hotel"`) with `pricePerNight`, `totalPrice`, `currency`, `hotelClass`, `rating` and `lowestPriceSite`, plus one `summary` row with `medianPrice` and `cheapestName`. Rows have `type`: `hotel`, `summary` or `error`. To watch one stay, pass fixed `checkIn` and `checkOut` and run it again later: `priceChange` is then the difference from the last run, negative when the hotel got cheaper.

# Actor input Schema

## `searches` (type: `array`):

One search per entry. A plain city name ("Paris") is priced for a stay that starts 30 days from the run and lasts 2 nights, for the number of adults below. For fixed dates use an object: {"city": "Lisbon", "checkIn": "2026-11-10", "checkOut": "2026-11-12", "adults": 2}. Use fixed dates to track one stay over time. You can also write "nights" instead of checkOut, or a phrase such as "boutique hotels in Kyoto". Put all your searches in one run: the run-start fee is charged once. Up to 50 per run.

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

The currency prices are shown in. Google converts at its own rate. Every row carries the currency Google actually answered in; if it ever differs from this setting the summary row says so.

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

Guests per room for every search that does not set its own "adults". Google prices one room for this many adults, so from about 5 adults up only hotels with a room that sleeps everyone come back with a price (far fewer rows). For a big group, search 2 or 3 adults at a time.

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

How many hotels with a price to return for each search. Each page of Google results holds about 20, and the Actor reads page after page until it has this many, Google runs out, or three pages in a row bring no new priced hotel. You pay per hotel returned.

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

Google mixes apartments and vacation rentals into its hotel lists. Off: hotels, hostels, guest houses and inns only. On: rentals too (their propertyType is "vacation rental").

## `includePriceSources` (type: `boolean`):

On: one extra request per hotel adds the cheapest booking site (lowestPriceSite), the price on up to 10 sites (priceBySite) and the street address. Roughly 1.5 seconds per hotel. Off: much faster, and those three fields stay empty.

## Actor input object example

```json
{
  "searches": [
    {
      "city": "Lisbon",
      "adults": 2
    },
    "Paris"
  ],
  "currency": "USD",
  "adults": 2,
  "maxHotelsPerSearch": 20,
  "includeVacationRentals": false,
  "includePriceSources": true
}
```

# Actor output Schema

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

Price per night and total, stars, rating, cheapest site and price change since the last run.

## `summaries` (type: `string`):

One row per search: hotels read, median, cheapest and highest price, and how many prices moved since the last 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 = {
    "searches": [
        {
            "city": "Lisbon",
            "adults": 2
        },
        "Paris"
    ],
    "maxHotelsPerSearch": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("northbell/google-hotels-price-tracker").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 = {
    "searches": [
        {
            "city": "Lisbon",
            "adults": 2,
        },
        "Paris",
    ],
    "maxHotelsPerSearch": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("northbell/google-hotels-price-tracker").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 '{
  "searches": [
    {
      "city": "Lisbon",
      "adults": 2
    },
    "Paris"
  ],
  "maxHotelsPerSearch": 20
}' |
apify call northbell/google-hotels-price-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,northbell/google-hotels-price-tracker"
        }
    }
}
```

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/zeuSk4eLSJzRpUYOV/builds/GWs9Li5n7Lv5WxdJh/openapi.json
