# Google Hotels Price Tracker: Calendar, Deals & Typical Range (`aleksandrbooking/google-hotels-price-tracker`) Actor

Track a hotel's price on every booking site for each check-in date from Google Hotels: the lowest price, whether Google calls it low, typical or high for the dates, sold-out dates, price changes and alerts. Not affiliated with Google.

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

## Pricing

from $0.80 / 1,000 priced dates

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

Track what every booking site charges for a hotel on each check-in date, as Google Hotels lists it, and what Google itself says about that price: low, typical or high for that hotel and those dates. One dataset row per hotel and date, with the cheapest site, the hotel's own price, the typical range, the change since the last run and an alert when the price is low, falls, reaches your target or sells out. Put it on a schedule and read ALERTS.

There is no login, no browser and no partner API. Prices come from Google Hotels pages that anyone can open, read as plain HTML. The Actor requests only the `/travel/hotels/` pages Google's robots.txt leaves open, and says in every record what it could and could not read.

### Who is this hotel price tracker for?

| You are | What you run | What you get |
|---|---|---|
| A hotel owner or revenue manager | your hotel and its competitors, every day | your price against the set date by date (rank, rate index), the dates Google calls low or high for each hotel, who undercuts your own site |
| A travel agent, a deal site or a travel blogger | the hotels you write about, the next 60 days | the cheapest dates, the dates Google calls low, the price drops since yesterday |
| A traveller planning a trip | one hotel, a season | what it costs on each date and which dates are cheaper than usual for that hotel |
| An analyst | the hotels of a city, weekly | the market date by date: cheapest, median and dearest price, the share of hotels sold out |

### What makes this different from other Google Hotels price scrapers?

- **It says whether the price is low for that hotel.** Google prints a typical range for each hotel and stay and calls the price low, typical or high against it. The row has the range and the call, and the dates Google calls low raise an alert. A price calendar alone does not tell a cheap date from an ordinary one.
- **It knows which dates are sold out.** A date on which no booking site has a price is delivered as sold out and costs nothing. A date that had a price in the previous run and has none now raises `sold_out` once.
- **It compares you with the competitive set.** Name your own hotel and the COMPSET record gives, for every date, your price, the competitors' lowest, median and highest, your rank and your rate index.
- **It remembers.** Each run says what moved since the last: `previousPrice`, `priceChange`, `priceChangePercent` on every row and a PRICE_CHANGES record with the biggest drops first.
- **It shows every booking site.** The row keeps the offer of each site Google lists (price, total, free-cancellation deadline, link), the hotel's own price and which sites undercut it.
- **It is priced by the date that has a price.** A priced date is one event; a sold-out date is free.

### What data does it return?

One row per hotel and check-in date, in calendar order, hotel by hotel.

| Field | What it is |
|---|---|
| **name**, **hotelClass**, **rating**, **reviewsCount** | The hotel, its stars (`null` where Google does not class it), Google's guest rating of 5 and the number of reviews. |
| **address**, **city**, **countryCode**, **latitude**, **longitude**, **website** | Where it is and its own website as Google lists it. |
| **googleUrl**, **googleMid**, **entityToken** | The hotel's Google Hotels page for this stay, and Google's own identifiers: the map feature id (`null` for vacation rentals) and the token in the page address. Stable, so they are the keys to join runs on. |
| **checkIn**, **checkOut**, **nights**, **dayOfWeek**, **adults**, **currency**, **country** | The stay: check-in and check-out dates (YYYY-MM-DD), the length, the weekday of check-in (`Mon`, `Tue` ...), the guests, the currency of the prices and the country of sale they are for. |
| **available** | `false` when no booking site has a price for the hotel for this stay: the date is sold out or not bookable. Such a row is delivered and not charged. |
| **price**, **priceBeforeTaxes**, **total** | The lowest price per night among the booking sites, as Google shows it (taxes and fees included where Google splits them out), the same before taxes and fees (`null` where the site gives one figure only) and the price for the whole stay. |
| **cheapestSite**, **sitesCount** | The booking site with the lowest price and how many sites have a price. |
| **officialPrice**, **parityStatus**, **officialUndercutBy** | Rate parity: the price of the hotel's own site, `undercut`, `parity` or `no_official_offer`, and the sites that charge at least one percent less than the hotel's own site (`provider`, `price`, `percentBelow`, biggest gap first). |
| **offers** | Every booking site's offer, cheapest first: `provider`, `providerId`, `official`, `price`, `priceBeforeTaxes`, `total`, `totalBeforeTaxes`, `currency`, `originalPrice`, `promotion`, `freeCancellation`, `freeCancellationUntil`, `freeCancellationUntilText` and `bookingUrl`. Empty when the run was set to leave offers out. |
| **googlePrice**, **typicalLow**, **typicalHigh** | The price Google sets against the typical range, and the low and high ends of that range for this hotel and these dates. All three are before taxes and fees, as Google prints them: compare `googlePrice` with the range, not `price`. `null` when the page has no range. |
| **priceLevel** | `low` under the range, `typical` inside it, `high` above it, as Google judges; `null` when the page has none. |
| **pricePosition** | Google's own number from 0 (cheap for the hotel) to 1 (dear for the hotel). Not a share of the range. |
| **usualDeltaPercent**, **dealLabel** | The label Google prints under a price that is well below the usual one, as text (`19% less than usual`) and as a number (`-19`). Google prints it from 15 percent below. |
| **previousPrice**, **priceChange**, **priceChangePercent**, **previousScrapedAt** | With **Remember prices between runs**: the price this hotel and check-in date had in the previous run of the same kind of stay, the difference (negative is cheaper), the difference in percent and when that run was. `null` on a first run, and where either price is missing. |
| **alerts** | Why the row is on the ALERTS list: `low_for_the_dates`, `below_target`, `price_drop`, `sold_out` (below). |
| **query**, **source**, **scrapedAt** | The hotel name or search text the row came from, whether it was a `search`, a `name` or a `link`, and when it was read (ISO-8601, UTC). |
| **customData** | Your own JSON from the input, copied onto every row. Present only when you give it. |

An example row, as a run returned it on 11 October 2026: a hotel in Batumi, sold in the United States, for one night. The list of offers and the addresses in it are shortened.

```json
{
  "name": "Courtyard by Marriott Batumi",
  "hotelClass": 5,
  "rating": 4.3,
  "reviewsCount": 591,
  "address": "5 Sherif Khimshiashvili St, Batumi 6000, Georgia",
  "city": "Batumi",
  "countryCode": "GE",
  "latitude": 41.6417259,
  "longitude": 41.6157544,
  "website": "https://www.marriott.com/en-us/hotels/buscy-courtyard-batumi/overview/?scid=f2ae0541-1279-4f24-b197-a979c79310b0",
  "googleUrl": "https://www.google.com/travel/hotels/entity/ChkIkcLNqfSn-JFgGg0vZy8xMWcy...",
  "googleMid": "0x4067876ab1deee13:0x6023e13f45336111",
  "entityToken": "ChkIkcLNqfSn-JFgGg0vZy8xMWcyeGtzczRsEAE",
  "checkIn": "2026-10-27",
  "checkOut": "2026-10-28",
  "nights": 1,
  "dayOfWeek": "Tue",
  "adults": 2,
  "currency": "USD",
  "country": "us",
  "available": true,
  "price": 148.45,
  "priceBeforeTaxes": null,
  "total": 148.45,
  "cheapestSite": "Qantas Hotels",
  "officialPrice": 148.68,
  "parityStatus": "parity",
  "officialUndercutBy": [],
  "sitesCount": 22,
  "offers": [
    { "provider": "Qantas Hotels", "providerId": 660369587, "official": false, "price": 148.45, "priceBeforeTaxes": null, "total": 148.45, "totalBeforeTaxes": null, "currency": "USD", "originalPrice": null, "promotion": null, "freeCancellation": false, "freeCancellationUntil": null, "freeCancellationUntilText": null, "bookingUrl": "https://www.qantas.com/hotels/properties/894340?adults=2&children=0&infa..." },
    { "provider": "Courtyard by Marriott Batumi", "providerId": 100231600, "official": true, "price": 148.68, "priceBeforeTaxes": 126, "total": 148.68, "totalBeforeTaxes": 126, "currency": "USD", "originalPrice": 148.68, "promotion": "Get the best prices plus free Wi-Fi with free membership enrollment", "freeCancellation": false, "freeCancellationUntil": null, "freeCancellationUntilText": null, "bookingUrl": null },
    { "provider": "Expedia.com", "providerId": 89, "official": false, "price": 148.68, "priceBeforeTaxes": 126, "total": 148.68, "totalBeforeTaxes": 126, "currency": "USD", "originalPrice": null, "promotion": null, "freeCancellation": false, "freeCancellationUntil": null, "freeCancellationUntilText": null, "bookingUrl": null }
  ],
  "googlePrice": 126,
  "priceLevel": "low",
  "typicalLow": 133,
  "typicalHigh": 177,
  "pricePosition": 0.106,
  "usualDeltaPercent": -19,
  "dealLabel": "19% less than usual",
  "previousPrice": 148.45,
  "priceChange": 0,
  "priceChangePercent": 0,
  "previousScrapedAt": "2026-10-11T21:44:16.443Z",
  "alerts": ["low_for_the_dates"],
  "query": "hotels in Batumi",
  "source": "search",
  "scrapedAt": "2026-10-11T21:46:35.891Z"
}
```

#### The records of the run

Beside the dataset, the run writes these records to its key-value store.

**DATE_SUMMARY**: the market the run saw, one line per check-in date.

| Field | What it is |
|---|---|
| **checkIn**, **dayOfWeek** | The date and its weekday. |
| **hotels**, **priced**, **soldOut**, **soldOutShare** | Hotels read for the date, how many have a price, how many do not, and the share without a price (0 to 1). |
| **minPrice**, **medianPrice**, **maxPrice**, **cheapestHotel** | The spread of the lowest prices per night and the hotel that has the lowest. |
| **low**, **typical**, **high** | How many hotels Google calls low, typical and high for the date. |

**COMPSET**: with **Your hotel**, one line per date: your hotel against the other hotels of the run.

| Field | What it is |
|---|---|
| **checkIn**, **dayOfWeek** | The date and its weekday. |
| **myPrice**, **myLevel**, **mySoldOut** | Your lowest price per night, Google's call on it, and whether your hotel has no price for the date. |
| **competitors**, **competitorsSoldOut** | Competitors with a price and without one. |
| **compMin**, **compMedian**, **compMax** | The competitors' lowest, median and highest price per night. |
| **rank**, **cheaperCompetitors** | Your place among yourself and the competitors with a price (1 is the cheapest), and how many competitors are cheaper. `null` and 0 when you have no price. |
| **rateIndex** | Your price over the competitors' median, times 100: 100 is level with the median, 120 is a fifth dearer. |

**HOTELS**: one line per hotel over all its dates: **name**, **entityToken**, **googleMid**, **googleUrl**, **isMine** (it is your hotel), **query**, **dates**, **priced**, **soldOut**, **minPrice**, **medianPrice**, **maxPrice**, **cheapestDates** (the three cheapest: `checkIn`, `price`, `priceLevel`), **lowDates** (dates Google calls low) and **withTypicalRange** (priced dates for which the page gave a range).

**ALERTS**: the rows that raised an alert, the earliest date first: **name**, **entityToken**, **checkIn**, **dayOfWeek**, **alerts**, **price**, **currency**, **cheapestSite**, **priceLevel**, **usualDeltaPercent**, **previousPrice**, **priceChangePercent** and **url** (the hotel's Google page for the stay).

**PRICE_CHANGES**: the prices that moved since the previous run, the biggest drops first: **name**, **entityToken**, **checkIn**, **dayOfWeek**, **previousPrice**, **price**, **priceChange**, **priceChangePercent**, **currency**, **cheapestSite** and **url**.

**SUMMARY**: **hotels**, **dates**, **rowsRead**, **rowsDelivered**, **priced**, **soldOut**, **withTypicalRange**, **low**, **alerts**, **yourHotel**, **charged**, **notCharged**, **googleRequests**, **googleFailedAttempts** and **failed**.

**FAILED_HOTELS**: the searches, names and dates that could not be read, each with `what`, `stage` and `reason`; absent when there were none.

### What are the alerts?

An alert is a fixed rule over a row. A row can raise several; the ALERTS record lists them with the reason.

| Alert | The rule |
|---|---|
| `low_for_the_dates` | Google calls the price `low` for the hotel and the dates, or the label under it says at least **Alert when below the usual price by** percent below usual (15 by default). |
| `below_target` | The price is at or under **Target price per night**. |
| `price_drop` | The price fell by at least **Alert on a drop of at least** percent (10 by default) since the previous run. Needs **Remember prices between runs**. |
| `sold_out` | The hotel had a price for the date in the previous run and has none now. Raised once: the next run does not repeat it for the same date. |

### How does the typical range work?

On a hotel's own page Google prints a typical range for the stay and says whether the price is low, typical or high for it ("Prices are lower than usual for these dates"). The Actor reads that from the data of the page. Three things to know before relying on it:

- **It is not on every page.** Of 269 priced hotel dates measured on 12 October 2026 (ten hotels of Batumi, thirty dates starting two days ahead), 158 carried a range, 59 percent. The share was 63 percent for dates up to nine days ahead, 67 percent for ten to nineteen, 48 percent for twenty to twenty-nine and, in the few dates beyond, three of eight. Two of the ten hotels never carried one. A row without a range has `priceLevel` `null`; that says Google gave none, not that the price is typical.
- **It is before taxes and fees.** `googlePrice` and the range are the figures Google prints, which leave out taxes and fees where Google can split them out. `price` is what the booking site shows. In most of the rows of Batumi measured, `googlePrice` was `price` divided by 1.18, the 18 percent tax of Georgia. Set `googlePrice` against `typicalLow` and `typicalHigh`.
- **It depends on the market.** Google makes its call for the country of sale of the run, so the same hotel and dates can carry the label in one market and not in another. Measured on 12 October 2026: Courtyard by Marriott Batumi carried the label on fifteen of thirty dates sold in the United States and on none of twelve dates sold in Germany. Run the markets you sell to separately.
- **The call is Google's.** The Actor reads it and does not recompute it. On the 26 rows of one run that carried a range, `priceLevel` agreed with `googlePrice` against the range on all but one, whose price stood on the low end of the range.

The label (`dealLabel`, `usualDeltaPercent`) is a separate figure: Google prints it only from 15 percent below the usual price, and it was on 67 of the 269 rows, including all 32 that Google called low.

### How do I use it?

1. Under **Hotels** put hotel names with the city (`Hilton Batumi`) or paste a Google Hotels link of a hotel. Or under **Searches** type what you would type into Google Hotels (`hotels in Batumi`) and set **Hotels per search**. To compare your hotel with its competitors, put it under **Your hotel**.
2. Set **Check-in dates to track** and **Days between check-ins**: 30 dates one day apart is the next month, 13 dates a week apart is three months, one weekday every week.
3. Press **Start**, or put the run on a schedule (daily is the usual choice) and read ALERTS after each run. Turn on an integration (Slack, e-mail, a webhook) on the run's success to get the ALERTS record where you work.

From the API:

```json
{
  "myHotel": "Hilton Batumi",
  "hotels": ["Radisson Blu Batumi", "Sheraton Batumi Hotel", "Le Meridien Batumi"],
  "daysAhead": 1,
  "dates": 60,
  "nights": 1,
  "currency": "USD",
  "targetPrice": 120,
  "alertDropPercent": 10
}
```

### What can I set?

| Setting | What it does |
|---|---|
| **Hotels** | Hotels by name with the city, or by Google Hotels link. |
| **Your hotel** | Your hotel, tracked with the others; adds the COMPSET record. |
| **Searches**, **Hotels per search** | Texts to search on Google Hotels, and how many of the hotels each lists to track, 1 to 200. |
| **First check-in date**, **Days ahead** | The first check-in: a date, or this many days from today (1 by default). A scheduled run with **Days ahead** always prices the same distance ahead. |
| **Check-in dates to track**, **Days between check-ins** | How many dates (1 to 120, 30 by default) and the gap between them (1 to 30 days). Every hotel is read once for every date. |
| **Nights** | The length of each stay, 1 to 30 (1 by default). |
| **Adults**, **Children (ages)** | The party the prices are for. |
| **Currency**, **Country of sale**, **Language** | The currency of the prices, the country Google sells the stay in (it decides which booking sites it lists) and the language of Google's texts. |
| **Remember prices between runs** | On by default: the run remembers each hotel and date in a store of your own account (`google-hotels-tracker-memory`) and says what changed on the next run of the same kind of stay (same nights, guests, currency and country). |
| **Target price per night** | A price at or under it raises `below_target`. |
| **Alert on a drop of at least (%)**, **Alert when below the usual price by (%)** | The percents for `price_drop` and for the label side of `low_for_the_dates`. 0 switches them off. |
| **Every booking site's price in the rows** | On by default. Off: rows keep the lowest price, the cheapest site and the other fields, without the offers, which makes them much smaller. |
| **Custom data** | JSON copied onto every row. |
| **Requests in parallel** | 1 to 10, five by default. |
| **Proxy** | Apify datacenter proxies by default; your own proxies if you choose Custom proxies. |

### What does it cost?

Pay per event. A `date` event for every hotel and check-in date delivered with a price: $0.0012 on the free plan, $0.00105 Bronze, $0.0009 Silver, $0.0008 Gold and above. A date with no price (sold out) is delivered and costs nothing. The platform's own events are the start of the run ($0.00005) and the dataset item ($0.00001) for every row stored.

Measured on the platform on 12 October 2026: ten hotels of Batumi for thirty dates, 300 rows, took 4 minutes 40 seconds and used $0.0155 of platform usage, with 368 requests to Google and no failed attempt. 269 of the rows had a price and 31 were sold out, so the run costs a buyer on the free plan 269 x $0.0012 + 300 x $0.00001 + $0.00005, about $0.33. One hotel for fourteen dates took 16 seconds. A run of 1,000 rows (25 hotels of Lisbon for 40 dates) took 26 minutes 28 seconds and used $0.0765 of platform usage, with 1,634 requests to Google, one failed attempt and a peak of 177 MB of memory.

### Limits

- A run prices one stay length and one party. Different lengths or parties are separate runs, and each kind of stay has its own memory.
- Google prices stays up to about eleven months ahead, and gives a typical range for far fewer of them (above). A calendar of 120 dates for 100 hotels is 12,000 pages; one run delivers at most 20,000 rows.
- A hotel's page does not list the same booking sites in every answer: Google leaves some out, the more often the smaller the hotel. A hotel with few offers is read again, up to three times, and the offers are merged. How steady the figure is, measured on the same reading code: six hotels for ten dates were read three times on 11 October 2026 (165 pairs of reads of the same hotel and date). The cheapest price differed by more than half a percent in 4 pairs (2%), because a booking site listed in one answer was missing from the other; the Booking.com price and the hotel's own price did not differ in any pair. The default drop alert of 10 percent is above that noise; a lower one, or the `offers` entry of the site you care about, needs more care.
- "Sold out" means that no booking site Google lists has a price for the hotel on the date. A hotel can have a room it sells on its own site only, or be closed for the date for another reason.
- The memory is a store of your account. A date that has passed is forgotten; the first run of a kind of stay has no changes to report.
- Google's pages change from time to time. The Actor finds hotels and offers by their shape and checks that every page answers for the stay it asked, so a change shows as a clear error rather than as wrong rows; if it ever does, open an issue with the run link.

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

This is an unofficial tool, not affiliated with, endorsed by or connected to Google LLC or any hotel. It reads publicly visible pages and collects no personal data. Google's terms restrict automated access, and you are responsible for making sure your use complies with those terms and with the law in your jurisdiction. See [Apify's stance on web scraping legality](https://blog.apify.com/is-web-scraping-legal/).

What the Actor does about robots.txt: it reads Google's robots.txt at the start of every run and requests only addresses it leaves open, which are the `/travel/hotels/` pages. It refuses any address the file closes.

### Found a problem?

Open an issue on the Issues tab with the run link and the hotel. Breakages in Google's pages are the expected failure mode of any scraper, and this one is built to say so rather than to deliver wrong data. Reports get read.

# Changelog

This Actor's version history is a separate document: https://apify.com/aleksandrbooking/google-hotels-price-tracker/changelog.md

# Actor input Schema

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

Hotels to track by name with the city ("Hilton Batumi") or by their Google Hotels link (the address that has /entity/ in it). A name that matches no hotel well enough is listed in FAILED_HOTELS and is not charged.

## `myHotel` (type: `string`):

Optional. Your hotel by name with the city or by its Google Hotels link. It is tracked with the others, and the run adds a COMPSET record that sets your price against the other hotels of the run on every date: their lowest, median and highest price, your rank and your rate index.

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

What you would type into Google Hotels: "hotels in Batumi", "boutique hotels in Lisbon". The first hotels Google lists for each text are tracked; set how many under "Hotels per search".

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

How many hotels of each search text to track, 1 to 200. Every hotel is read once for every check-in date, so ten hotels for 30 dates is 300 rows.

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

YYYY-MM-DD. Leave empty to use "Days ahead" instead. Google prices stays up to about eleven months ahead.

## `daysAhead` (type: `integer`):

The first check-in is this many days from today, when no first check-in date is given. A scheduled run with this set always prices the same distance ahead.

## `dates` (type: `integer`):

How many check-in dates to price, starting with the first one. Each date is a stay of "Nights" nights and is one row for every hotel, charged when it has a price. 1 to 120. A calendar of 30 dates for 10 hotels is 300 rows.

## `stepDays` (type: `integer`):

The gap between the check-in dates: 1 for every day, 7 for the same weekday every week.

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

How many nights each stay lasts. One night gives the rate of the arrival date.

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

Adults in the room. Prices are for the whole party, not per person.

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

One entry per child, the age in years: 4, 11. Up to five children.

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

The currency prices are given in, and the target price and the typical range are in. Google converts for booking sites that charge in another currency.

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

The two-letter country code Google sells the stay in: us, gb, de, ge. It decides which booking sites Google lists and what they charge, which is why the same hotel shows different offers in different countries. It is not the country of the hotel.

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

The language of the texts Google returns: descriptions, labels, amenities.

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

On: each hotel and check-in date is remembered in a store of your own account (google-hotels-tracker-memory) and, on the next run of the same kind of stay (same nights, guests, currency and country), every row says what changed: previousPrice, priceChange and priceChangePercent, and a PRICE_CHANGES record lists the moves, biggest drops first. A date that was priced and has no price now is reported as sold out once. Put the run on a schedule and read ALERTS.

## `targetPrice` (type: `number`):

Optional, in the run's currency. A date priced at or below it raises the below_target alert.

## `alertDropPercent` (type: `integer`):

A price that fell by at least this percent since the previous run raises the price_drop alert. 0 switches it off. Needs "Remember prices between runs".

## `alertBelowUsualPercent` (type: `integer`):

A date whose label from Google says it is at least this percent below the usual price ("19% less than usual") raises the low_for_the_dates alert, in addition to the dates Google calls low. 0 leaves only Google's own call.

## `includeOffers` (type: `boolean`):

On: each row carries the offer of every booking site (price, total, free-cancellation deadline, link). Off: only the lowest price, the cheapest site, the hotel's own price and the other fields, which makes the rows much smaller. The hotel pages are read either way.

## `customData` (type: `object`):

Any JSON. It is copied onto every row, so rows of different runs can be told apart after merging.

## `concurrency` (type: `integer`):

How many requests run at the same time, across the whole run. The default is gentle on Google and quick enough.

## `proxy` (type: `object`):

Apify datacenter proxies are the default and what this Actor is priced on. Apify residential groups are not available here; a run that asks for one is refused in the first seconds, before any hotel is charged. For your own proxies choose Custom proxies and supply them.

## `dryRun` (type: `boolean`):

Produce data without charging events. Honored only for runs started by the Actor owner; ignored for everyone else.

## Actor input object example

```json
{
  "hotels": [
    "Hilton Batumi"
  ],
  "searchQueries": [],
  "maxHotelsPerSearch": 10,
  "daysAhead": 1,
  "dates": 14,
  "stepDays": 1,
  "nights": 1,
  "adults": 2,
  "childrenAges": [],
  "currency": "USD",
  "country": "us",
  "language": "en",
  "trackChanges": true,
  "alertDropPercent": 10,
  "alertBelowUsualPercent": 15,
  "includeOffers": true,
  "concurrency": 5,
  "proxy": {
    "useApifyProxy": true
  },
  "dryRun": false
}
```

# Actor output Schema

## `rows` (type: `string`):

No description

## `dates` (type: `string`):

No description

## `compset` (type: `string`):

No description

## `alerts` (type: `string`):

No description

## `changes` (type: `string`):

No description

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

No description

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

No description

## `failed` (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 = {
    "hotels": [
        "Hilton Batumi"
    ],
    "dates": 14
};

// Run the Actor and wait for it to finish
const run = await client.actor("aleksandrbooking/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 = {
    "hotels": ["Hilton Batumi"],
    "dates": 14,
}

# Run the Actor and wait for it to finish
run = client.actor("aleksandrbooking/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 '{
  "hotels": [
    "Hilton Batumi"
  ],
  "dates": 14
}' |
apify call aleksandrbooking/google-hotels-price-tracker --silent --output-dataset

```

## MCP server setup

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