Booking.com Reviews API — Guest Reviews as JSON
Documentation menu
FetchLayer FetchLayer API

Read a property’s guest reviews

Guest reviews for one property, by booking.com URL or compact id — **the route worth coming here for.** **What the guest liked and what they disliked are separate fields.** `positiveText` and `negativeText` arrive apart, either of them possibly null, in the language the guest wrote them, with `language` beside them — nothing is machine-translated over the guest's own words. So "how many people complained about the bathroom" is a count over one field rather than sentiment analysis over a paragraph. Beside them: the guest's `score`, the `stayCheckIn`/`stayCheckOut` dates and `nights` the review refers to, the `roomType` they actually stayed in, and their public first name, country and `travelerType` ("Couple", "Family", "Solo traveller"). **A reviews response tells you how complete it is, without a second call.** `totalReviewCount` is the property's full review count as Booking.com reports it, `reviewCount` is how many came back here, `hasMore` is the boolean, and `notes[]` states the pair in plain words. A real response measured on 17 September 2026: `notes: ["These are 10 of the 3854 reviews the source reports for this property.", "More reviews are available. Continue with nextCursor."]`. That difference is the point: ten reviews and *the first ten of 3,854* are different answers, and you can tell which one you are holding from the response in your hand. The response also carries `categoryScores`: The property's score split seven ways — Staff, Facilities, Cleanliness, Comfort, Value for money, Location, Free Wifi — each as `{category, label, average}`, where `category` is the stable key (`hotel_staff`, `hotel_services`, `hotel_clean`, `hotel_comfort`, `hotel_value`, `hotel_location`, `hotel_free_wifi`) and `label` the human one. A property strong on location and weak on facilities does not look like its opposite: the measured example scores 9.44 on Location against 7.82 on Facilities behind a single 8.1. Billing: 1 credit per page fetched, reported as `pagesFetched`. A page is up to 25 reviews by default and up to 500 with `limit`; a walk stops early when `limit` is reached, so `pagesFetched` reports what was actually read rather than what was asked for. Measured on 17 September 2026: `{"hotel":"fr/du-printemps-paris","limit":10}` returned 200 in 4.28-4.49s across three runs, and `{"pages":3,"limit":60}` returned 60 reviews with `pagesFetched: 3` in 6.14s.

POST /hotel-reviews Reviews
https://api.fetchlayer.dev/booking/hotel-reviews
OpenAPI JSON

Headers

Authorization string required

Bearer token — your FetchLayer API key.

Parameters

hotel string required

A property: its booking.com URL, or its compact `"countryCode/pageName"` id. The only required field.

limit integer optional

Maximum reviews returned in total, up to 500. Pass -1 for the maximum. (default: 25)

pages integer optional

How many pages of reviews to collect in one request, up to 20. Each page fetched is 1 credit. Pass -1 for the maximum — combined with `limit: -1` that is how you pull as deep as the source goes. (default: 1)

cursor string optional

Continue from a previous response's `nextCursor`.

format string optional

Envelope format: json or markdown. (default: json)

Response Fields

hotel-reviews

Read a property’s guest reviews

transport string

The source. "booking".

notes string[]

Caveats and completeness statements you can act on, in plain words. On /hotel-reviews this is where the "10 of the 3854" line lives; on /search-hotels it is where a default stay window is declared when you passed no dates; on /hotel-detail it is where the "this route does not price a stay" answer lives.

pagesFetched number

Pages read, and what the request is billed at: 1 credit per page. A page costs the same whether it comes back full or half empty. /resolve-url reports 0 and is free.

hotelId string

The property the reviews belong to, echoed back as its compact id — useful when you passed a URL.

totalReviewCount number

**The property's full review count as Booking.com reports it.** Compare it to `reviewCount` and you know whether you are holding all of them, with no second call. 3854 on the property measured.

reviewCount number

How many reviews came back in this response.

hasMore boolean

Whether there are further reviews past this page.

nextCursor string

Pass back as `cursor` to continue. Null when there is nothing more.

categoryScores object[]

The property's score split seven ways — Staff, Facilities, Cleanliness, Comfort, Value for money, Location, Free Wifi — each as `{category, label, average}`, where `category` is the stable key (`hotel_staff`, `hotel_services`, `hotel_clean`, `hotel_comfort`, `hotel_value`, `hotel_location`, `hotel_free_wifi`) and `label` the human one. A property strong on location and weak on facilities does not look like its opposite: the measured example scores 9.44 on Location against 7.82 on Facilities behind a single 8.1.

reviews[].id string

The review's id.

reviews[].score number

The guest's own score for the stay, on Booking.com's 1-10 scale.

reviews[].title string

The headline the guest gave the review, in their own language. Null where they wrote none — a scored review with no words at all is ordinary here.

reviews[].positiveText string

**What the guest liked, on its own.** Null where they wrote nothing positive. Kept apart from `negativeText` so praise and complaint are countable without parsing a paragraph.

reviews[].negativeText string

**What the guest disliked, on its own.** Null where they wrote nothing negative. A review can carry one, both or neither.

reviews[].language string

The language the text is written in, as a code. A single property's reviews are not one language — `it`, `tr` and `de` all appeared in the ten measured — so this is the field to branch on before you run anything over the text.

reviews[].stayCheckIn string

When the reviewed stay started, YYYY-MM-DD. **The review is anchored to a real stay**, not just a posting date.

reviews[].stayCheckOut string

When it ended, on the same terms.

reviews[].nights number

How many nights the stay ran — so you can separate a one-night opinion from a six-night one.

reviews[].roomType string

The room the guest actually stayed in, e.g. "Superior Twin Room". This is what lets a complaint be attributed to a room type rather than to the property.

reviews[].reviewedAt string

An ISO timestamp for when the review was posted, e.g. "2026-09-17T10:35:58.000Z".

reviews[].reviewer object

`{name, countryCode, countryName, travelerType}` — the guest's public first name, where they are from, and the trip type they declared ("Couple", "Family", "Solo traveller"). Public profile fields only.

reviews[].hostResponse string

The property's reply where it answered, null otherwise.

reviews[].helpfulVotes number

How many readers marked the review helpful. Can be null where the source published no count, and 0 is a real answer distinct from that.

Request

curl -X POST "https://api.fetchlayer.dev/booking/hotel-reviews" \
  -H "Authorization: Bearer ss-your-key" \
  -H "Content-Type: application/json" \
  -d '{"hotel":"fr/du-printemps-paris","limit":10}'

Response

{
  "transport": "booking",
  "notes": [
    "These are 10 of the 3854 reviews the source reports for this property.",
    "More reviews are available. Continue with nextCursor."
  ],
  "pagesFetched": 1,
  "hotelId": "fr/du-printemps-paris",
  "totalReviewCount": 3854,
  "reviewCount": 10,
  "hasMore": true,
  "nextCursor": "10",
  "categoryScores": [
    {
      "category": "hotel_staff",
      "label": "Staff",
      "average": 8.94481086730957
    },
    {
      "category": "hotel_services",
      "label": "Facilities",
      "average": 7.824008941650391
    },
    {
      "category": "hotel_clean",
      "label": "Cleanliness",
      "average": 8.511276245117188
    },
    {
      "category": "hotel_comfort",
      "label": "Comfort",
      "average": 8.569668769836426
    },
    {
      "category": "hotel_value",
      "label": "Value for money",
      "average": 8.086325645446777
    },
    {
      "category": "hotel_location",
      "label": "Location",
      "average": 9.435894966125488
    },
    {
      "category": "hotel_free_wifi",
      "label": "Free Wifi",
      "average": 8.791600227355957
    }
  ],
  "reviews": [
    {
      "id": "d2ac5babf71467e7",
      "score": 9,
      "title": null,
      "positiveText": null,
      "negativeText": null,
      "language": "it",
      "stayCheckIn": "2026-09-10",
      "stayCheckOut": "2026-09-13",
      "nights": 3,
      "roomType": "Superior Twin Room",
      "reviewedAt": "2026-09-17T10:35:58.000Z",
      "reviewer": {
        "name": "Roberto",
        "countryCode": "it",
        "countryName": "Italy",
        "travelerType": "Couple"
      },
      "hostResponse": null,
      "helpfulVotes": null
    },
    {
      "id": "57e7cc183b361958",
      "score": 10,
      "title": "Wir kommen wieder! Und das sagt alles.",
      "positiveText": "Im Vergleich mit allen anderen Hotels, die wir in Paris bewohnt haben, ist das Printemps der wahre Himmel auf Erden: Große Zimmer ohne Schnick-Schnack, großes schönes Bad mit Badewanne, alles renoviert und fein säuberlich gepflegt. Reizendes Personal!",
      "negativeText": "Da fällt mir überhaupt nichts ein!",
      "language": "de",
      "stayCheckIn": "2026-09-09",
      "stayCheckOut": "2026-09-15",
      "nights": 6,
      "roomType": "Superior Twin Room",
      "reviewedAt": "2026-09-16T21:33:05.000Z",
      "reviewer": {
        "name": "Penny",
        "countryCode": "ch",
        "countryName": "Switzerland",
        "travelerType": "Family"
      },
      "hostResponse": null,
      "helpfulVotes": 0
    }
  ]
}