Booking.com Hotels, Prices and Reviews Scraper avatar

Booking.com Hotels, Prices and Reviews Scraper

Pricing

from $1.20 / 1,000 properties

Go to Apify Store
Booking.com Hotels, Prices and Reviews Scraper

Booking.com Hotels, Prices and Reviews Scraper

Scrape booking.com hotels, apartments, villas and hostels. Search any destination with the site's own filters (type, stars, review score, budget, meals, cancellation, amenities) or paste links. Live prices in 36 currencies, room-level rates, facilities, house rules and guest reviews.

Pricing

from $1.20 / 1,000 properties

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

5 days ago

Last modified

Categories

Share

Scrape accommodation from booking.com at scale: hotels, apartments, villas, hostels, guesthouses, B&Bs, campgrounds and everything else the site lists. Name a destination and a stay, or paste links you already built in your own browser, and get back one structured row per property with a live price, the rating, the exact location, the matched room configuration and, optionally, the whole property page and its guest reviews.

Built for people who need the numbers to be right: prices in the currency you asked for, a review score next to the number of reviews behind it, and an honest statement in the log when a destination is bigger than the site will serve.


What you get

Every row, always

IdentitypropertyId, propertyName, propertyUrl, pageName, accommodationTypeId, hostType
RatingstarRating, reviewScore, reviewScoreLabel, reviewCount, secondaryReviewScore, externalReviewScore, externalReviewCount
Locationaddress, city, countryCode, latitude, longitude, displayLocation, distanceFromSearchCentre, distanceMetres, isCentrallyLocated, publicTransportDistance, beachDistance
Priceprice.perStay, price.perNight, price.perStayFormatted, price.beforeDiscount, price.currency, price.chargesInfo, price.badges, plus the property's own currency alongside
Roomsrooms[] with roomId, price, mealPlan, occupancy, freeCancellationUntil, urgencyMessage; matchedUnit with bedrooms, bathrooms, beds, kitchens and floor area
ConditionsfreeCancellation, noPrepayment, petsAllowedFreeOfCharge, mealPlanIncluded, isAvailableForDates, isSoldOut, isSustainable, isPreferredPartner, hasGeniusRate
StaycheckIn, checkOut, nights, adults, children, roomsRequested
PhotosmainPhoto, thumbnailPhoto

With fetchDetails on, each row also carries the property's own page

facilityGroups (every listed facility, grouped), topFacilities, houseRules (check-in and check-out times, minimum check-in age, group limit, smoking, parties, city regulations, accepted credit cards, cash), childrenAndBeds (with the per-age-band price rules), petsPolicy, damagePolicy, finePrint, photos (up to 40), roomTypes (the full room catalogue with amenities), questionsAndAnswers, languagesSpoken, brands, chainIds, propertyType, propertyCurrency, reviewCategoryScores and totalReviewCount.

With maxReviewsPerProperty above 0, each row also carries reviews[]

Score, title, what the guest liked, what they did not, language, the date, the room they stayed in, how many nights, the traveller type, the property's own reply, and the reviewer's public display name and country. No contact details are collected: the review surface exposes none and this actor invents none.


Two ways to run it

Search mode

Name one or more destinations exactly as you would type them into the site's search box, set the stay, and narrow with the site's own filters.

{
"mode": "search",
"destinations": ["Sydney", "Lisbon"],
"checkIn": "2026-11-02",
"checkOut": "2026-11-04",
"adults": 2,
"rooms": 1,
"currency": "USD",
"starRatings": ["4", "5"],
"minReviewScore": "8",
"maxPricePerNight": 350,
"reservationPolicies": ["free_cancellation"],
"amenities": ["swimming_pool", "free_wifi"],
"sortBy": "rating_high_to_low",
"maxItems": 50
}

Filters available: property type, star rating, minimum guest review score, budget per night, meals, reservation policy, property amenities, room amenities, bed preference and travel group. Those are sent to the site as its own filter tokens, so they narrow the search itself.

Three more are applied by this actor after the search, because the site has no working filter for them:

  • minReviewCount drops a 10 out of 10 that came from two guests.
  • availableOnly drops properties that are not bookable for your dates. The site pads a thin result set with these, and it does publish an availability filter, but it ignores it: sending that filter returns exactly the same result set as sending nothing. So this actor identifies the padded rows itself and reports the answer in the isAvailableForDates column, which is the same column the filter reads. Searching a small town for a large group is where this bites: one live check returned 25 cards of which only 2 were bookable.
  • excludeSoldOut drops properties the site has explicitly flagged sold out. That is a narrower question than the one above, so it stays a separate option.

URL mode

Paste links. A search link is walked with the destination, dates, guests and filter string that link already carries, so what you get is exactly what you saw. A property link returns that one property with its full detail.

{
"mode": "url",
"urls": [
"https://www.booking.com/searchresults.html?ss=Lisbon&checkin=2026-11-02&checkout=2026-11-04&nflt=class%3D5",
"https://www.booking.com/hotel/au/hilton-sydney.html"
],
"fetchDetails": true,
"maxReviewsPerProperty": 50
}

Sample output

Illustrative shape, trimmed. Values are placeholders, not a real listing.

{
"propertyId": "0000000",
"propertyName": "Example Harbour Hotel",
"propertyUrl": "https://www.booking.com/hotel/au/example-harbour-hotel.html",
"starRating": 4,
"reviewScore": 8.6,
"reviewScoreLabel": "Excellent",
"reviewCount": 2793,
"address": "1 Example Street",
"city": "Sydney",
"countryCode": "au",
"latitude": -33.8712,
"longitude": 151.207,
"price": {
"currency": "USD",
"perStay": 412.5,
"perNight": 206.25,
"perStayFormatted": "$412.50",
"beforeDiscount": 480.0,
"chargesInfo": "Includes taxes and fees",
"propertyCurrency": "AUD",
"perStayInPropertyCurrency": 620.0
},
"rooms": [
{ "roomId": "0000001", "occupancy": 2, "price": 412.5, "currency": "USD",
"mealPlan": "Breakfast included", "freeCancellationUntil": "2026-10-30" }
],
"matchedUnit": { "bedrooms": 1, "bathrooms": 1, "beds": 1,
"area": { "value": 32, "unit": "m2" } },
"freeCancellation": true,
"checkIn": "2026-11-02",
"checkOut": "2026-11-04",
"nights": 2,
"houseRules": { "checkInFrom": "3:00 PM", "checkOutUntil": "11:00 AM" },
"reviews": [
{ "score": 9.0, "positiveText": "Great location and very clean",
"negativeText": "Check-in was slow", "reviewerCountry": "Australia",
"travellerType": "COUPLES", "nights": 3, "reviewedAt": "2026-08-25T00:00:00Z" }
],
"scrapedAt": "2026-09-05T12:00:00Z"
}

Things worth knowing before you run it

Prices need a stay. A price only exists for concrete dates, so if you leave checkIn and checkOut empty the run prices a 2 night stay 30 days out and says which window it used in the log. Set the dates whenever the dates matter.

Currency is real conversion, not a label. Every price comes back in the currency you picked, and the property's own currency is returned beside it so you can see the original. The budget filter is denominated in the same currency you picked, so the two can never disagree.

One search reaches 1000 properties. The site stops serving new results past that point, whatever total it declares. A destination with 5000 properties will report 5000 and hand over 1000 of them. The run says so in the log rather than pretending it finished. To reach the rest, split the search: by neighbourhood link, by property type, by star rating or by budget band.

Max results decides what you get, sort decides which. With maxItems set and sortBy left on the default, you get the site's own top picks. Set sortBy to price_low_to_high or rating_high_to_low when the first N matter.

Reviews are paginated. maxReviewsPerProperty is read 25 at a time, so 100 reviews cost four extra requests for that property. Reviews and the property page share ONE per-property surcharge, so turning both on costs the surcharge once.


Recurring runs

Continue an interrupted crawl

Put the previous run's id in resumeFromRunId. Everything that run already collected is skipped, so you are not charged for it twice.

Monitor a search on a schedule

Turn on incrementalMode. The actor remembers the previous run of the same search by itself and returns only what changed, each row tagged changeType (NEW, UPDATED, REAPPEARED) with a changedFields list, firstSeenAt and lastSeenAt. Price moves, rating moves and availability changes are what you will see most.

Set stateKey to run several independent campaigns. emitUnchanged and emitExpired add rows for properties that did not change and for ones that disappeared; both are off by default and both bill as results when on. EXPIRED is only ever emitted after a run that reached the natural end of every search, so a capped, resumed or partly blocked run never marks a live property as gone.


Send results into your apps (MCP connectors)

Optionally push the results straight into your own tools through Apify's MCP proxy. Set mcpConnectors to the connectors you have authorised (for example notion or slack), set notionParentPageUrl when you use Notion so pages are created in the right place, and use maxNotifyProperties to cap how many properties are exported. The dataset always keeps everything; the connector export is a side channel and never changes what was scraped.


Output views

The dataset ships four views on the Output tab: Properties (price, rating, location, stay), Property detail (facilities, house rules, room catalogue, photos), Guest reviews (scores and review text) and Changes since the last run (incremental mode).


What you are charged for

You are charged once when the run starts, once for each property returned, and once more for each property whose extra pages (its own page, its reviews, or both) were read and returned data. A property that is suppressed by incremental mode, or whose extra read failed, is not charged the surcharge. A run that returns nothing has nothing to pay for beyond the start. The rates are on the Store page for this actor.

This actor collects data that booking.com publishes to anyone, without logging in. It does not collect personal contact details. Review text and public reviewer display names are user generated content published by the site; if you process them, do so in line with the terms of the site and with the data-protection law that applies to you.