Booking.com Price Tracker — Room-Level Hotel Prices
Pricing
from $5.00 / 1,000 results
Booking.com Price Tracker — Room-Level Hotel Prices
Track Booking.com prices by room type, per night, up to 365 days. Get rooms_left, rate options, meal plans, discounts, and sold-out detection. Clean output for revenue management and competitive analysis. CSV, JSON, HTML, Excel. Built by NoraView Intelligence.
Pricing
from $5.00 / 1,000 results
Rating
5.0
(2)
Developer
NoraView Intelligence
Maintained by CommunityActor stats
9
Bookmarked
196
Total users
44
Monthly active users
4.9 days
Issues response
2 days ago
Last modified
Categories
Share
🏨 Booking.com Room-Level Price Scraper
Extract complete room-level pricing from any Booking.com hotel — every room type, every rate option, every date — up to 365 days ahead.
Unlike listing scrapers that return one price per hotel, this actor dives into each property page and extracts granular room-by-room data: prices, rate options, availability signals, meal plans, discounts, facilities, and sold-out detection.
One run = complete pricing visibility for your competitive set.
💡 Paste hotel URLs, set your date range, hit Start. Results ready in JSON, CSV, or Excel.
🎯 Who is this for?
- Revenue managers monitoring competitor pricing daily
- Hotel operators tracking market positioning at the room-type level
- Travel tech companies feeding structured pricing data into dashboards or algorithms
- Market analysts studying seasonal trends and demand patterns
- Consultants building competitive intelligence reports for hospitality clients
📥 Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
hotelUrls | array | ✅ | — | Booking.com hotel URLs (up to 10 per run) |
daysAhead | integer | ❌ | 30 | Number of days to scrape (1–365) |
startDate | string | ❌ | Today | Start date in YYYY-MM-DD format |
currency | string | ❌ | USD | Any Booking.com currency: USD, EUR, GBP, MAD, AED, JPY… |
adults | integer | ❌ | 2 | Number of adult guests |
children | integer | ❌ | 0 | Number of children |
rooms | integer | ❌ | 1 | Number of rooms |
includeSoldOut | boolean | ❌ | true | Include sold-out dates in results |
includeWholesaleRates | boolean | ❌ | false | Capture partner/wholesale rates (bbasic), tagged separately as is_wholesale |
proxyCountries | array | ❌ | ["FR"] | Source markets to scrape from. The actor runs once per country; each result is tagged with proxy_country. Requires useApifyProxy: true |
delayBetweenRequests | integer | ❌ | 4 | Seconds between page loads (anti-blocking) |
useApifyProxy | boolean | ❌ | false | Use Apify Proxy for better success rates |
Example input
{"hotelUrls": ["https://www.booking.com/hotel/ma/savoy-le-grand.html","https://www.booking.com/hotel/ma/longue-vie-hotels.html"],"daysAhead": 30,"currency": "USD","adults": 2,"rooms": 1,"includeSoldOut": true,"useApifyProxy": true,"proxyCountries": ["FR", "US", "GB"]}
💡 Tip: You only need the base hotel URL — query parameters like ?checkin=... are automatically handled. Works with any Booking.com property worldwide.
💡 Multi-country tip: Booking.com applies geo-pricing based on visitor location. Scraping from multiple proxyCountries (e.g. ["FR", "US", "GB"]) reveals how the same room is priced for different source markets. Keep currency fixed across countries so the difference you see is the geo-pricing cohort, not a currency conversion.
📤 Output
Each result represents one room type for one date. A hotel with 8 room types scraped across 30 days produces ~240 results — a complete pricing matrix.
Output fields
| Field | Type | Description |
|---|---|---|
hotel_url | string | Source URL |
hotel_name | string | Property name as shown on Booking.com |
scrape_timestamp | string | When this data was collected (UTC) |
proxy_country | string | Source market the result was scraped from (e.g. FR, US) |
check_in_date | string | Check-in date (YYYY-MM-DD) |
check_out_date | string | Check-out date (YYYY-MM-DD) |
room_id | integer | Booking.com internal room type ID |
room_name | string | Full room name (e.g., "Prestige Double Room with Pool View") |
room_name_clean | string | Room name with bed type suffix removed |
bed_type | string | Bed configuration (e.g., "1 extra-large double bed") |
max_guests | integer | Maximum occupancy for this room |
room_size_sqm | integer | Room size in m² (null if not shown) |
room_view | string | View type (e.g., "Pool view", "Seating Area") |
has_private_bathroom | boolean | Whether the room has a private bathroom |
facilities | array | Full list of room facilities (30–40+ items per room) |
room_amenities | array | Premium amenities only (balcony, minibar, spa bath, etc.) |
currency | string | Price currency |
price | number | Lowest available price for this room |
price_primary | number | Best price for 2-guest standard occupancy |
price_public | number | Non-Genius public price (for competitive benchmarking) |
original_price | number | Pre-discount price (null if no discount) |
discount_percent | integer | Discount percentage (null if no discount) |
rooms_left | integer | Booking.com availability signal (null = high availability) |
availability_status | string | available, low_availability, low_availability_urgent, or sold_out |
stock_confidence | string | exact, capped, or hidden — see explanation below |
meal_plan | string | Meal plan description |
is_breakfast_included | boolean | Whether breakfast is included at no extra cost |
is_refundable | boolean | Whether free cancellation is offered |
book_now_pay_later | boolean | Whether deferred payment is available |
taxes_included | number | Taxes included in the displayed price |
taxes_excluded | number | Taxes added on top of the displayed price |
has_wholesale_rate | boolean | Whether any rate option for this room is a wholesale/partner rate (only relevant when includeWholesaleRates: true) |
rate_options | array | All pricing tiers for this room (see below) |
rate_options_count | integer | Number of rate options available |
Rate options structure
Each entry in rate_options contains:
| Field | Type | Description |
|---|---|---|
price | number | Price for this specific rate |
public_price | number | Non-Genius price (original price if Genius discount applied) |
max_guests | integer | Guest count this rate is designed for |
is_refundable | boolean | Free cancellation available |
is_genius | boolean | Whether this is a Genius-discounted rate |
is_wholesale | boolean | Whether this is a partner/wholesale (bbasic) rate. Always false unless includeWholesaleRates: true |
original_price | number | Pre-discount price (null if none) |
free_cancellation_until | string | Last date for free cancellation (YYYY-MM-DD) |
taxes_and_fees | number | Taxes shown in DOM |
meal_plan | string | Meal plan for this rate |
block_id | string | Booking.com internal block ID |
taxes_included | number | Taxes from Booking's JSON data (included in price) |
taxes_excluded | number | Taxes from Booking's JSON data (excluded from price) |
stay_prices | object | Price per number of nights (LOS pricing data) |
book_now_pay_later | boolean | Deferred payment available |
💡 Note: Rate options only include rates that match your search parameters (e.g., searching for 2 adults filters out 1-person-only rates). Partner/wholesale rates (bbasic) are excluded by default — enable includeWholesaleRates to capture them, tagged separately as is_wholesale so they never mix with retail rates.
Example output
{"hotel_url": "https://www.booking.com/hotel/ma/savoy-le-grand.html","hotel_name": "Savoy Le Grand Hotel Marrakech","scrape_timestamp": "2026-03-17T22:20:20Z","proxy_country": "FR","check_in_date": "2026-03-17","check_out_date": "2026-03-18","room_id": 160633804,"room_name": "Prestige Double Room with Pool View","room_name_clean": "Prestige Double Room with Pool View","bed_type": "1 extra-large double bed","max_guests": 1,"room_size_sqm": 43,"room_view": "Pool view","has_private_bathroom": true,"facilities": ["Room", "463 feet²", "Balcony", "Pool view", "Air conditioning","Ensuite bathroom", "Flat-screen TV", "Soundproofing", "Terrace","Coffee machine", "Minibar", "Free WiFi", "..."],"room_amenities": ["balcony", "air conditioning", "soundproofing", "terrace", "minibar"],"currency": "USD","price": 186,"price_primary": 186,"price_public": 186,"original_price": 207,"discount_percent": 10,"rooms_left": null,"availability_status": "available","stock_confidence": "hidden","meal_plan": "breakfast","is_breakfast_included": true,"is_refundable": false,"book_now_pay_later": true,"taxes_included": null,"taxes_excluded": null,"has_wholesale_rate": false,"rate_options": [{"price": 186,"public_price": 186,"max_guests": 1,"is_refundable": false,"is_genius": false,"is_wholesale": false,"original_price": 207,"meal_plan": "breakfast","block_id": "160633804_419828305_1_1_0","taxes_excluded": null,"book_now_pay_later": true}],"rate_options_count": 1}
🔍 Understanding key fields
price vs. price_primary vs. price_public
| Field | What it is | When to use |
|---|---|---|
price | Absolute cheapest option (may be 1-person or restricted) | Quick market scan |
price_primary | Best price for standard 2-guest occupancy | Revenue management benchmarking |
price_public | Non-Genius public rate (strips Genius discounts) | Competitor comparison — most travelers don't have Genius |
💡 For competitive analysis, use price_public. Genius discounts (10–20%) make prices look artificially low. price_public gives you the rate that most travelers actually see.
proxy_country
Booking.com prices the same room differently depending on the visitor's location (geo-pricing). The proxy_country field tells you which source market each result was scraped from. Running multiple proxyCountries in one job lets you compare cohorts side by side — e.g. how a French visitor, a US visitor, and a UK visitor each see the same property.
💡 For clean cohort comparison, keep currency fixed across all countries. Otherwise you mix two variables: the geo-pricing cohort and the currency conversion.
availability_status
| Status | Meaning | Revenue insight |
|---|---|---|
available | Rooms widely available | Normal market conditions |
low_availability | Inventory signal from internal data | Demand is building |
low_availability_urgent | Booking.com shows a visible scarcity alert | High demand — act on pricing |
sold_out | No rooms available for this date | Peak demand — opportunity to optimize your rates |
stock_confidence
| Value | Source | Reliability |
|---|---|---|
exact | DOM scarcity badge visible on page | High — Booking.com shows this to create urgency |
capped | rooms_left = 10 from internal JSON | Medium — actual stock is ≥ 10 |
hidden | rooms_left = null — no signal from either source | Low — Booking.com not revealing stock level |
rooms_left
Booking.com reveals availability through two channels, both captured by this scraper:
| Source | How it works |
|---|---|
Internal JSON (b_nr_stays) | Booking's internal stock data embedded in page scripts. Always captured when available. |
| DOM scarcity badges | Visible alerts like "Only 3 left!" shown to shoppers. Triggers stock_confidence: "exact". |
| Value | Meaning |
|---|---|
1–9 | Real scarcity signal |
10 | Booking.com display cap — actual inventory is ≥ 10 |
null | No signal from either source — high availability |
facilities vs. room_amenities
| Field | What it contains | Example |
|---|---|---|
facilities | Complete list — every feature Booking.com shows for the room (30–40+ items) | "463 feet²", "Pool view", "Air conditioning", "Toilet paper", ... |
room_amenities | Premium features only — the differentiators that affect pricing | "balcony", "minibar", "soundproofing", "spa bath" |
Use facilities for full room comparison. Use room_amenities for quick tier classification.
💡 Tips for best results
- Start with 7–30 days to validate your setup, then scale to 365
- Schedule daily runs with Apify Scheduler — hotel prices change constantly
- Use Apify Proxy (
useApifyProxy: true) for better success rates on large runs - Monitor up to 10 hotels per run for optimal speed and reliability
- Track sold-out patterns over time to map demand cycles in your market
- Compare
rate_optionsto analyze refundable vs. non-refundable pricing strategies - Use
price_public(notprice) when comparing against your own rates — strips Genius discounts - Use
facilitiesto match comparable room types across different hotels - Compare
proxyCountriesto see geo-pricing differences across your source markets — keepcurrencyfixed for a clean comparison
🔗 Integrations
| Integration | Use case |
|---|---|
| Apify Scheduler | Automate daily/weekly price monitoring |
| Webhooks | Get notified when a run completes |
| API | Pull data programmatically (see API tab) |
| Google Sheets | Direct export for quick analysis |
| n8n / Make / Zapier | No-code automation pipelines |
| JSON / CSV / Excel | Download in any format |
🚀 Use cases
Daily competitor monitoring — Track what your competitive set charges across every room type, every day. See exactly how competitors price their rooms, when they discount, and when they sell out.
Revenue management — Feed room-level market data into pricing decisions. Compare your rates against competitors using matching rate options (same occupancy, same cancellation policy, same meal plan). Use price_public for fair Genius-free comparison.
Geo-pricing analysis — Scrape the same properties from multiple proxyCountries to see how Booking.com prices rooms for visitors from different source markets — useful when your guests come predominantly from specific countries.
Room-type matching — Use facilities, room_size_sqm, and room_view to match comparable rooms across different hotels. A 43m² Prestige room with pool view at Hotel A maps to a similar tier at Hotel B.
Seasonal trend analysis — Scrape 365 days to visualize demand curves, identify shoulder seasons, and plan promotions around events and holidays.
Portfolio benchmarking — Manage multiple properties? Compare each one against its local market at the room-type level.
Travel platform data feeds — Power booking engines, metasearch tools, or dashboards with structured, validated pricing data.
❓ FAQ
Does this work with any Booking.com property? Yes — any hotel, resort, riad, apartment, or boutique property listed on Booking.com, in any country. Works with small riads (5 rooms) and large hotels (100+ rooms).
What currencies are supported? All currencies available on Booking.com: USD, EUR, GBP, MAD, AED, SAR, JPY, and 30+ more.
What does rooms_left: null mean?
Booking.com is not displaying a scarcity alert for this room — it has comfortable availability. When inventory drops, Booking.com shows alerts like "Only 3 left!" and rooms_left captures that exact count.
What does rooms_left: 10 mean?
This is Booking.com's display cap. The actual inventory is 10 or more — Booking.com doesn't show exact counts above this threshold.
Why are sold-out dates valuable? Sold-out dates reveal peak demand periods. If a competitor is fully booked, that's a high-demand window where you can optimize your own rates.
What's the difference between price, price_primary, and price_public?
price is the absolute cheapest rate. price_primary is the best rate matching standard 2-guest occupancy. price_public strips Genius discounts to show the rate most travelers actually see — use this for competitive benchmarking.
What are Genius rates and why does price_public matter?
Booking.com Genius gives 10–20% discounts to frequent bookers. price_public always shows the non-Genius price, giving you the rate that the majority of travelers see. This is critical for fair competitor comparison.
What are bbasic rates and can I include them?
Booking.com sometimes shows "Tarif Prestataire" (partner/wholesale rates) from third-party resellers. By default the scraper skips them, since they aren't representative of the hotel's own retail pricing. If you need them — common in some Asian markets — set includeWholesaleRates: true and they'll be captured and tagged with is_wholesale: true, kept separate from retail rates so the two never mix.
How does proxyCountries work?
The actor runs once per country in the list, routing through a residential proxy for that market, and tags every result with proxy_country. This reveals Booking.com's geo-pricing — how the same room is priced for visitors from different countries. Requires useApifyProxy: true. Keep currency fixed across countries for a clean comparison.
How does the scraper handle large hotels with many room types? Hotels with 9+ room types use a different DOM structure. The scraper handles this automatically by grouping rate rows by room ID and matching them to room type cells.
How often should I run this? For active revenue management, daily runs are recommended. Prices and availability on Booking.com change frequently — sometimes multiple times per day.
Can I scrape more than 10 hotels? For optimal reliability, each run handles up to 10 hotels. For larger sets, schedule multiple runs or use the Apify API to batch them.
📝 Changelog
v2.2.0 — June 2026
- ✅ Multi-country proxy —
proxyCountriesfield scrapes from multiple source markets in one run; each result tagged withproxy_countryfor geo-pricing comparison - ✅ Wholesale rates —
includeWholesaleRatesflag captures partner/bbasicrates, tagged separately asis_wholesale(andhas_wholesale_rateat the room level), kept separate from retail - ✅ Resilient registry load — room-registry navigation now retries with IP rotation, so a single dead proxy IP no longer blocks sold-out detection for the whole hotel
v2.1.1 — March 2026
- ✅ Fixed multi-room extraction — removed name-based deduplication that caused rooms to be silently skipped;
roomIdis now the single source of truth for deduplication - ✅ Robust fallback names — rooms with missing DOM names now use
Room_{id}instead of colliding on"Unknown Room" - ✅ Cleaner bbasic handling — partner rate rows correctly skipped at both cell and row level across all hotel sizes
- ✅
stay_prices(LOS data) — length-of-stay pricing matrix extracted from Booking's internal JSON (b_stay_prices) - ✅
taxes_included/taxes_excluded— tax breakdown extracted fromb_included_charges/b_excluded_charges - ✅
book_now_pay_later— deferred payment flag extracted fromb_book_now_pay_later - ✅
stock_confidence— distinguishesexact(DOM badge),capped(JSON ≥ 10), andhidden(no signal)
v2.1.0 — March 2026
- ✅ Cell-based extraction — handles hotels with 9+ room types in a single table
- ✅ Full facilities list — 30–40+ items per room (size, view, bathroom, amenities)
- ✅
price_public— non-Genius public rate for fair competitor comparison - ✅
room_size_sqm— extracted from real room cell (not partner rate cell) - ✅
room_view— extracted from facilities and room name - ✅
has_private_bathroom— boolean from room facilities - ✅
room_amenities— premium features for tier classification - ✅ Genius detection —
is_geniusflag per rate option withpublic_priceextraction
v2.0.3 — March 2026
- ✅ Clean output schema — reduced from 35+ fields to 22 focused fields
- ✅ Accurate
max_guests— uses Booking.com'sdata-fltrsattribute - ✅
fitfiltering — rate options only include rates matching your search parameters - ✅ Fixed
rooms_leftextraction — expanded JSON parsing window - ✅ Fixed
is_breakfast_included— correctly detects all Booking.com breakfast formats - ✅
price_primary— new field for revenue management benchmarking
v2.0.0 — February 2026
- ✨ Room-by-room extraction with multiple rate options per room
- ✨
rooms_left+availability_statusavailability tracking - ✨ Discount detection with original price and percentage
- ✨ Meal plan and cancellation policy extraction
- ✨ Sold-out detection across date ranges
v1.0.0 — February 2026
- Initial release
💬 Support & feature requests
Have a question, found a bug, or want a new feature? → Open an issue on the Issues tab.
Want a custom solution for your revenue management needs? → Reach out via Issues.
Built by NoraView Intelligence — AI-powered revenue management for independent hotels.
Track Booking.com prices by room type, per night, up to 365 days ahead. Get rooms_left, rate options, meal plans, discounts, refundable pricing, sold-out detection, full facilities, room size, view, Genius rate detection, wholesale/partner rates, and multi-country geo-pricing. Clean structured output for revenue management and competitive analysis. CSV, JSON, HTML, Excel.