Booking.com Reviews Scraper avatar

Booking.com Reviews Scraper

Pricing

from $0.49 / 1,000 results

Go to Apify Store
Booking.com Reviews Scraper

Booking.com Reviews Scraper

Extracts guest review data (ratings, text, reviewer demographics, stay details, partner replies) for hotels listed on Booking.com by hotel URL or hotel ID.

Pricing

from $0.49 / 1,000 results

Rating

0.0

(0)

Developer

Ibnu Adzim

Ibnu Adzim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Extracts guest review data for any hotel listed on Booking.com — just give it a hotel page link or hotel ID.

Why use this actor

  • No account, no login, and no API key needed — works on public hotel pages only.
  • Pulls the full review picture: star ratings, written reviews (positive/negative split), reviewer country and trip type, room type and stay dates, helpful-vote counts, and any partner (hotel) reply.
  • Also returns the hotel's aggregate rating breakdown — score filters, customer-type breakdown, language breakdown, room-type breakdown, and total review count — as a single summary row per hotel.
  • Every hotel you submit gets at least one output row — including a clear diagnostic reason on rows that couldn't be matched or fetched, so nothing silently disappears from your results.
  • Works with either a full Booking.com hotel page URL or the raw numeric hotel ID.
  • Built-in cap on reviews per hotel (adjustable) so a single wildly popular hotel with tens of thousands of reviews doesn't blow up your run — set it to 0 to pull everything.

How it works

  1. You give the actor one or more Booking.com hotel page links (or numeric hotel IDs).
  2. If you gave a URL, the actor first resolves it to Booking's internal hotel ID via the same hotel-search lookup Booking's own search box uses — and double-checks the match against the hotel name in your URL before trusting it, so it never silently returns a different property's reviews.
  3. It then pulls the review data directly from Booking.com, page by page, until it runs out of reviews or hits your per-hotel cap.
  4. Results are streamed to your dataset as they finish, with automatic retries for temporary hiccups.
  5. You export the finished dataset as JSON, CSV, or Excel straight from the Apify Console — no scrapers or infrastructure to manage yourself.

Input

{
"hotelUrls": [
"https://www.booking.com/hotel/sg/marina-bay-sands.html"
],
"sortBy": "most_relevant",
"maxReviewsPerHotel": 200,
"maxConcurrency": 3,
"proxyConfiguration": {
"useApifyProxy": true,
"apifyProxyGroups": ["RESIDENTIAL"]
}
}
FieldTypeDescription
hotelUrlsarray of stringsBooking.com hotel page URLs (e.g. https://www.booking.com/hotel/sg/marina-bay-sands.html) or raw numeric Booking.com hotel IDs (e.g. 245881).
sortBystringReview order: most_relevant (default), newest_first, oldest_first, highest_score, or lowest_score.
maxReviewsPerHotelintegerStop after this many reviews per hotel. Default 200. Set to 0 to fetch every review (can be slow for hotels with tens of thousands of reviews).
maxConcurrencyintegerHow many hotels to process at the same time. Default 3.
proxyConfigurationobjectProxy settings. Residential proxy is turned on by default, though the review API was not observed to gate on IP reputation during testing.

Output

Each hotel produces one summary row plus one review row per guest review. Real examples from a run against the live site (long fields truncated):

Summary row (recordType: "SUMMARY"):

{
"_input": "https://www.booking.com/hotel/sg/marina-bay-sands.html",
"_source": "S1-graphql",
"_scrapedAt": "2026-08-10T12:32:40Z",
"recordType": "SUMMARY",
"hotelId": 245881,
"matchedHotelName": "Marina Bay Sands",
"matchScore": 1.0,
"reviewsCount": 16291,
"customerTypeFilter": [
{ "name": "Families (5593)", "value": "FAMILIES", "count": 5593 },
{ "name": "Couples (7437)", "value": "COUPLES", "count": 7437 },
"... 3 more"
],
"reviewScoreFilter": [
{ "name": "Wonderful: 9+ (14116)", "value": "REVIEW_ADJ_SUPERB", "count": 14116 },
"... 4 more"
],
"sorters": [
{ "name": "Most relevant", "value": "MOST_RELEVANT" },
"... 4 more"
]
}

Review row (recordType: "REVIEW"):

{
"_input": "https://www.booking.com/hotel/sg/marina-bay-sands.html",
"_source": "S1-graphql",
"_scrapedAt": "2026-08-10T12:32:40Z",
"recordType": "REVIEW",
"hotelId": 245881,
"matchedHotelName": "Marina Bay Sands",
"reviewUrl": "80ba17d8d02303e4",
"reviewScore": 1.0,
"reviewedDate": 1776392467,
"helpfulVotesCount": 1,
"guestDetails": {
"username": "Nahalla",
"countryCode": "au",
"countryName": "Australia",
"guestTypeTranslation": "Family",
"anonymous": false
},
"bookingDetails": {
"customerType": "FAMILIES",
"roomType": { "id": "24588264", "name": "Sands Family Suite" },
"checkinDate": "2026-04-03",
"checkoutDate": "2026-04-13",
"numNights": 10,
"stayStatus": "stayed"
},
"textDetails": {
"title": "Will never stay again",
"positiveText": "The location was good, a lot of things to do and places to go .",
"negativeText": "Not child friendly, the room was expensive for no reason...",
"lang": "en"
},
"partnerReply": null,
"isApproved": true
}

When a hotel URL can't be confidently matched to a specific property, or the input can't be understood, the actor still emits one row for that input with a clear reason, instead of leaving it out silently:

{
"_input": "https://www.booking.com/hotel/ae/burj-al-arab.html",
"_source": "none",
"_scrapedAt": "2026-08-10T12:32:40Z",
"recordType": "ERROR",
"_error": "hotel_not_confidently_resolved",
"_errorDetail": "No confident match for 'burj al arab' (country=ae). Best candidate: 'GuestReady - A Glimpse of Burj Al Arab' (score=0.50, need >=0.8). Try passing the raw numeric hotel ID instead."
}
FieldTypeDescription
_inputstringThe hotel URL or ID you submitted.
_sourcestringWhich internal strategy produced this row. "none" on a failed row.
_scrapedAtstringUTC timestamp of when this row was produced.
recordTypestring"SUMMARY", "REVIEW", or "ERROR".
hotelIdintegerBooking.com's numeric ID for the hotel (present on successful rows).
matchedHotelNamestringThe hotel name Booking.com's own search returned for your URL (present when a URL was resolved; blank when you passed a raw numeric ID directly).
matchScorenumberHow confidently the URL was matched to that hotel, from 0 to 1 (present when a URL was resolved).
_errorstringPresent only on rows that couldn't be fetched, e.g. hotel_not_confidently_resolved, invalid_input.
_errorDetailstringHuman-readable detail for the error, present only alongside _error.
(all other fields)On a successful row, every review or rating field Booking.com provides is passed through unchanged — the exact set can vary slightly by hotel.

Notes / limits

  • Very popular hotels can have tens of thousands of reviews. The default 200-per-hotel cap keeps runs fast and predictable; raise it (or set it to 0) if you need the complete history for a specific property.
  • Booking.com hotel URLs don't embed a numeric ID, so the actor resolves your URL to a hotel via Booking's own hotel-name search and cross-checks the match — for a handful of very generic or landmark-style names (e.g. searching just a tourist landmark's name rather than the exact hotel name on your URL) this match can come back inconclusive. If that happens, open the hotel's page in your browser once and copy the numeric ID from Booking's own listing, or try a more specific hotel URL.
  • Reviews are exactly as written by the guest — no automatic translation is applied by this actor (Booking.com's own lang field on each review tells you what language it's in).

Other actors in this collection

ActorWhat it returns
Agoda Reviews ScraperGuest reviews for hotels listed on Agoda.com
Orbitz Hotel Reviews ScraperGuest reviews for hotels listed on Orbitz.com
GetYourGuide Reviews ScraperGuest reviews for tours/activities listed on GetYourGuide.com