# Booking Reviews Scraper (`api-ninja/booking-reviews-scraper`) Actor

💬 Collect Booking.com hotel reviews with flexible filters and automatic pagination.

- **URL**: https://apify.com/api-ninja/booking-reviews-scraper.md
- **Developed by:** [API ninja](https://apify.com/api-ninja) (community)
- **Stats:** 5 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 🏨 What is Booking.com Reviews Scraper?

**Booking.com Reviews Scraper** collects hotel reviews, guest ratings, property responses, reviewer profiles, and stay details from Booking.com. Add a list of **hotel names, property URLs, or hotel IDs**, choose how many reviews you want per hotel, and start your run.

Use the results to understand guest feedback, compare hotels, research recurring complaints, or prepare review data for sentiment analysis. Hotels are processed one by one, and pagination runs automatically.

#### What can you do with this Actor?

- 💬 Collect review titles, positive and negative comments, scores, and review dates.
- 🏨 Read property responses alongside the feedback they address.
- 🧳 Explore traveler types, guest countries, room types, stay dates, and nights stayed.
- 📷 Retrieve review photo URLs and reviewer avatars when available.
- 🔎 Filter by traveler type, score, language, stay season, keyword, or topic.
- ↕️ Collect the most relevant, newest, oldest, highest-scoring, or lowest-scoring reviews first.
- 📦 Set a review limit per hotel or collect all available matching reviews.
- 📋 Browse three formatted tables while keeping the original review rows intact.

On Apify, you can follow each run in its logs, access results through the API, [schedule recurring runs](https://docs.apify.com/actors/running/schedules), and connect the data to tools such as Make, Zapier, and Google Sheets through [Apify integrations](https://apify.com/integrations).

### 🚀 How to scrape Booking.com reviews

1. Open the Actor in Apify Console.
2. In **Hotels to scrape**, add one hotel name, Booking.com URL, or hotel ID per list entry. Use a URL or ID when you want a precise property match.
3. Set **Desired reviews per hotel**, or enable **Scrape all reviews**.
4. Optionally select a review order and apply filters.
5. Click **Start**. Follow the **Log** tab to see the resolved hotel, matching review count, available filters, and page progress.
6. Open **Output** to explore the tables, then export your results or retrieve them through the dataset API.

**Start with one hotel and 100 reviews.** The three prefilled examples all refer to Hotel AMANO East Side; keep only one of those entries to avoid scraping the same property three times.

### ⚙️ Input settings

| Input          | Default         | What it does                                                                                                                     |
| -------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `query`        | Required        | A list of hotel names, Booking.com URLs, numeric IDs written as strings, or country/slugs such as `de/amano-east-side`.          |
| `maxReviews`   | `100`           | Maximum unique reviews to save **per hotel**. Enter a whole number of at least `25`. There is no configured upper cap.           |
| `scrapeAll`    | `false`         | Collect all available matching reviews for each hotel. Overrides `maxReviews`.                                                   |
| `sortBy`       | `most_relevant` | Review order: `most_relevant`, `newest`, `oldest`, `highest_score`, or `lowest_score`.                                           |
| `customerType` | All travelers   | Filter by `families`, `couples`, `group_of_friends`, `solo_travellers`, or `business_travellers`.                                |
| `score`        | All scores      | Filter by `wonderful` (9+), `good` (7–9), `fair` (5–7), `poor` (3–5), or `very_poor` (1–3).                                      |
| `language`     | All languages   | Original review language as a lowercase two-letter code, such as `en`, `de`, or `fr`.                                            |
| `timeOfYear`   | All seasons     | Stay season: `mar_may`, `jun_aug`, `sep_nov`, or `dec_feb`.                                                                      |
| `keyword`      | No text filter  | Search within review text, for example `breakfast`, `parking`, or `staff`.                                                       |
| `topicId`      | All topics      | Select a suggested topic or enter its numeric ID **as a string**, such as `"245"` for Breakfast. Available topics vary by hotel. |
| `locale`       | `en-us`         | Booking response language code, such as `en-us`, `en-gb`, or `fr`.                                                               |

Optional filters can be left blank. Filters apply together and use the same settings for every hotel in your list. Available languages and topic IDs appear in the run logs.

#### Input example: collect 100 reviews from one hotel

```json
{
    "query": ["https://www.booking.com/hotel/de/amano-east-side.html"],
    "maxReviews": 100,
    "scrapeAll": false,
    "sortBy": "most_relevant",
    "locale": "en-us"
}
```

You can replace the URL with `"Hotel AMANO East Side"` or `"7559215"`. Hotel names resolve to the first matching hotel suggestion.

#### Input example: find recent breakfast feedback

```json
{
    "query": ["7559215"],
    "maxReviews": 250,
    "scrapeAll": false,
    "sortBy": "newest",
    "customerType": "couples",
    "language": "en",
    "keyword": "breakfast",
    "locale": "en-us"
}
```

To collect all available matches, set `scrapeAll` to `true`. The Actor keeps requesting pages until the source returns an empty review list. With a review limit, the final page is trimmed so the saved count does not exceed your requested amount.

### 📋 Output and exports

Each dataset item is **one original review row**. Nested guest and stay objects, original text, photo URLs, and `null` values are preserved. Response-level metadata, such as pagination and available filter options, is shown in logs and is not added to review rows.

The Output tab offers three views, in this order:

| Table                          | What you can explore                                                                                                             |
| ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------- |
| **📋 Complete review details** | All 25 review, reviewer, and stay fields in one detailed table.                                                                  |
| **💬 Reviews**                 | Scores, dates, review text, property responses, guest country, traveler type, room, nights, language, helpful votes, and photos. |
| **🧳 Guest & stay details**    | Reviewer profiles, avatars, stay dates, room identifiers, and approval status.                                                   |

Dates, numbers, booleans, and images have appropriate display formats. These views change presentation only; Apify's built-in raw view and the dataset JSON retain the original nested data.

#### Example Booking.com review

This example is a review row from Hotel AMANO East Side:

```json
{
    "id": "7581d065a276f330",
    "score": 10,
    "title": null,
    "positive": null,
    "negative": null,
    "language": "de",
    "date": "2023-11-07",
    "helpful_votes": null,
    "is_approved": true,
    "photos": [],
    "guest": {
        "name": null,
        "country_code": "de",
        "country": "Germany",
        "type": "group_of_friends",
        "review_count": 3,
        "member_since": null,
        "avatar": null,
        "is_anonymous": true
    },
    "stay": {
        "checkin": "2023-11-04",
        "checkout": "2023-11-06",
        "nights": 2,
        "room_id": 755921501,
        "room_name": "Standard Double Room",
        "status": "stayed"
    },
    "owner_reply": null
}
```

Export your dataset in JSON, CSV, or Excel. JSON is useful when you want to retain nested objects and photo arrays; table-oriented exports are useful for spreadsheet analysis. Learn more about [Apify datasets and exports](https://docs.apify.com/platform/storage/dataset).

### 💰 Pricing

This Actor uses **pay-per-event pricing**, effective **October 12, 2026**. You pay for saved review rows and Actor starts. **Apify platform usage costs for these Actor runs are included**; they are not charged separately to you.

| Event                                                         |                No discount |                    Bronze |                    Silver |                      Gold |
| ------------------------------------------------------------- | -------------------------: | ------------------------: | ------------------------: | ------------------------: |
| **Result** — each saved review (`apify-default-dataset-item`) | **$10.00 / 1,000 reviews** | **$1.00 / 1,000 reviews** | **$1.00 / 1,000 reviews** | **$1.00 / 1,000 reviews** |
| **Actor Start** (`apify-actor-start`)                         |                  **$0.01** |                 **$0.01** |                 **$0.01** |                 **$0.01** |

For a single Actor start, the following examples include both the result charge and the $0.01 start charge:

| Reviews saved across all hotels | No discount | Bronze, Silver, or Gold |
| ------------------------------- | ----------: | ----------------------: |
| 100                             |       $1.01 |                   $0.11 |
| 1,000                           |      $10.01 |                   $1.01 |
| 5,000                           |      $50.01 |                   $5.01 |

The review limit applies separately to each hotel, while result charges cover the total rows saved across the run. For example, collecting 100 reviews from each of 10 hotels produces up to 1,000 billable results. A start charge still applies when no reviews are saved.

Check the Actor's **Pricing** tab for the current rate applicable to your account. Use a review limit for a predictable maximum result count; **Scrape all reviews** can collect substantially more rows.

### 🔌 API, scheduling, and integrations

Run the Actor manually or use the same JSON input through the [Apify API](https://docs.apify.com/api/v2). The Actor's **API** tab provides request examples and client snippets for integrating it into JavaScript or Python workflows.

Save your preferred input as a task and schedule it to collect reviews regularly. You can also connect results to spreadsheets, dashboards, or automation tools using [Apify integrations](https://apify.com/integrations). Each fresh run collects reviews according to its input; it does not automatically filter out reviews saved in earlier runs.

### ❓ FAQ and support

#### Why did I receive fewer reviews than requested?

The limit is a maximum, not a guaranteed count. A hotel may have fewer available reviews, or your filters may narrow the matches. Run timeouts, spending limits, and source availability can also affect how much data is collected. Check the run status and logs, then try fewer filters if needed.

#### What happens if a hotel name matches the wrong property?

A name uses the first matching hotel suggestion. Use the hotel's Booking.com URL or numeric ID for a precise match, and check the resolved hotel ID in the logs.

#### Can I enter the same hotel in different formats?

Yes, but each list entry is processed separately. Entering a name, URL, and ID for the same property scrapes it again and can produce repeated rows across those entries. Duplicate review IDs are skipped within each hotel's collection.

#### Does the language setting translate reviews?

No. `language` filters reviews by their original language. `locale` controls the response language, including labels returned by Booking.com. Review text stays as returned by the source.

#### Why are some fields empty?

Some reviews contain only a score, and anonymous guests may have no name or avatar. Photo lists can be empty, and property responses or helpful-vote counts may be unavailable. These values remain `null` or empty arrays; the Actor does not fill them with invented content.

#### How can I tell which hotel a review belongs to?

Rows retain the source review structure, which does not include a top-level hotel ID. The logs identify each hotel as it is processed. Run one hotel at a time if you need a separate dataset for each property.

#### What should I do if a run fails?

Temporary network failures and rate limits are retried automatically. If the run still fails, inspect its logs. For support, open an issue in the Actor's **Issues** tab and include the run ID, hotel identifier, and a short description of the problem. A missing API-credential error indicates an Actor configuration issue to report to the maintainer; do not post tokens or credentials in an issue.

### 🧩 Related Actor

Need to discover hotels before collecting their reviews? Try [Booking Hotel Scraper](https://apify.com/api-ninja/booking-hotel-scraper), then use the property URLs or hotel IDs in this Actor's hotel list.

# Actor input Schema

## `query` (type: `array`):

Add hotel names, Booking.com URLs, numeric hotel IDs, or country/slugs. Hotels are scraped one by one in the order listed. Names use the first matching hotel.

## `maxReviews` (type: `integer`):

Maximum number of unique reviews to save per hotel. Enter a whole number of at least 25. Ignored when Scrape all reviews is enabled.

## `scrapeAll` (type: `boolean`):

Collect every available review matching your filters for each hotel. Pagination continues until an empty results list is returned. Overrides the desired review count.

## `sortBy` (type: `string`):

Choose the order in which reviews are collected. Defaults to most relevant.

## `customerType` (type: `string`):

Only reviews from the selected traveler type.

## `score` (type: `string`):

Only reviews in the selected Booking.com score bucket. Bucket boundaries follow the API.

## `language` (type: `string`):

Only reviews written in this language (two-letter code, e.g. en, fr, or de). Leave blank for all languages. Available languages vary by property and are listed in the API response under filter_options.languages.

## `timeOfYear` (type: `string`):

Only reviews from stays during the selected months.

## `keyword` (type: `string`):

Search within review text, for example breakfast, parking, or helpful staff. Leave blank for all review texts.

## `topicId` (type: `string`):

Select a topic or enter a numeric topic ID. Suggestions come from the example hotel; available topics vary by property. Leave All topics selected to avoid a topic filter.

## `locale` (type: `string`):

Booking language code that sets the response language, e.g. en-us, en-gb, or fr. Defaults to en-us.

## Actor input object example

```json
{
  "query": [
    "Hotel AMANO East Side",
    "https://www.booking.com/hotel/de/amano-east-side.html",
    "7559215"
  ],
  "maxReviews": 100,
  "scrapeAll": false,
  "sortBy": "most_relevant",
  "customerType": "",
  "score": "",
  "language": "",
  "timeOfYear": "",
  "keyword": "",
  "topicId": "",
  "locale": "en-us"
}
```

# Actor output Schema

## `results` (type: `string`):

Saved review rows with scores, review text, property responses, photos, guest profiles and stay details. The dataset API returns the original nested JSON.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "query": [
        "Hotel AMANO East Side",
        "https://www.booking.com/hotel/de/amano-east-side.html",
        "7559215"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("api-ninja/booking-reviews-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "query": [
        "Hotel AMANO East Side",
        "https://www.booking.com/hotel/de/amano-east-side.html",
        "7559215",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("api-ninja/booking-reviews-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "query": [
    "Hotel AMANO East Side",
    "https://www.booking.com/hotel/de/amano-east-side.html",
    "7559215"
  ]
}' |
apify call api-ninja/booking-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,api-ninja/booking-reviews-scraper"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/RwiLYWwxeYYoeTOKk/builds/o914MA4lGuajvTYup/openapi.json
