Hotel Rate Parity Monitor: Who Undercuts Your Site avatar

Hotel Rate Parity Monitor: Who Undercuts Your Site

Pricing

from $0.80 / 1,000 checked dates

Go to Apify Store
Hotel Rate Parity Monitor: Who Undercuts Your Site

Hotel Rate Parity Monitor: Who Undercuts Your Site

Check a hotel's rate parity on Google Hotels, date by date: which booking sites charge less than the hotel's own site, by how much, and the dates on which the hotel's own site is not listed. Scorecards per hotel and per site. Not affiliated with Google.

Pricing

from $0.80 / 1,000 checked dates

Rating

0.0

(0)

Developer

Aleksandr Kobtsev

Aleksandr Kobtsev

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

2

Monthly active users

2 days ago

Last modified

Share

Check a hotel's rate parity on Google Hotels, date by date: what the hotel's own site charges, which booking sites charge less, by how much, and the dates on which the hotel's own site is not listed at all. One dataset row per hotel and check-in date, a scorecard for each hotel and for each booking site, the list of breaches with the biggest gaps first, and an alert when a site is well below the hotel's own price.

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 rate parity monitor for?

You areWhat you runWhat you get
A hotel owner or revenue manageryour hotel, the next two weeks, every daythe dates on which a booking site is below your own price, which site, how far, and whether you are listed on Google with your own site at all
A hospitality marketing or revenue agencythe hotels of your clients, weekly, one run per clienta scorecard for each hotel and a list of breaches you can send to the booking site's account manager
A hotel chain or a management companythe portfolio, a few dates a weekthe hotels that are undercut most often and the sites that do it, ranked
A channel manager or a metasearch consultanta city, one weekendthe market's parity at a glance: how many hotels are undercut and by whom

What makes this different from a price scraper?

  • It starts from the hotel's own price. For every date it finds the hotel's own site among the sites Google lists, and compares every other site with it. A scraper gives you a list of prices; this gives you the verdict and the gap.
  • It says when the hotel's own site is not listed. On a date for which Google lists booking sites and not the hotel's own, a guest cannot book direct from Google's page. That is a finding of its own, not a missing price.
  • It scores hotels and sites. HOTEL_SCORECARDS gives each hotel its share of dates in parity, undercut and not listed, its median and worst gap and the sites that undercut it most. SITE_SCORECARDS ranks the booking sites over the whole run.
  • The country of sale is a setting. Google lists different sites at different prices for guests of different countries; run the same hotels for the markets you sell to.
  • A date with no price at all is free. It is delivered, marked sold out, and not charged.

What data does it return?

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

FieldWhat it is
name, hotelClass, rating, reviewsCountThe hotel, its stars (null where Google does not class it), Google's guest rating of 5 and the number of reviews.
city, countryCode, websiteWhere it is and its own website as Google lists it.
googleUrl, googleMid, entityTokenThe 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, countryThe 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.
availablefalse 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.
parityStatusparity when no site is the asked percent or more below the hotel's own site, undercut when one is, no_official_offer when the hotel's own site is not among the sites Google lists a price for; null without a price.
ownPrice, ownSiteThe hotel's own price per night, as Google shows it (with taxes and fees where Google splits them out), and the name Google gives its site. null when it is not listed.
cheapestSite, cheapestPriceThe booking site with the lowest price and that price, per night.
worstGapPercent, breachCountHow far below the hotel's own price the cheapest breaching site is, in percent, and how many sites are at least the asked percent below it.
breachesThe sites that undercut the hotel's own site, the biggest gap first: site, price, percentBelow, freeCancellation and bookingUrl (the booking site's own page for this hotel and stay).
sitesCountHow many booking sites have a price for the hotel on the date.
alertsWhy the row is on the ALERTS list: undercut, no_official_offer (below).
query, source, scrapedAtThe 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).
customDataYour 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. It had twelve sites below its own; three are shown, and the links in it are shortened.

{
"name": "Best Western Premier Batumi",
"hotelClass": 5,
"rating": 4.3,
"reviewsCount": 1056,
"city": "Batumi",
"countryCode": "GE",
"website": "https://www.bestwestern.ru/ru_RU/book/hotel-details.91457.html?aff=BRU&i...",
"googleUrl": "https://www.google.com/travel/hotels/entity/ChkIhOLMzo-nnJ1fGg0vZy8xMWdu...",
"googleMid": "0x406787b5000b26db:0x5f3a7138f9d33104",
"entityToken": "ChkIhOLMzo-nnJ1fGg0vZy8xMWduamJjcmJsEAE",
"checkIn": "2026-11-01",
"checkOut": "2026-11-02",
"nights": 1,
"dayOfWeek": "Sun",
"adults": 2,
"currency": "USD",
"country": "us",
"available": true,
"parityStatus": "undercut",
"ownPrice": 101.2,
"ownSite": "Best Western Premier Batumi",
"cheapestSite": "Super.com",
"cheapestPrice": 65.67,
"worstGapPercent": 35.11,
"breachCount": 12,
"breaches": [
{ "site": "Super.com", "price": 65.67, "percentBelow": 35.11, "freeCancellation": false, "bookingUrl": "https://www.super.com/travel/transition/?data=price=53.83%26total_price=..." },
{ "site": "Reserving", "price": 69.14, "percentBelow": 31.68, "freeCancellation": false, "bookingUrl": "https://h-en.reserving.com/search?i=7103&rf=GOOGLEHOTELS&portal=rsvcom&l..." },
{ "site": "Reservation Day", "price": 70.66, "percentBelow": 30.18, "freeCancellation": false, "bookingUrl": "https://www.reservationday.com/transition/?data=price=59.88%26total_pric..." }
],
"sitesCount": 24,
"alerts": ["undercut"],
"query": "hotels in Batumi",
"source": "search",
"scrapedAt": "2026-10-11T22:24:08.873Z"
}

The records of the run

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

HOTEL_SCORECARDS: one line per hotel over all its dates.

FieldWhat it is
name, entityToken, googleMid, googleUrl, websiteThe hotel and its identifiers.
dates, priced, soldOutDates checked, dates with a price and dates without one.
parity, undercut, noOfficialOfferOf the priced dates, how many are in parity, undercut and not listed with the hotel's own site.
parityShare, undercutShare, noOfficialOfferShareThe same as shares of the priced dates, 0 to 1; null when no date has a price.
medianWorstGapPercent, maxWorstGapPercent, worstDateOver the dates the hotel was undercut: the median of the worst gap, the biggest worst gap and its date.
topSitesThe sites that undercut the hotel most often, up to five: site, dates, averageGapPercent, maxGapPercent.

SITE_SCORECARDS: one line per booking site that undercut a hotel in the run, the most frequent first: site, breaches (hotel dates on which it was below the hotel's own site), hotels, averageGapPercent, maxGapPercent and shareOfUndercutDates (the share of the run's undercut hotel dates it was among the sites below, 0 to 1).

BREACHES: every site below a hotel on a date, the biggest gaps first: name, entityToken, checkIn, dayOfWeek, site, price, ownPrice, percentBelow, currency and url (the hotel's Google page for the stay). At most 2,000 lines.

DATE_SUMMARY: the hotels of the run on each date: checkIn, dayOfWeek, hotels, priced, soldOut, parity, undercut, noOfficialOffer, undercutShare and worstGapPercent.

ALERTS: the rows that raised an alert, the earliest date first: name, entityToken, checkIn, dayOfWeek, alerts, ownPrice, worstGapPercent, worstSite, cheapestSite, cheapestPrice, currency and url.

SUMMARY: hotels, dates, rowsRead, rowsDelivered, priced, soldOut, parity, undercut, noOfficialOffer, undercutShare, noOfficialOfferShare, alerts, 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?

AlertThe rule
undercutA booking site is at least Alert on a gap of at least percent (10 by default) below the hotel's own price for the date.
no_official_offerGoogle lists booking sites with a price for the hotel on the date and the hotel's own site is not among them. Can be switched off.

What did a real check show?

Measured on the platform on 12 October 2026: ten hotels of Batumi, thirty check-in dates starting two days ahead, one night, two adults, sold in the United States, a gap of two percent. 290 of the 300 hotel dates had a price.

  • The hotel's own site was undercut on 157 dates (54 percent), in parity on 46 (16 percent) and not listed on 87 (30 percent).
  • On the undercut dates the median of the worst gap was 22.7 percent and the biggest 61.3 percent; 151 dates had a gap of ten percent or more and 87 of twenty percent or more.
  • The picture was by hotel, not by date. Five of the ten were undercut on every priced date but one or two, one on 12 of 30 and one on 2 of 30; three were not listed with their own site on any date. One hotel had 23 to 25 sites below its own on every date.
  • The sites below the hotel's own most often were Reservation Day (115 hotel dates, four hotels, 20.6 percent on average), Super.com (96, six hotels, 21.2 percent), Etrip.net and Vio.com (66 each) and goseek.com (62).

How to read it. Google lists the price a guest sees on each site, including member, app-only and bundle rates and sites that resell the same room. A site below the hotel's own price is a fact about what a guest sees; whether it breaks a contract or is a rate the hotel allows is for the hotel to judge. A hotel that is not listed with its own site may simply not take part in Google's booking links.

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.
  2. Set Check-in dates to check and Days between check-ins: 14 dates one day apart is the next two weeks, 13 dates a week apart is three months.
  3. Set Country of sale to the market your guests come from; run again for the next market.
  4. Press Start, or put the run on a schedule (daily or weekly) and read ALERTS and HOTEL_SCORECARDS after each run. An integration (Slack, e-mail, a webhook) on the run's success sends the records where you work.

From the API:

{
"hotels": ["Hilton Batumi", "Radisson Blu Batumi", "Le Meridien Batumi"],
"daysAhead": 1,
"dates": 14,
"country": "us",
"currency": "USD",
"minGapPercent": 2,
"alertGapPercent": 10
}

What can I set?

SettingWhat it does
HotelsHotels by name with the city, or by Google Hotels link.
Searches, Hotels per searchTexts to search on Google Hotels, and how many of the hotels each lists to check, 1 to 200 (20 by default).
First check-in date, Days aheadThe first check-in: a date, or this many days from today (1 by default). A scheduled run with Days ahead always checks the same distance ahead.
Check-in dates to check, Days between check-insHow many dates (1 to 120, 14 by default) and the gap between them (1 to 30 days). Every hotel is read once for every date.
NightsThe length of each stay, 1 to 30 (1 by default).
Adults, Children (ages)The party the prices are for.
Currency, Country of sale, LanguageThe currency of the prices, the country Google sells the stay in (it decides which booking sites it lists and at what price) and the language of Google's texts.
Smallest gap that counts (%)A site is a breach when it is at least this percent below the hotel's own site, 1 to 90 (2 by default).
Alert on a gap of at least (%)The gap that raises undercut; 0 raises it for every breach (10 by default).
Alert when the hotel's own site is not listedRaises no_official_offer (on by default).
Custom dataJSON copied onto every row, for telling clients or runs apart.
Requests in parallel1 to 10, five by default.
ProxyApify 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 for thirty dates, 300 rows, took 5 minutes 18 seconds and used $0.0179 of platform usage. 290 of the rows had a price, so the run costs a buyer on the free plan 290 x $0.0012 + 300 x $0.00001 + $0.00005, about $0.35. Five hotels for ten dates took 59 seconds.

Limits

  • A run checks one stay length, one party and one country of sale. Other lengths, parties or markets are separate runs.
  • Parity here is what Google shows for the stay at the moment of the request. A booking site may charge a different figure at checkout, and the same hotel shows different sites and prices in different countries.
  • 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. A breach seen on one date and one read is a lead, not a finding: read the same hotels on a schedule and look for the dates that come back.
  • "Not listed" means that Google lists booking sites with a price and not the hotel's own. It does not say why.
  • Google prices stays up to about eleven months ahead. A run delivers at most 20,000 rows.
  • 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.

This is an unofficial tool, not affiliated with, endorsed by or connected to Google LLC or any hotel or booking site. 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.

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.