Booking.com Reviews Scraper
Under maintenancePricing
from $0.30 / 1,000 row saveds
Booking.com Reviews Scraper
Under maintenanceScrape every guest review for any Booking.com property: full positive and negative text, 1–10 score, stay dates, nights, room type, reviewer country, traveller type, photos and replies. Adds a reputation profile per property with all seven sub-scores. Filter by keyword, language, season or date.
Pricing
from $0.30 / 1,000 row saveds
Rating
0.0
(0)
Developer
Hamza
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Every guest review for any Booking.com property, as clean structured data. Name the properties you care about — by name, by the link from your browser, or by their Booking.com id — and this actor collects the full text of what guests wrote, the score they gave, when they stayed and for how long, the room they booked, the country they came from, the kind of traveller they were, the photos they attached and whether the property ever replied. On top of the raw reviews it produces one summary row per property with all seven sub-scores, the traveller-segment mix, the review-language mix and the topics Booking.com itself surfaces for that property. Built for hotel operators watching their own reputation, revenue and brand teams watching a comp set, and analysts who need review text in bulk for scoring or text mining.
There is no limit on how many reviews it can collect for a single property — a property with thousands of reviews can be pulled in full.
What you can do with it
- Track your own reputation over time. Run it on a schedule with "Newest first" and an "only reviews since" date to top up a growing review archive cheaply, day after day.
- Benchmark a comp set. Point it at ten competitors and compare the seven sub-scores — staff, facilities, cleanliness, comfort, value for money, location, free wifi — side by side, with the traveller mix behind each one.
- Find out what guests actually complain about. Filter to a keyword like "noise", "breakfast" or "parking" and get both the matching reviews and the recalculated total, so you learn how many guests mentioned it, not just which.
- Segment by who was staying. Split families from business travellers from solo guests and see whether your weak scores come from one segment only.
- Compare seasons honestly. Ask for stays in one season and get that season measured directly, rather than trusting a published seasonal figure.
- Feed text analysis. Positive and negative text arrive as separate clean columns with markup already stripped, ready for sentiment or topic modelling.
What you get
Two kinds of row land in the same dataset, told apart by recordType.
A review row:
{"recordType": "review","reviewId": "42ec08f76423b438","reviewScore": 1,"reviewedAt": "2026-07-22T10:46:19.000Z","reviewedDateUnix": 1784717179,"reviewTitle": "Not for family with kids","positiveText": "Nothing","negativeText": "The hotel is old beds, doors got holes, no working ice mech or vending machine. This is not a hotel for a family .. The breakfast was very trash disappointed and had waffles but no eggs or sausages, nothing but cereal and oatmeal package.","reviewTextLanguage": "xu","reviewerName": "Nacoyia","reviewerCountryCode": "us","reviewerCountryName": "United States","reviewerIsAnonymous": false,"reviewerAvatarUrl": "https://xx.bstatic.com/static/img/review/avatars/ava-n.png","checkinDate": "2026-07-16","checkoutDate": "2026-07-18","numNights": 2,"roomId": "19110202","roomTypeName": "Queen Room with Two Queen Beds - Non-Smoking","customerType": "SOLO_TRAVELLERS","helpfulVotesCount": 0,"isTranslatable": false,"photos": [],"partnerReplyDate": null,"hasPartnerReply": false,"hotelId": 191102,"hotelName": "Hilton Austin","hotelUrl": "https://www.booking.com/hotel/us/hilton-austin.en-us.html","propertyReviewsCount": 898,"filterLanguage": null,"filterCustomerType": "ALL","filterTimeOfYear": "ALL","filterKeyword": null,"sortedBy": "MOST_RELEVANT","scrapedAt": "2026-07-30T09:14:02.181Z","actorRunId": "y7Kq2mVbN4tRp8sD"}
And one reputation profile row per property:
{"recordType": "propertyProfile","hotelId": 191102,"hotelName": "Hilton Austin","hotelUrl": "https://www.booking.com/hotel/us/hilton-austin.en-us.html","reviewsCount": 898,"resolutionConfidence": "high","subScores": [{ "key": "hotel_staff", "label": "Staff", "value": 7.901 },{ "key": "hotel_services", "label": "Facilities", "value": 7.11 },{ "key": "hotel_clean", "label": "Cleanliness", "value": 7.334 },{ "key": "hotel_comfort", "label": "Comfort", "value": 7.31 },{ "key": "hotel_value", "label": "Value for money", "value": 7.471 },{ "key": "hotel_location", "label": "Location", "value": 7.435 },{ "key": "hotel_free_wifi", "label": "Free Wifi", "value": 8.004 }],"subScoreAverage": 7.509,"segmentMix": [{ "segment": "FAMILIES", "label": "Families", "count": 326 },{ "segment": "COUPLES", "label": "Couples", "count": 277 },{ "segment": "GROUP_OF_FRIENDS", "label": "Groups of friends", "count": 55 },{ "segment": "SOLO_TRAVELLERS", "label": "Solo travelers", "count": 240 },{ "segment": "BUSINESS_TRAVELLERS", "label": "Business travelers", "count": 162 }],"languageMix": [{ "languageCode": "fr", "languageName": "French", "count": 21 },{ "languageCode": "en", "languageName": "English", "count": 611 },{ "languageCode": "es", "languageName": "Spanish", "count": 163 },{ "languageCode": "de", "languageName": "German", "count": 22 }],"topics": [{ "id": 270, "name": "Room" },{ "id": 245, "name": "Breakfast" },{ "id": 276, "name": "Clean" },{ "id": 249, "name": "Location" }],"availableSorters": ["MOST_RELEVANT", "NEWEST_FIRST", "OLDEST_FIRST", "SCORE_DESC", "SCORE_ASC"],"scrapedAt": "2026-07-30T09:14:02.181Z","actorRunId": "y7Kq2mVbN4tRp8sD"}
Input reference
Which properties
Give them any of three ways, or mix all three — duplicates are merged and the most precise form of a property wins.
| Field | Type | Default | Description |
|---|---|---|---|
hotelNames | array of strings | ["Hilton Austin"] | Property names to look up, one per line. The name you asked for is checked against the property Booking.com returns; a weak match is reported and skipped rather than guessed at. |
hotelUrls | array of strings | [] | Booking.com property page links pasted straight from your browser. The property behind the link is verified before any reviews are saved. |
hotelIds | array of strings | [] | Booking.com numeric property ids, for example 191102. The fastest and most exact way to name a property — nothing has to be looked up and there is no chance of landing on the wrong hotel. |
maxHotels | integer | 20 (max 200) | How many properties to work through, counted after the three lists are merged. |
How many reviews
| Field | Type | Default | Description |
|---|---|---|---|
maxReviewsPerHotel | integer | 250 (max 5000) | Reviews to save per property. Set to 0 for reputation profiles only and no individual reviews. If you list several review languages, this is the allowance for each language. |
sortBy | select | MOST_RELEVANT | Order Booking.com serves reviews in: most relevant, newest first, oldest first, highest score first, lowest score first. |
onlyReviewsSince | date | (empty) | Keep only reviews written on or after this date. Pair it with "Newest first" and the run stops as soon as it reaches reviews older than your cut-off — the cheapest way to do a daily or weekly top-up. |
Narrow it down
Every filter below is applied by Booking.com itself, and the property's own review total is recalculated for the filter you chose — so a filtered run tells you how many reviews match, not just which ones.
| Field | Type | Default | Description |
|---|---|---|---|
keywordFilter | string | (empty) | Keep only the reviews Booking.com matches for this term, for example noise or breakfast. Matching is Booking.com's own, not a pattern you control; a term nobody wrote about returns nothing at all rather than an error. |
reviewLanguages | array of strings | [] | Two-letter language codes such as en, es, fr — up to ten. Each language is collected as its own pass, with its own reviews-per-property allowance, and every row records which pass produced it. Empty means every language. |
customerType | select | ALL | All travellers, families, couples, groups of friends, solo travellers or business travellers. |
timeOfYear | select | ALL | Any time of year, or stays in March–May, June–August, September–November or December–February. |
What to include
| Field | Type | Default | Description |
|---|---|---|---|
includeReputationProfile | boolean | true | Adds one extra row per property with all seven sub-scores, the traveller-segment mix, the review-language mix and the topics Booking.com surfaces for that property. |
includePhotos | boolean | true | Adds the guest photos attached to a review, with every published size. Turn it off for a smaller dataset. |
Run settings
Sensible defaults — most runs never need to touch these.
| Field | Type | Default | Description |
|---|---|---|---|
maxRequests | integer | 2000 (max 20000) | A hard ceiling on how much work one run may do. The projected size of the job is printed in the log before anything starts, and the run finishes cleanly with whatever it collected once the ceiling is reached. |
| Properties at a time | integer | 4 (max 8) | How many properties are worked on at once. Higher finishes a long list sooner. |
language | string | en-us | Booking.com language code used for labels such as sub-score names, for example en-us, en-gb, de, fr, es. |
currency | string | USD | Three-letter currency code. Reviews carry no prices, so this only affects the wording of anything money-related. |
proxyCountry | string | us | Country to appear to browse from. Booking.com serves the same reviews everywhere, so most runs can leave this alone. |
Output fields
Review rows (recordType: "review")
| Field | Type | Description |
|---|---|---|
reviewId | string | Stable 16-character identifier for the review. Use it to de-duplicate across runs. |
reviewScore | number | The guest's overall score, 1–10. |
reviewedAt | string | When the review was written, as a full ISO 8601 timestamp. |
reviewedDateUnix | integer | The same moment as published by Booking.com, in seconds. |
reviewTitle | string | The review headline. Often absent. |
positiveText | string | What the guest liked. Highlight markup is stripped. |
negativeText | string | What the guest disliked. Often absent. |
reviewTextLanguage | string | The language the review was written in. Not the reviewer's nationality. |
reviewerName | string | Display name of the guest. |
reviewerCountryCode | string | Two-letter country of the guest. |
reviewerCountryName | string | Country name of the guest. |
reviewerIsAnonymous | boolean | Whether the guest posted anonymously. |
reviewerAvatarUrl | string | Avatar image for the guest. |
checkinDate | string | First night of the stay being reviewed. |
checkoutDate | string | Last day of the stay being reviewed. |
numNights | integer | Length of the stay in nights. |
roomId | string | Identifier of the room booked, as text so it joins cleanly against other datasets. |
roomTypeName | string | Name of the room booked. |
customerType | string | Traveller segment: families, couples, groups of friends, solo or business. |
helpfulVotesCount | integer | How many people marked the review helpful. |
isTranslatable | boolean | Whether Booking.com offers a translation of this review. |
photos | array | Guest photos, each with an id, a kind and every published size and URL. |
partnerReplyDate | string | When the property replied, when it did. |
hasPartnerReply | boolean | Whether the property replied at all. |
hotelId | integer | Booking.com id of the property. |
hotelName | string | Name of the property, as Booking.com publishes it. Empty when you supplied a bare numeric id, because then nothing has to be looked up — give the name or the link if you want this column filled. |
hotelUrl | string | Link to the property page. A convenience field built from the property's own details — it may not resolve for every property. |
propertyReviewsCount | integer | The property's review total for the filters in force on this row. |
filterLanguage | string | Which review-language pass produced this row, when languages were used. |
filterCustomerType | string | Traveller-type filter in force for this row. |
filterTimeOfYear | string | Season filter in force for this row. |
filterKeyword | string | Keyword filter in force for this row. |
sortedBy | string | The order the reviews were collected in. |
scrapedAt | string | When this row was collected. |
actorRunId | string | The run that produced this row. |
Reputation profile rows (recordType: "propertyProfile")
| Field | Type | Description |
|---|---|---|
hotelId | integer | Booking.com id of the property. |
hotelName | string | Name of the property. |
hotelUrl | string | Link to the property page. |
reviewsCount | integer | Total reviews published for the property. |
resolutionConfidence | string | How certain the actor is that this is the property you asked for: exact when you gave an id, high when the link or the name matched what came back. |
subScores | array | The seven sub-scores, each with its internal key, its display label and its value: staff, facilities, cleanliness, comfort, value for money, location, free wifi. |
subScoreAverage | number | Mean of the seven sub-scores, for quick comp-set ranking. |
segmentMix | array | Review counts by traveller segment. |
languageMix | array | Review counts by review language. |
topics | array | The topics Booking.com itself surfaces for the property, with their ids. |
availableSorters | array | The orders this property's reviews can be sorted in. |
scrapedAt | string | When this row was collected. |
actorRunId | string | The run that produced this row. |
Pricing
Pay per event — you are billed for what you keep, not for how long the run takes.
| What triggers a charge | Price |
|---|---|
| Any row saved to the dataset — a review or a reputation profile | $0.0003 each, i.e. $0.30 per 1,000 rows |
| A property's reputation profile is produced | $0.008 per property |
Review rows arrive in bulk and are priced accordingly, so a deep sweep stays cheap. A reputation profile is one row per property and is assembled property by property, so it costs several times more to produce than a review row and it carries its own charge instead of being buried in the per-row price.
Worked example: 10,000 reviews across 20 properties is about $3.16 — $3.00 of review rows plus $0.16 of reputation profiles. Switch the reputation profile off and pricing is single-tier: 10,000 reviews for $3.00 flat. A profile-only run over a 50-property comp set is roughly $0.42.
Reviews that fall outside your date cut-off, or that a filter excludes, are never saved and therefore never billed.
Limits and what this actor cannot do
- Seasonal review counts published by Booking.com read zero even for properties with thousands of reviews, so this actor never repeats them. When you ask for a season it applies that season as a real filter and reports the recalculated total, which is the only trustworthy figure.
- A review's language is not the reviewer's nationality. They are separate
columns —
reviewTextLanguageandreviewerCountryCode— and conflating them will give you wrong conclusions about where your guests come from. The language value itself is occasionally an odd code that Booking.com publishes as-is. - Looking a property up by name is not guaranteed. Booking.com sometimes returns a confidently-presented first result that is a different hotel with a similar profile. When the name you asked for does not match the property that came back, that property is skipped and the log names both strings rather than writing someone else's reviews under your hotel. If you need certainty, give the property link or its numeric id.
- The same property listed twice is collected once. If a property appears in your list both by name and by id or link, it is only recognised as one property once the name has been looked up — from then on the duplicate is skipped and said so in the log, so you are never billed twice for the same reviews.
- The property link is a convenience field. It is assembled from the property's own details and will resolve for the great majority of properties, but it is not the link Booking.com published, and a few may not open.
- Keyword matching is Booking.com's own. It is not a pattern you control, so it may include a near-match you would not have written and exclude a phrasing you would have. A term nobody wrote about returns nothing at all, which is a clean answer and not an error.
- Review totals are a live snapshot. A property's counts move as guests write and Booking.com re-indexes, so two runs minutes apart can differ slightly.
- Reviews carry no prices, so this actor cannot tell you what any guest paid.
- Speed depends on the size of the job and on Booking.com's own response times. No fixed completion time is promised for any run size.
- Booking.com's terms prohibit automated access. You are responsible for using this data lawfully and in line with the source site's terms, including any personal-data obligations that attach to review text and reviewer names in your jurisdiction.
FAQ
Do I need a Booking.com account? No. None at all.
Does it need a login, a password or any personal details? No. There is nothing to sign in to and nothing to configure — pick your properties and run it.
How many reviews can I get for one property?
As many as Booking.com publishes. There is no ceiling on review depth, so a
property with several thousand reviews can be collected in full — set
maxReviewsPerHotel high enough and raise maxRequests to match. The projected
size of the job is printed in the log before any work starts.
Can I schedule it to watch reviews as they come in?
Yes, and it is designed for it. Set sortBy to "Newest first" and
onlyReviewsSince to the date of your last run: the actor stops as soon as it
reaches reviews older than your cut-off, so a daily top-up over a watchlist
costs a fraction of the first full pull. reviewId is stable across runs, so
de-duplicating your archive on that column is all you need.
Is the data complete? For a property you identified by id or by link, yes — every published review can be collected, and the reputation profile comes from Booking.com's own published figures. Two honest caveats: a property named only by name may be skipped if the match is not convincing, and Booking.com's seasonal counts are unusable, which is why seasons are measured by filtering instead.
Why do some rows have empty reviewTitle, negativeText or photos?
Because those guests did not write a headline, had nothing negative to say, or
attached no photos. Those fields are frequently absent by nature and arrive
empty rather than being filled with a guess.
What is the difference between the two row types? Review rows are the raw material — one per guest review — and are what you want for text analysis. The reputation profile row is one summary per property and is what you want for a comp-set comparison. You can have either or both.