Booking.com Reviews Scraper: Pros, Cons, Reviewer Country avatar

Booking.com Reviews Scraper: Pros, Cons, Reviewer Country

Pricing

from $0.81 / 1,000 reviews

Go to Apify Store
Booking.com Reviews Scraper: Pros, Cons, Reviewer Country

Booking.com Reviews Scraper: Pros, Cons, Reviewer Country

Booking.com hotel reviews for hotel URLs: score, liked and disliked text, hotel reply, reviewer country, traveler type, stay details; $1.80 per 1,000 reviews. Filters by traveler type, score and season, optional free hotel summary. Only-new mode, free error rows, no reviewer names.

Pricing

from $0.81 / 1,000 reviews

Rating

0.0

(0)

Developer

Arcadium Data

Arcadium Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Categories

Share

Give it Booking.com hotel URLs and it returns one JSON row per guest review: score (1-10 and on a 0-5 scale), what the guest liked and disliked as separate fields, title, date, language, traveler type, room type, nights, reviewer country and the hotel's reply. $1.80 per 1,000 reviews on the free plan, less on paid plans; you pay only for rows you get.

Why this actor

  • Liked and disliked text arrive split, so aspect-level analysis needs no guessing.
  • Filters by traveler type, score band and season, with one charge per review even when it matches several passes.
  • Only new reviews and a free coverage row per hotel (stated vs delivered), plus a free error row with a code for an input that failed.
  • Easy switch. Input names of the other popular Booking reviews actor (sortReviewsBy, cutoffDate, reviewScores, maxReviewsPerHotel) are accepted.

Built by Arcadium Data: public data, dated and agent-ready, never personal data.

Use with AI agents

Returns Booking.com hotel reviews (score, liked and disliked text, hotel reply, reviewer country) for hotel URLs. Agents can call it through the Apify MCP server (https://mcp.apify.com, open source as apify/actors-mcp-server) as arcadium/booking-reviews: the input schema is read from the actor, the result is a dataset of JSON rows.

Input example (minimal):

{
"startUrls": [
{
"url": "https://www.booking.com/hotel/gb/the-savoy.html"
}
],
"maxReviewsPerHotel": 20
}

What comes back: one review row per review (charged), free coverage rows (stated total vs delivered), an optional free hotel-summary row (includeHotelSummary) and a free error row for an input that could not be read. Filter on the rowType field. An input that fails is reported, not hidden (includeErrorRows, on by default): the error row carries rowType: "error", a code (invalid_input, not_found, blocked, unavailable, filter_unsupported or no_match), a message and the input it is about. Retry on blocked and unavailable later; do not retry the other codes with the same input.

Cost of the call above: 20 reviews at $1.80 per 1,000 plus the $0.001 start fee is about $0.04 on the free plan; paid plans pay less. Free rows are never charged.

What you get

FieldWhat it holds
reviewIdBooking's own ID, prefixed Booking___. Stable between runs, so weekly exports can be deduplicated.
dateReview date, ISO format.
titleThe review headline.
pros, consWhat the guest liked and disliked. text holds both joined.
ratingOverallScore on a 0 to 5 scale (Booking's 1 to 10 score divided by 2). The original is in extras.score10.
languageReview language, empty when Booking could not tell.
helpfulVotesHow many readers marked the review as helpful.
vendorResponseThe hotel's reply, with the greeting name removed.
extrasTraveler type, room type, check-in and check-out dates, nights, photo count.
countryReviewer country as a two-letter code. On by default; switch off with includeReviewerCountry: false.
entityId, productName, productUrl, productWhich hotel the review belongs to.

Output example:

{
"platform": "booking",
"reviewId": "Booking___c6397d1e2a854aa3",
"date": "2026-09-30",
"title": "Perfect stay",
"pros": "Staff went out of their way for us.",
"cons": null,
"ratingOverall": 5,
"language": "en",
"vendorResponse": "Dear [name],\nThank you for staying with us...",
"extras": { "score10": 10, "travelerType": "COUPLES", "roomType": "Superior King", "nights": 3 },
"entityId": "280149",
"productName": "The Savoy"
}

Input

{
"startUrls": [{ "url": "https://www.booking.com/hotel/gb/the-savoy.html" }],
"maxReviewsPerHotel": 500,
"sort": "NEWEST_FIRST",
"travelerTypes": ["COUPLES"],
"scoreRanges": ["SUPERB", "GOOD"],
"languages": ["en", "de"]
}
FieldWhat it does
startUrls, hotelIdsHotel or reviews page URLs, or numeric hotel IDs. Rows from IDs have no hotel name, and productUrl is the Booking.com home page because a hotel page address cannot be built from an ID alone.
maxReviewsPerHotelCap per hotel.
sortNewest first (default), oldest first, highest or lowest score, most relevant.
travelerTypesFamilies, couples, groups of friends, solo, business.
scoreRangesSuperb (9+), good (7-9), passable (5-7), poor (3-5), very poor (1-3).
languages, seasons, topics, keywordLanguage codes, stay season, topic IDs, free-text search.
dateFromOnly reviews from this date on. With newest first, reading stops once reviews are older. With any other sort, every page is read and older reviews are filtered out, so it costs more requests.
onlyNewReviews, stateKeyOnly reviews not delivered by an earlier run with the same key.
includeHotelSummaryOne free row per hotel with the overall score and the category scores (cleanliness, comfort, location, staff, value, services, wifi) against the city average where Booking publishes it.
includeReviewerCountryAdds the reviewer's country as an ISO code. On by default.

Each traveler type, score band and season in your list is read as its own pass, so a long list multiplies the number of requests. A review that matches several passes is delivered and charged once. With newest first, dateFrom and onlyNewReviews stop each pass early as soon as a page is older than the cutoff, so extra passes cost a few requests each. With any other sort every pass is read in full.

Migrating from another Booking reviews actor

These input names of the other popular Booking reviews actor are accepted as they are: sortReviewsBy (f_recent_desc, f_score_desc and so on), cutoffDate, reviewScores (review_adj_superb, review_adj_good, ...) and maxReviewsPerHotel. Output field names are our own.

Coverage and edited reviews

A free coverage row per hotel says how many reviews the source reports against how many you received, and why reading stopped (your cap, the source's cap, or the end). With onlyNewReviews, a review that was edited after it was delivered comes back once more with extras.changeType set to edited; that row is charged like a new review.

Use it from an AI assistant

Paste this into your assistant to run the actor for you:

Use the Apify actor "booking-reviews" to collect reviews.
Input: {"startUrls":[{"url":"<hotel page URL>"}],"maxReviewsPerHotel":200,"sort":"NEWEST_FIRST"}
Each dataset row is one review. Key fields: date, title, pros, cons, ratingOverall, extras.travelerType.
Run it, then summarize the main praise and complaints and mention the review count.

Use it from code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("arcadium/booking-reviews").call(run_input={
"startUrls": [{"url": "https://www.booking.com/hotel/gb/the-savoy.html"}],
"maxReviewsPerHotel": 200,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["date"], item["ratingOverall"], item["pros"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('arcadium/booking-reviews').call({
startUrls: [{ url: 'https://www.booking.com/hotel/gb/the-savoy.html' }],
maxReviewsPerHotel: 200,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, 'reviews');

Pricing

You pay per review delivered, at the price of your Apify plan. Hotel summary rows, coverage rows, error rows and repeats in only-new mode are free.

Apify planPer 1,000 reviews
Free$1.80
Starter (Bronze)$1.71
Scale (Silver)$1.35
Business (Gold)$0.81
Platinum$0.45
Diamond$0.27

Plus a one-off $0.001 per GB of memory when a run starts.

Set a maximum cost per run in the Apify run options and the actor stops before it goes over.

Use cases

  • Reputation monitoring: pull the newest reviews every week with onlyNewReviews and watch what changes.
  • Competitor benchmarking: compare category scores (location, staff, value) across hotels in one city with the summary row.
  • Complaint mining: filter to poor and very poor scores and read the cons column.
  • Model training: aspect-level sentiment from the native liked and disliked split.

Limitations

  • Public reviews only. Nothing behind a login.
  • Booking only shows roughly the last three years of reviews, so "all reviews" means that window.
  • Review language is empty for a small share of reviews where Booking does not know it.
  • Searching by hotel name is not supported yet. Paste the hotel page URL or the hotel ID.
  • dateFrom works with every sort order, but only newest first can stop early; other orders read all matching pages and filter.
  • Hotel IDs without a URL give rows without a hotel name; Booking only reports the name through the hotel page.
  • Booking publishes category scores (cleanliness, location and so on) per hotel, not per review, so they are in the optional summary row only.
  • City averages in the summary row are only available when the hotel is given as a URL.

Privacy

Reviewer names, usernames, profile photos, guest photos, emails and phone numbers are never collected. Names in greetings and sign-offs (for example 'Dear John' or 'Regards, Anna') are replaced with [name]; other names in the text are not detected. The reviewer's country is on by default and is a two-letter country code, nothing else about the person; switch it off with includeReviewerCountry: false.

FAQ

How fresh is the data? It is read when you run the actor, so it matches what the site shows at that moment.

Can I get only new reviews since my last run? Yes. Turn on onlyNewReviews and keep the same stateKey. The state is stored per hotel. Use another stateKey to start a separate series.

A hotel returned no reviews. Why? Check that the URL opens a hotel page in your browser. Unknown hotels and hotels without reviews return an error row, which is not charged.

Something looks wrong in the output. Who do I tell? Open an issue on the actor page with the run link. We read them all.