Hotel Price Intelligence & Rate Parity Tracker
Pricing
Pay per usage
Hotel Price Intelligence & Rate Parity Tracker
Compare hotel prices across Booking.com, Hotels.com, and Expedia in one run. Detect rate parity violations and find the best OTA deal for any hotel.
Pricing
Pay per usage
Rating
0.0
(0)
Developer
BotFlowTech
Actor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Compare hotel prices across Booking.com, Hotels.com, and Expedia in one run. Detect rate parity violations and find the best deals automatically.
What it does
This actor takes a list of hotel names (or a city/country) and a date range, then searches all three major Online Travel Agencies in parallel. For every hotel it produces a single comparison record containing:
- The lowest price per night on each OTA
- Which platform has the best deal (
bestOTA) - The absolute price variance in your chosen currency
- Whether rate parity is maintained (prices within 5% across OTAs)
- Availability status, room types, cancellation policy, and breakfast flags
Each record is pushed to the Apify dataset in real time as hotels are processed, so you can integrate it into monitoring dashboards, spreadsheet exports, or downstream webhooks.
Use cases
| Use case | Who uses it |
|---|---|
| Rate parity monitoring | Revenue managers at hotel chains checking that OTAs honor contracted rates |
| OTA competitive comparison | Travel agencies and booking platforms benchmarking competitor pricing |
| Price trend tracking | Running the actor on a daily schedule to build a 30-day pricing history per hotel |
| Deal-finder apps | Consumer apps surfacing the cheapest OTA for a given hotel and date |
| Hotel competitor intelligence | Independent hotels monitoring nearby property prices to adjust their own rates |
| Travel journalism | Deal-hunters and travel bloggers verifying "best price guarantee" claims |
Input
{"hotelNames": ["Marriott Times Square", "Hilton London Metropole"],"checkIn": "2025-06-15","checkOut": "2025-06-18","adults": 2,"rooms": 1,"currency": "USD","platforms": ["booking", "hotels", "expedia"],"maxHotels": 50}
Or use location-based bulk search instead of hotelNames:
{"searchByLocation": {"city": "Paris","country": "FR","stars": 4},"checkIn": "2025-08-01","checkOut": "2025-08-04","adults": 2,"rooms": 1,"currency": "EUR","platforms": ["booking", "expedia"],"maxHotels": 100}
Input fields
| Field | Type | Default | Description |
|---|---|---|---|
hotelNames | string[] | — | List of hotel names to compare. Use specific names for best matching (e.g. "Marriott Times Square New York"). |
searchByLocation | object | — | Alternative to hotelNames. Finds all hotels in a city, optionally filtered by star rating. |
searchByLocation.city | string | — | City name (e.g. "New York", "London") |
searchByLocation.country | string | — | Country name or ISO 2-letter code (e.g. "US", "FR") |
searchByLocation.stars | number | — | Optional star rating filter (1–5) |
checkIn | string | required | Check-in date in YYYY-MM-DD format |
checkOut | string | required | Check-out date in YYYY-MM-DD format |
adults | integer | 2 | Number of adult guests per room |
rooms | integer | 1 | Number of rooms |
currency | string | "USD" | ISO 4217 currency code for prices |
platforms | string[] | ["booking","hotels","expedia"] | Which OTAs to query. Any subset of the three. |
maxHotels | integer | 50 | Max hotels to process (1–500) |
proxyConfiguration | object | — | Apify proxy settings. Residential proxies strongly recommended. |
requestTimeoutSecs | integer | 60 | Per-page timeout in seconds |
maxConcurrency | integer | 3 | Parallel browser sessions (1–10) |
Output
One dataset item per hotel. Example output for two hotels:
[{"searchedName": "Marriott Times Square","checkIn": "2025-06-15","checkOut": "2025-06-18","nights": 3,"adults": 2,"rooms": 1,"currency": "USD","platforms": {"booking": {"platform": "booking","hotelName": "New York Marriott Marquis","normalizedName": "new york marriott marquis","starRating": 4,"location": "Times Square, New York","latitude": null,"longitude": null,"lowestPricePerNight": 289.00,"averagePricePerNight": 312.50,"rooms": [{"roomType": "Standard Room","pricePerNight": 289.00,"totalPrice": 867.00,"cancellationPolicy": "free_cancel","breakfastIncluded": false}],"cancellationPolicy": "free_cancel","breakfastIncluded": false,"available": true,"reviewScore": 8.4,"reviewCount": 12480,"directUrl": "https://www.booking.com/hotel/us/new-york-marriott-marquis.html","currency": "USD","scrapedAt": "2025-04-02T14:30:00.000Z","error": null},"hotels": {"platform": "hotels","hotelName": "New York Marriott Marquis","normalizedName": "new york marriott marquis","starRating": 4,"location": "Times Square, Manhattan","latitude": null,"longitude": null,"lowestPricePerNight": 299.00,"averagePricePerNight": 299.00,"rooms": [{"roomType": "Standard Room","pricePerNight": 299.00,"totalPrice": 897.00,"cancellationPolicy": "free_cancel","breakfastIncluded": false}],"cancellationPolicy": "free_cancel","breakfastIncluded": false,"available": true,"reviewScore": 8.2,"reviewCount": 10920,"directUrl": "https://www.hotels.com/ho123456/","currency": "USD","scrapedAt": "2025-04-02T14:30:08.000Z","error": null},"expedia": {"platform": "expedia","hotelName": "New York Marriott Marquis","normalizedName": "new york marriott marquis","starRating": 4,"location": "Times Square, New York, NY","latitude": null,"longitude": null,"lowestPricePerNight": 312.00,"averagePricePerNight": 312.00,"rooms": [{"roomType": "Standard Room","pricePerNight": 312.00,"totalPrice": 936.00,"cancellationPolicy": "non_refundable","breakfastIncluded": false}],"cancellationPolicy": "non_refundable","breakfastIncluded": false,"available": true,"reviewScore": 8.3,"reviewCount": 9870,"directUrl": "https://www.expedia.com/h1234567.Hotel-Information","currency": "USD","scrapedAt": "2025-04-02T14:30:18.000Z","error": null}},"bestPrice": 289.00,"bestOTA": "booking","worstPrice": 312.00,"worstOTA": "expedia","priceVariance": 23.00,"priceDifferencePercent": 7.96,"rateParity": false,"rateParityThresholdPercent": 5,"comparedAt": "2025-04-02T14:30:18.000Z","dataQuality": "full"},{"searchedName": "Hilton London Metropole","checkIn": "2025-06-15","checkOut": "2025-06-18","nights": 3,"adults": 2,"rooms": 1,"currency": "USD","platforms": {"booking": {"platform": "booking","hotelName": "Hilton London Metropole","normalizedName": "hilton london metropole","starRating": 4,"location": "Paddington, London","latitude": null,"longitude": null,"lowestPricePerNight": 178.00,"averagePricePerNight": 195.00,"rooms": [{"roomType": "Standard Room","pricePerNight": 178.00,"totalPrice": 534.00,"cancellationPolicy": "free_cancel","breakfastIncluded": false}],"cancellationPolicy": "free_cancel","breakfastIncluded": false,"available": true,"reviewScore": 7.9,"reviewCount": 8440,"directUrl": "https://www.booking.com/hotel/gb/hilton-london-metropole.html","currency": "USD","scrapedAt": "2025-04-02T14:31:00.000Z","error": null},"hotels": {"platform": "hotels","hotelName": "Hilton London Metropole","normalizedName": "hilton london metropole","starRating": 4,"location": "Paddington, London","latitude": null,"longitude": null,"lowestPricePerNight": 180.00,"averagePricePerNight": 180.00,"rooms": [{"roomType": "Standard Room","pricePerNight": 180.00,"totalPrice": 540.00,"cancellationPolicy": "free_cancel","breakfastIncluded": false}],"cancellationPolicy": "free_cancel","breakfastIncluded": false,"available": true,"reviewScore": 7.8,"reviewCount": 7120,"directUrl": "https://www.hotels.com/ho234567/","currency": "USD","scrapedAt": "2025-04-02T14:31:08.000Z","error": null},"expedia": {"platform": "expedia","hotelName": "Hilton London Metropole","normalizedName": "hilton london metropole","starRating": 4,"location": "Paddington, London, UK","latitude": null,"longitude": null,"lowestPricePerNight": 177.00,"averagePricePerNight": 177.00,"rooms": [{"roomType": "Standard Room","pricePerNight": 177.00,"totalPrice": 531.00,"cancellationPolicy": "free_cancel","breakfastIncluded": false}],"cancellationPolicy": "free_cancel","breakfastIncluded": false,"available": true,"reviewScore": 7.9,"reviewCount": 6980,"directUrl": "https://www.expedia.com/h2345678.Hotel-Information","currency": "USD","scrapedAt": "2025-04-02T14:31:18.000Z","error": null}},"bestPrice": 177.00,"bestOTA": "expedia","worstPrice": 180.00,"worstOTA": "hotels","priceVariance": 3.00,"priceDifferencePercent": 1.69,"rateParity": true,"rateParityThresholdPercent": 5,"comparedAt": "2025-04-02T14:31:18.000Z","dataQuality": "full"}]
Output fields reference
Top-level comparison fields
| Field | Type | Description |
|---|---|---|
searchedName | string | The hotel name as provided in the input |
checkIn | string | Check-in date (YYYY-MM-DD) |
checkOut | string | Check-out date (YYYY-MM-DD) |
nights | number | Number of nights |
adults | number | Adults searched for |
rooms | number | Rooms searched for |
currency | string | Currency of all prices |
platforms | object | Per-platform data keyed by booking, hotels, expedia |
bestPrice | number | null | Lowest price per night found across all platforms |
bestOTA | string | null | Platform name with the lowest price |
worstPrice | number | null | Highest price per night found |
worstOTA | string | null | Platform name with the highest price |
priceVariance | number | null | Absolute difference: worstPrice - bestPrice |
priceDifferencePercent | number | null | Relative spread: (worstPrice - bestPrice) / bestPrice * 100 |
rateParity | boolean | null | true if all OTA prices are within 5% of each other; false = violation; null = only one platform returned data |
rateParityThresholdPercent | number | Threshold used for rate parity check (default: 5%) |
comparedAt | string | ISO 8601 timestamp of when comparison was computed |
dataQuality | "full" | "partial" | "failed" | full = all queried platforms returned prices; partial = some failed; failed = none returned data |
Per-platform price fields (inside platforms.booking, platforms.hotels, platforms.expedia)
| Field | Type | Description |
|---|---|---|
platform | string | Platform identifier |
hotelName | string | Hotel name as returned by the OTA |
normalizedName | string | Normalized name used for matching |
starRating | number | null | Hotel star rating (1–5) |
location | string | Address or neighborhood string from the OTA |
latitude | number | null | GPS latitude (when available) |
longitude | number | null | GPS longitude (when available) |
lowestPricePerNight | number | null | Cheapest room option per night |
averagePricePerNight | number | null | Average across available room types |
rooms | RoomOffer[] | Array of room offers (see below) |
cancellationPolicy | "free_cancel" | "non_refundable" | "mixed" | "unknown" | Overall cancellation policy |
breakfastIncluded | boolean | null | Whether any offer includes breakfast |
available | boolean | Whether the hotel had any availability |
reviewScore | number | null | Guest review score (OTA scale, typically 0–10) |
reviewCount | number | null | Total number of guest reviews |
directUrl | string | Deep link to hotel page on the OTA |
currency | string | Currency of prices |
scrapedAt | string | ISO 8601 timestamp when this OTA was queried |
error | string | null | Error message if this OTA failed for this hotel |
Room offer fields (inside rooms[])
| Field | Type | Description |
|---|---|---|
roomType | string | Room category name |
pricePerNight | number | Price per night for this room type |
totalPrice | number | Total price for the full stay |
cancellationPolicy | "free_cancel" | "non_refundable" | "unknown" | Cancellation policy for this specific room |
breakfastIncluded | boolean | Whether breakfast is included |
Rate parity explained
Rate parity is a contractual or strategic requirement that a hotel's room prices remain consistent across all booking channels (OTAs, direct website, etc.).
This actor flags a rate parity violation when any OTA's price differs from the cheapest platform by more than 5% (priceDifferencePercent > 5).
Revenue managers can run this actor daily on a schedule and filter output for rateParity: false to catch violations and renegotiate OTA contracts.
Scheduling for price monitoring
To track a hotel's price over time, schedule the actor using Apify Scheduler:
- Go to Schedules in your Apify Console
- Create a new schedule (e.g. daily at 6:00 AM UTC)
- Attach this actor with your hotel list and target dates
- Connect the dataset to a Google Sheet or webhook for automatic alerting
Each run's output is appended to the dataset, building a historical price record.
Proxy recommendations
Hotel booking sites aggressively block datacenter IPs. For reliable results:
- Use Apify Residential Proxies (
proxyConfiguration: { useApifyProxy: true, apifyProxyGroups: ["RESIDENTIAL"] }) - For high-volume runs (100+ hotels), consider country-specific residential proxies matching the target OTA's locale
- Datacenter proxies may work for testing but will have higher block rates in production
Pricing
$2.00 per 1,000 hotel comparisons (PAY_PER_EVENT billing)
| Run type | Hotels | Platforms | Cost |
|---|---|---|---|
| Quick check | 10 hotels | 3 platforms | $0.02 |
| Daily monitoring | 500 hotels | 3 platforms | $1.00 |
| Weekly agency run | 200 hotels | 3 platforms | $0.40 |
A single comparison = one dataset item (one hotel × all platforms). You are not charged per platform call — only per completed hotel comparison record.
Performance
| Metric | Typical value |
|---|---|
| Time per hotel (3 platforms) | 30–60 seconds |
| Concurrency (default) | 3 parallel browsers |
| 50 hotels, 3 platforms | ~10–15 minutes |
| 500 hotels, 3 platforms | ~90–150 minutes |
Actual performance depends on OTA response times, proxy speed, and whether CAPTCHAs are encountered.
Limitations
- OTAs may change their HTML structure, which can require selector updates. The actor uses multiple fallback selectors per field to reduce breakage.
- Geographic availability: some OTA features (currencies, deal badges) vary by region. Setting
proxyConfigurationto match the target currency's country improves accuracy. - Dynamic pricing: OTA prices can change within seconds. Prices in the dataset reflect the moment each OTA was queried during the run.
- This actor is for market research and price intelligence purposes. Review each OTA's Terms of Service before using in production.