How to Track Hotel Competitor Prices Across Booking Sites
Track hotel rates across booking sites with like-for-like searches, complete price records, and a repeatable workflow for spotting meaningful changes.
To track hotel competitor prices reliably, compare the same hotels across the booking sites your guests use, with the same stay dates, length of stay, guest count, room type, meal plan, cancellation terms, and rate eligibility. Record the total mandatory price, currency, availability, source, and capture time for every observation. A spreadsheet works for a small, occasional check; rate-shopping software can help when consistent coverage, history, alerts, or multi-property workflows become difficult to maintain manually.
A price difference is meaningful only after you rule out differences in itinerary, room, occupancy, taxes, fees, availability, and restrictions. Treat each observation as a time-stamped snapshot of a public offer, then verify notable changes before adjusting your rates.
1. Define the question and competitive set
Start with a decision, not a large list of hotels. You might want to understand weekend positioning, rates around a local event, forward demand for a holiday, or whether your own direct rate differs from your OTA listings. The question determines which properties, dates, and channels you need to observe.
Include properties guests could reasonably choose instead of yours. Consider location and access, property type and service level, room capacity, amenities, guest rating, and the occasions each property serves. A nearby hotel is not automatically comparable, and a hotel may be relevant for one season or guest segment but not another. Review your set periodically and note why each property belongs in it.
Keep your own property in the comparison. Checking your direct website alongside your OTA and distributor listings can reveal channel discrepancies that a competitor-only view will miss. A difference is a prompt to investigate; it does not by itself establish why the rate differs.
2. Standardize every search
Use a fixed search specification for every property and channel in a comparison. Save it with the observations so another person can reproduce the search.
- Dates and stay length: Use identical check-in and checkout dates. Include the same number of nights when comparing history.
- Occupancy: Match the number of adults and children, and children’s ages when the booking site asks for them.
- Room: Compare the same room category or a clearly documented equivalent, including capacity and bed configuration where relevant.
- Meal plan: Note whether breakfast or another meal is included.
- Cancellation and payment: Record whether the rate is refundable, the cancellation deadline, and payment timing.
- Eligibility: Label member, loyalty, mobile, country-specific, package, coupon, or other restricted rates. Do not present a conditional offer as generally bookable.
- Search context: Keep market, language, currency, device context, and other relevant search conditions consistent where possible.
Google’s hotel price accuracy policy says the selected check-in and checkout dates and occupancy must match the displayed price, and the price must be complete and bookable. This is a useful standard for a fair comparison even when you are recording prices manually. See Google’s hotel price accuracy policy.
3. Compare the full mandatory price
Do not compare a search-result headline price on one site with a checkout total on another. Record the nightly price and the total for the stay, plus mandatory taxes and fees where they are displayed. Preserve the price breakdown and the currency. Note optional charges separately; do not add them to the required total by default.
Google’s policy states that taxes and fees must represent all mandatory charges collected by the partner or hotel, regardless of when they are due. Local display rules and booking flows can differ, so record what the page actually shows and verify the final booking step when a difference could change a pricing decision. See Google’s price accuracy policy and Google’s taxes and fees guidance.
Also record whether the room is available at that price. A price shown for a sold-out room, an unavailable rate, or a rate that changes before booking is not equivalent to a currently bookable offer.
4. Build a repeatable manual tracking sheet
For a small competitive set and a manageable number of dates, a spreadsheet is often enough. Give the task a named owner and a schedule, use the same search specification each time, and retain dated observations instead of overwriting the latest rate.
Useful columns include:
- Observation ID and capture date/time, including time zone
- Your property or competitor name, location, and room/property identifier
- Booking channel and page URL or another page identifier
- Check-in, checkout, nights, adults, children, and child ages if relevant
- Room category, occupancy, bed configuration, and meal inclusion
- Refundability, cancellation deadline, payment timing, and eligibility restrictions
- Nightly base price, stay total, mandatory taxes and fees, currency, and displayed price breakdown
- Availability at the observed price and any change seen at checkout
- Notes about promotions, missing information, or differences from the standard search
Take a second observation or check the final booking page before interpreting an unusual rate as a durable market move. A single snapshot may reflect a temporary promotion, an inventory change, a sellout, or a transient display difference.
5. Automate page evidence when useful
When a team needs to preserve what a public booking page showed at a particular time, a screenshot can accompany the structured rate record. A screenshot is supporting evidence, not a substitute for recording the itinerary, rate conditions, total, currency, and availability in fields that can be compared.
You can capture a public page with a browser automation tool or a website screenshot API. For your own authorized workflows, keep a consistent URL and search context, save the capture timestamp with the record, and check the site’s terms and applicable rules before automating access. Do not treat a screenshot alone as proof that a rate remained available or was eligible for every guest.
DIY with a browser and Playwright (Node.js)
This runnable example captures a page you can access, using a URL supplied on the command line. It saves a full-page PNG and prints the capture time. It does not extract or validate rates; add site-specific parsing only for pages and workflows you are authorized to access, and retain the search conditions alongside any extracted value.
npm init -y
npm install playwright
npx playwright install chromium
// capture.mjs
import { chromium } from 'playwright';
const target = process.argv[2];
if (!target) {
console.error('Usage: node capture.mjs <public-page-url>');
process.exit(2);
}
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 1000 } });
const response = await page.goto(target, { waitUntil: 'domcontentloaded', timeout: 45000 });
if (!response) throw new Error('Navigation returned no HTTP response');
await page.screenshot({ path: 'rate-observation.png', fullPage: true });
console.log(JSON.stringify({
capturedAt: new Date().toISOString(),
url: page.url(),
status: response.status(),
screenshot: 'rate-observation.png'
}, null, 2));
} finally {
await browser.close();
}
Run it with a URL you are allowed to visit:
node capture.mjs 'https://example.com/hotel-page'
For a site you control or have permission to automate, adapt the browser setup to the page’s normal consent and loading flow. Avoid bypassing access controls, bot protections, or login restrictions. If the page depends on a known element becoming visible, wait for that element instead of adding an arbitrary long delay; if the page is slow, increase the navigation timeout deliberately and record that configuration.
cURL: call a screenshot API
A screenshot API can capture a URL without maintaining a browser installation. The example below uses ScreenshotNeo and writes the returned image to a file. Put your API key in an environment variable in a real shell rather than committing it to source control.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
Python: call a screenshot API
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
with open("shot.webp", "wb") as image_file:
image_file.write(r.content)
Node.js: call a screenshot API
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status} ${await res.text()}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer())));
Replace the example target with the public page you are authorized to capture. See the ScreenshotNeo API documentation for request options and response details. A screenshot records page appearance; keep the comparison fields in your spreadsheet or database so prices remain analyzable.
6. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server for developers. One GET request can return a PNG, JPEG, WebP, or PDF. For a quick capture, use the cURL call above; the equivalent Python and Node.js examples are in the preceding section, and the API docs cover the available parameters.
- Cookie and consent banners are accepted and removed before capture, along with 60+ known consent platforms, newsletter popups, and chat widgets; each step can be turned off.
- Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed. The response identifies page verdict and billing status in headers.
- An MCP server provides
take_screenshot,get_page_info, andcapture_pdffor Claude, Cursor, and other MCP clients. - The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots; every feature is available on every plan.
Sign up free for 1,000 screenshots a month, with no card required.
7. Read changes in context
Once you have several observations, look for repeated differences and movement over time. Compare your rate with the competitive-set range, not just one hotel’s lowest displayed number. Ask whether the apparent undercut is consistently bookable, restricted to members or mobile users, tied to a different room or meal plan, or limited to one distribution channel.
Use rate observations alongside your own pickup, inventory, booking pace, and revenue goals. A competitor’s public price does not reveal its costs, demand, available inventory, or pricing objective. Avoid changing your price based on one unexplained snapshot.
8. When to use rate-shopping software
Manual checks suit a small comp set, a few channels, and occasional validation of what a guest sees. Consider rate-shopping software when repeated checks are hard to maintain, many dates or channels matter, the team needs historical trends or alerts, or multiple properties need a shared workflow.
Provider capabilities vary by market and property. Hotel Compete describes daily updates, multiple rate-type comparisons, some brand-site shopping, OTA parity checks, forward-date shopping, and competitive-set management. MonitorHotels describes cross-channel competitor rate shopping, configurable competitive sets, rate histories, future-date trends, and OTA search-position information. These are vendor-described functions; confirm coverage and availability for your market and selected properties directly with the provider.
Cendyn describes Rate Match as continuously shopping rates, notifying hotels about OTA parity violations, and offering direct-price comparison or matching. Treat matching as an optional workflow. Check contract terms, applicable market rules, rate eligibility, and the underlying like-for-like comparison before responding. Vendor statements about business outcomes are not independent evidence of results.
Questions to ask in a demo or trial
- Coverage: Does it monitor the booking sites and direct channels guests use in your geography? Which properties or channels are excluded?
- Matching: Can it distinguish room, occupancy, length of stay, board, cancellation policy, member or mobile eligibility, and mandatory fees?
- Freshness and history: How often are near-term and farther-out dates checked? Are timestamps and historical observations retained?
- Competitive sets: Can you manage sets by season, segment, or property and understand missing observations?
- Alerts and workflow: Can staff set useful thresholds, see the source and conditions, and route an issue to the right person?
- Export and integration: Can data reach your revenue-management system, channel manager, dashboard, or spreadsheet without losing comparison conditions?
- Verification and cost: Can you compare the provider’s result against a manual booking-path check? What are current coverage, implementation, contract, and pricing terms?
Choose on relevant coverage and trustworthy like-for-like matching, not a feature count or an unverified performance claim. A frequent feed that cannot preserve rate conditions may be less useful than a slower feed that makes comparisons reproducible.
9. Troubleshooting common discrepancies
| What you see | Likely cause | What to check |
|---|---|---|
| A competitor appears much cheaper | Different dates, occupancy, room, meal plan, or restricted rate | Repeat the search with the same itinerary and eligibility; record the exact rate conditions. |
| Search result and checkout total differ | Taxes, mandatory fees, or other required charges appear later in the flow | Record the complete mandatory total and breakdown at the final booking step. |
| The displayed offer cannot be booked | Stale result, inventory change, or a room/rate that is no longer available | Verify availability and price on the booking path, then mark the original observation unavailable or changed. |
| Prices differ by country, device, or currency | Localized display, mobile or member offer, currency conversion, or market-specific conditions | Keep search context consistent and label any remaining difference; do not treat eligibility-specific rates as public rates. |
| Your direct rate differs from an OTA | OTA promotion, member/mobile offer, fees, stale page or feed, or mismatched room/rate terms | Compare the same conditions and verify both booking paths. Treat a parity alert as a lead to investigate, not proof of cause. |
| Automated capture is blank or incomplete | Page content loads after initial navigation, scripts are delayed, or the page changed its layout | For an authorized page, wait for a meaningful selector or a suitable load condition, inspect the resulting screenshot, and record the capture configuration. |
| Playwright reports navigation timeout | The page did not reach the requested load condition in the configured time | Check the URL and network access, use an appropriate wait condition, and adjust the timeout for the page. Do not assume a timeout means the offer itself is unavailable. |
| Screenshot API request fails | Invalid credentials, malformed URL, unsupported option, or failed page load | Check the API response and headers, validate the URL and key, consult the API docs, and distinguish a page verdict from a transport or request error. |
10. Performance, reliability, and cost
For manual work, effort grows with the number of properties, channels, dates, and rate conditions. Keep the initial scope small enough that staff can finish it on schedule, then expand based on the decisions the data supports. A standard template and fixed owner reduce inconsistent searches and duplicated work.
For automated capture, page load time and third-party scripts affect completion time. Capture only the evidence needed, use an appropriate viewport or full-page mode, and avoid requesting the same page repeatedly when a saved observation answers the question. Browser automation requires maintaining a runtime and handling site changes; an API avoids local browser setup but still depends on the target page loading and returning useful content.
For any workflow, save timestamps, conditions, source, and outcome. Retry or manually verify a failed or suspicious capture rather than interpreting missing data as a zero price. Respect site terms and access controls. Budget rate-shopping software against the channels and history you actually need, and request current pricing and contract details from vendors; no common price or coverage level can be assumed across providers.
Frequently asked questions
How often should a hotel check competitor rates?
Set a cadence that matches the decision and how quickly the relevant market changes. Keep it consistent, and add checks for important demand dates rather than treating one universal frequency as right for every property.
Should I match the lowest competitor rate?
Not automatically. First confirm that the offer is bookable and comparable, then weigh it against your own demand, inventory, pace, and revenue objectives.
Can a screenshot prove what a guest would pay?
It can preserve what a page displayed at a moment in a particular context. It does not by itself prove that the offer was available to every guest or remained bookable, so keep the search conditions and availability evidence with it.
Is a parity alert proof that an OTA is undercutting my rate?
No. It identifies a discrepancy to investigate. Room and rate terms, eligibility, taxes, currency, promotions, and stale data can all explain a difference.
What is the minimum useful tracking record?
At minimum, retain the source and time, stay dates and occupancy, room and rate conditions, total mandatory price and currency, and whether the offer was available.


