Booking.com Room Rates Scraper
Pricing
from $2.10 / 1,000 hotel-priceds
Booking.com Room Rates Scraper
Scrape every room Booking.com is selling for a hotel and your dates. Just add hotel links and get room name, size, beds, board, price for the stay, price per night, cancellation terms and payment policy. Export to CSV, JSON or Excel, or schedule it.
Pricing
from $2.10 / 1,000 hotel-priceds
Rating
0.0
(0)
Developer
BonCross API
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
9 days ago
Last modified
Categories
Share
What is Booking.com Room Rates Scraper?
A Booking.com hotel page leads with one "from" price. Booking.com Room Rates Scraper gets you everything behind it: each room the hotel is selling for your dates and each rate plan on that room, one row per bookable rate, with the board, the cancellation terms, the payment policy and what tax is or isn't in the price. Paste hotel links, set the dates, and that's the run.
What you get that a headline price can't tell you:
- The full grid. On the properties we measured that was 8 to 34 rates per hotel-stay, and The Savoy returned 61 for the night in the example further down.
- A price you can add up. Each rate says whether tax is included, with the amount inside the price and the amount payable on top.
- Like-for-like comparisons. Booking sells some rooms to fewer guests for less, and those rates are marked. 21 of The Savoy's 61 rows were that kind. Unmarked, they'd look like cheaper rooms.
- An answer for each hotel you asked about. A sold-out stay is one row saying sold out. A stay your filters emptied is one row saying how many rates there were. A hotel that couldn't be reached is one free error row.
- A price per hotel-stay, not per row: $3.50 per 1,000 priced hotel-stays on the Free plan and $2.60 on Business, however many rates the hotel has.
BonCross Verified means we tested this actor against the live site before release and kept the record:
- 28 of 28 live checks on its inputs and filters passed on 8 October 2026
- 9 hotels run on 7 October 2026 on one weekend: 103 rates, 2 sold-out answers
- A stay your filters empty gets one row saying how many rates were found
People use it for rate-parity checks against their own channel, competitor rate shopping across a set of hotels and dates, watching how a rival's rate plans and cancellation terms move, and feeding travel products that need bookable room-level prices.
What data is on each rate row?
| Field | Notes | |
|---|---|---|
| 🏨 | id, hotelId, hotelName, url, input | the rate, the property, a link back to it and the hotel as you supplied it |
| 📅 | checkIn, checkOut, nights | the stay the rate was priced for |
| 🛏 | roomId, roomName, roomDescription, roomSizeSqm | as the site lists them |
bathroomCount, isSmoking | where the site gives them | |
bedConfiguration, maxOccupancy, maxAdults | beds and how many the room sleeps | |
| 🍳 | board, mealPlan, isBreakfastIncluded | room only, breakfast, half board and so on; mealPlan is the site's code |
| 💷 | priceTotal, pricePerNight, currency | the stay total and the nightly equivalent |
priceBeforeDiscount, priceTotalText | the struck-through price, where there is one | |
isRefundable, cancellation, cancellationDetail | free cancellation and its deadline | |
| 💳 | isPrepaymentRequired, prepayment | pay ahead or pay at the property |
| 👥 | isAlternativeOccupancy, occupancyIndex | marks a rate sold to fewer guests; the index is a variant number, not a guest count |
blockId | the site's own identifier for the rate | |
| 📷 | photos | room photos |
| 🧾 | pricesIncludeTax | true where the price includes every tax and charge Booking puts a figure on, false where some are payable on top |
taxesAndChargesIncluded, taxesAndChargesExcluded | the taxes and charges inside the price and on top of it, for the stay, in the row's currency | |
chargesNote | the site's note about charges not in the price | |
scrapedAt | when the row was collected |
How to scrape Booking.com room rates
- Create a free Apify account and open Booking.com Room Rates Scraper.
- Add your hotels: paste Booking.com hotel links, their slugs, or hotel IDs. If you have many, use Start URLs with a file or a Google Sheet.
- Set your check-in and check-out dates and the adults and children in the room. Prices are for one room.
- Filter to refundable rates or rates with breakfast if you want to, and cap the rows per hotel or for the whole run.
- Click Start, then download the rates as CSV, Excel or JSON.
A link is looked up as that exact hotel page. If Booking has no such page you get an error row, never another hotel's rates.
⬇️ Input
Hotels and two dates are all it needs.
There are three caps, and they count different things. "Max rows per hotel" keeps the cheapest that many rates for each hotel-stay. "Max hotel-stays" stops the run after that many stays (a stay is one hotel for your dates, with all its rates). "Max rows in total" stops after that many rows, and the last stay is cut to fit, keeping its cheapest rates. All three default to 0, which means no limit.
| Input | Type | Notes |
|---|---|---|
hotels | array | Hotel links, country/slug (us/bellagio), slugs or IDs |
startUrls | array | The same hotels as links, a file, or a Google Sheet |
checkIn, checkOut | string | YYYY-MM-DD. Check-out must be after check-in |
adults, childrenAges | number, array | Who the room is for. Booking lists the same rooms and prices for any party, so these decide which rooms are big enough. Prices are for one room |
hideRoomsTooSmall | boolean | Leave out rooms that cannot sleep your party. On by default |
maxRowsPerHotel | number | Keep the cheapest this many rates per hotel-stay. 0 keeps every one |
maxItems | number | Stop after this many hotel-stays (one hotel for your dates, all its rates). 0 (default) means no limit |
maxRows | number | Stop after this many rows; the last stay is cut to fit, keeping its cheapest rates. 0 (default) means no limit |
onlyRefundable | boolean | Keep only rates with free cancellation |
onlyBreakfastIncluded | boolean | Keep only rates whose board includes breakfast |
includeAlternativeOccupancy | boolean | Keep reduced-occupancy rates. On by default, and marked |
sessions | number | Passes per hotel, 1 to 5 (default 2). See the FAQ |
currency, language | string | Currency code (default USD) and Booking language code (default en-gb) |
maxConcurrency, delayMs | number | Parallel requests, 1 to 32 (default 32), and an optional pause before each call in ms (default 0). Neither changes the rows |
One hotel, one night, two adults and a child, in pounds
{"hotels": ["https://www.booking.com/hotel/gb/the-savoy.html"],"checkIn": "2026-11-02","checkOut": "2026-11-03","adults": 2,"childrenAges": ["5"],"currency": "GBP","onlyRefundable": false,"maxItems": 0}
Refundable breakfast rates for several hotels, the five cheapest each, capped at 200 rows
{"hotels": ["us/bellagio", "https://www.booking.com/hotel/sg/marina-bay-sands.html"],"checkIn": "2026-11-02","checkOut": "2026-11-04","onlyRefundable": true,"onlyBreakfastIncluded": true,"maxRowsPerHotel": 5,"maxRows": 200}
When we ran that second example on 7 October 2026, Marina Bay Sands returned its five cheapest refundable breakfast rates and Bellagio returned one row saying 26 rates were found and none passed the filters. That row is shown in the Output section.
For developers
maxItemscounts hotel-stays andmaxRowscounts rows. The run stops at whichever is reached first. A sold-out row or a "none passed the filters" row counts as one stay and one row.sessionsis the number of passes per hotel. Booking shows reduced-occupancy rates to some visitors and not others: 1 pass may miss them, 2 catches them about 9 times in 10, and 3 about 97 times in 100. Each pass is one extra request.childrenAgestakes one entry per child, their age at check-in (0 to 17). Children count towards the room's capacity.maxConcurrency(default 32, 1 to 32) is how many requests run at once. Several hotels are priced together. Lower it to 1 and hotels are priced one at a time. Row order doesn't change.delayMs(default 0) adds a wait before each call, capped at 2000 ms.- If several inputs name the same hotel and three of its stays fail in a row, its remaining stays aren't asked for and each gets a free error row saying so.
- A run that the platform moves or restarts part-way picks up where it stopped. Hotels already in the dataset aren't priced, delivered or billed twice. We tested it by restarting a 500-hotel run part-way, and no row appeared twice.
⬆️ Output
One row per rate, cheapest first within each hotel-stay. This is the cheapest rate from the first example above, run on 7 October 2026 (one of the room's photos is kept here).
{"id": "280149-2026-11-02-2026-11-03-28014903_88652304_2_2_0","hotelId": 280149,"hotelName": "The Savoy","checkIn": "2026-11-02","checkOut": "2026-11-03","nights": 1,"blockId": "28014903_88652304_2_2_0","roomId": 28014903,"roomName": "Deluxe Room with 2 Twin Beds","roomDescription": "Savoy Deluxe Rooms offer more space and are decorated in either Edwardian\nor Art Deco style, overlooking the courtyard or the city. Famous for their giant showerheads, the well-appointed marble bathrooms are finished with large chrome fittings and Miller Harris amenities. Many bathrooms have separate\nwalk-in showers.","roomSizeSqm": 35,"bedConfiguration": "1 x single bed","maxOccupancy": 3,"maxAdults": 3,"isSmoking": false,"bathroomCount": null,"mealPlan": "BREAKFAST_EXCLUDED","board": "Room only","isBreakfastIncluded": false,"occupancyIndex": 2,"currency": "GBP","priceTotal": 807.5,"priceTotalText": "£807.50","pricePerNight": 807.5,"priceBeforeDiscount": null,"chargesNote": null,"pricesIncludeTax": false,"taxesAndChargesIncluded": 0,"taxesAndChargesExcluded": 161.5,"isRefundable": false,"cancellation": "Non-refundable","cancellationDetail": "Please note, if cancelled, modified or in case of no-show, the total price of the reservation will be charged.","isPrepaymentRequired": true,"prepayment": "Pay the property before arrival","photos": ["https://cf.bstatic.com/xdata/images/hotel/max1024x768/920380812.jpg?k=86f9425b053c7a71fce9ecef34311fa02a4bf93368d5f319a1794323ea7a847a&o="],"url": "https://www.booking.com/hotel/gb/the-savoy.html","scrapedAt": "2026-10-07T20:35:50.725Z","isAlternativeOccupancy": false,"input": "https://www.booking.com/hotel/gb/the-savoy.html"}
id joins the hotel, the stay and Booking's own blockId, which makes a rate row unique across a run and joinable. input echoes the hotel exactly as you supplied it. priceBeforeDiscount is filled only where the rate is discounted, and is null otherwise.
Reading the price
Prices are quoted as Booking.com shows them to a visitor in the United States, on every row and every run. Repeated checks of the same hotel are always on the same basis. On that basis some rates have every tax inside the price and others quote the price before taxes and list them separately, and each row tells you which. pricesIncludeTax is false where a tax or charge with a figure is payable on top, and taxesAndChargesExcluded is that figure. priceTotal + taxesAndChargesExcluded is then the full price: £807.50 + £161.50 = £969 for the room above. Prices are reported exactly as Booking returned them and are never converted from one basis to the other. A charge Booking can't put a figure on, such as a city tax that "may apply", doesn't count against pricesIncludeTax, and chargesNote mentions it.
Rows that aren't rates
A hotel-stay whose rates your filters all remove returns one row saying so, with rateCount: 0, ratesFound (how many rates the site had) and the reason in error:
{"id": "186104-2026-11-02-2026-11-04-nomatch","hotelId": 186104,"hotelName": "Bellagio","input": "us/bellagio","checkIn": "2026-11-02","checkOut": "2026-11-04","nights": 2,"isSoldOut": false,"rateCount": 0,"ratesFound": 26,"url": "https://www.booking.com/hotel/us/bellagio.html","error": "26 rate(s) found, none passed the filters set on this run","scrapedAt": "2026-10-07T20:36:02.311Z"}
A sold-out stay returns one row marked isSoldOut: true. A hotel that couldn't be reached returns an error row, which is never charged.
How many rates per hotel, and how fast?
You get every rate the site is selling for the stay. On the properties measured that is 8 to 34 rows per hotel-stay, depending on how many room types the hotel has and how many boards and rate plans it sells each under. A large hotel can go well past that, as The Savoy's 61 shows.
| Run | Rows | Time |
|---|---|---|
| One hotel, one night, 8 cheapest rates | 8 | 2 to 6 s |
| 14 hotels, two nights | 111 | 5 to 11 s |
| 500 hotels, two nights | about 8,300 | 42 to 50 s |
Whole runs on Apify, start-up included, measured on 2 October 2026. Booking.com's answer time varies through the day, which is the spread. A hotel-stay is a single lookup with no pages to work through, and a longer list adds little time: the 500-hotel run worked out at about 600 hotel-stays a minute, which fits several thousand hotels into the default one-hour run limit.
How much does it cost?
| Event | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
actor-start, per run | $0.001 | $0.001 | $0.001 | $0.001 |
hotel-resolved, per hotel link, slug or id resolved to a property | $0.0005 | $0.0005 | $0.0005 | $0.0005 |
hotel-checked, per hotel-stay the site answered, whether or not it had rooms | $0.0005 | $0.0005 | $0.0005 | $0.0005 |
hotel-priced, per hotel-stay whose rates came back and rows were written | $0.003 | $0.0027 | $0.0024 | $0.0021 |
Enterprise plans pay the Business price.
$3.50 per 1,000 priced hotel-stays on the Free plan, $2.60 on Business, plus $0.0005 per hotel to look it up. You pay the same for a hotel with 8 rates as for one with 61. Proxy usage and platform usage are included.
- Ten hotels for one stay: $0.001 + 10 × $0.0005 + 10 × ($0.0005 + $0.003) = $0.041 ($0.032 on Business).
- A daily monitor of 20 hotels for a month: 30 × ($0.001 + 20 × $0.0005 + 20 × $0.0035) = $2.43 for the month ($1.89 on Business).
What you don't pay the per-stay rate for:
- A sold-out stay, or one whose rates your filters all remove, pays the small
hotel-checkedfee only. - A hotel-stay the site never answered is charged nothing.
- Error rows are never charged.
Apify's Free plan gives you $5 of credits a month, which is about 120 runs of ten hotels each: roughly 1,200 priced hotel-stays with all their rates.
Limitations
- Room rates are per hotel-stay. To compare dates, run the same hotel across several date pairs.
- Reduced-occupancy rates are shown to some visitors and not others. The actor takes more than one pass to catch them (see the FAQ).
occupancyIndexis an opaque variant index, not a number of guests, and it's named that way to stop the column being misread. UseisAlternativeOccupancyto tell a reduced-occupancy rate from the full-occupancy one, andmaxOccupancyfor how many the room sleeps.- There's no guest count per rate. Booking doesn't publish one on this data. A reduced-occupancy rate is identified as such but not labelled with how many guests it covers.
- The party doesn't change Booking's prices here. 2 adults, 4 adults and 2 adults with 2 children returned the same rooms at the same prices. Your party is used to leave out rooms too small for it.
- Prices are for one room. Booking's room list is priced per room and the number of rooms is chosen on the page, which is why there's no rooms input.
- You get prices in the currency and language you ask for. A hotel's own currency may differ.
FAQ
Why do some runs return a few more rows than others?
Booking shows reduced-occupancy rates, the same room sold to fewer guests for less, to some visitors and not to others. The actor makes more than one pass to catch them either way. One pass is the fastest and the most likely to miss them. More passes raise the odds, but on some runs the site shows none of them to any pass, and a re-run can return a few more rows.
What does isAlternativeOccupancy mean?
It marks a rate that covers fewer guests than the room's full occupancy, which is why it's cheaper than an otherwise identical rate. Those rows are kept and marked. Nothing is lost, and you can't accidentally pair a one-breakfast rate with a two-breakfast one in a like-for-like comparison. If you only want the full-occupancy rate for each room and board, turn off "Include reduced-occupancy rates".
A hotel came back as one row with an error about filters. What happened?
The hotel had rates, and none survived the filters you set. ratesFound tells you how many there were. The usual causes are "Only refundable rates" with "Only rates including breakfast" on a hotel that sells no such combination, or a party too big for any room while "Hide rooms too small for your party" is on. Loosen one and run it again.
Why is a hotel returning one row saying sold out?
The site had nothing available for those dates. That's an answer a rate monitor wants, so you get it as a row.
Does the number of adults change the price?
Not here. Booking lists the same rooms at the same prices whatever the party, and the adults and children you enter decide which rooms are big enough to keep.
Can I search a city instead of listing hotels?
Run Booking.com Hotel Search Scraper for the destination and dates, then feed the hotels it returns into this actor.
Do I need proxies or a Booking.com account?
No to both. Rates are read as a logged-out visitor sees them, with no login of yours involved, and the proxy usage is part of the price you already pay.
Is it legal to scrape Booking.com prices?
Room prices are public: anyone can see them without signing in, and that's all this actor reads. Collecting public data like this is generally lawful in the UK, EU and US. How you use the prices, and whether that fits Booking.com's terms, is for you to check.
Running it as a rate monitor
A daily rate check is the usual setup. Create an Apify Schedule with your hotel list and dates, and each run writes a fresh grid you can diff against the last. A webhook can fire when a run finishes, and the rows can go on to Google Sheets, Airtable or Slack through Apify's integrations.
From code, start a run and wait for the dataset in one call:
POST https://api.apify.com/v2/acts/boncross~booking-room-rates/run-sync-get-dataset-items
Through the Apify MCP server at mcp.apify.com, an AI agent can call booking-room-rates with a hotel and dates and get the rate rows back.
More from BonCross
- Booking.com Hotel Details Scraper: The full Booking.com record for a property.
- Booking.com Hotel Search Scraper: Every hotel Booking.com is selling for a destination and your dates.
- Booking.com Reviews Scraper: Every Booking.com guest review for any hotel.
- Expedia Hotel Details Scraper: The full property record from Expedia and Hotels.com.
- Expedia Hotel Search Scraper: Every hotel Expedia and Hotels.com list for a destination and your dates.
- Expedia Room Rates Scraper: Every room Expedia and Hotels.com are selling for a hotel and your dates.
Your feedback
Seen a rate on Booking.com that isn't in your rows, or a price that doesn't add up? Open an issue on the Issues tab with the hotel and dates. We check it against the site and reply there.