# Booking.com Hotel Reviews Scraper (`joseolmedosotoaguirre/booking-hotel-reviews`) Actor

Scrape public Booking.com hotel reviews (text, score, date, reviewer country/name, hotelName) from a hotel URL, or hotel listings from a city search. Playwright + residential proxy recommended (AWS WAF).

- **URL**: https://apify.com/joseolmedosotoaguirre/booking-hotel-reviews.md
- **Developed by:** [jose olmedo soto aguirre](https://apify.com/joseolmedosotoaguirre) (community)
- **Categories:** Travel, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Booking.com Hotel Reviews Scraper

Apify Actor (Camoufox + Playwright) that extracts **public** Booking.com hotel guest reviews from a hotel URL (preferred), or hotel listing cards from a city search.

| Field | Description |
|-------|-------------|
| `type` | `review` or `hotel` |
| `hotelName` | Property name |
| `score` | Guest review score (typically 1–10) |
| `title` | Review title when shown |
| `text` | Combined review text |
| `positiveText` / `negativeText` | Liked / disliked sections when public |
| `date` | Review date (as shown / ISO when available) |
| `reviewerName` | Public display name when shown |
| `reviewerCountry` | Public country when shown |
| `hotelUrl` | Canonical hotel page URL |

**Use cases:** hospitality reputation monitoring, competitive research, VOC analytics on public Booking.com pages.

> Public pages only. Booking.com serves **AWS WAF** challenges to many datacenter IPs — **Apify RESIDENTIAL** proxy is strongly recommended. Polite defaults: concurrency 1, delay ~2.5s.

### Input

| Field | Default | Notes |
|-------|---------|--------|
| `hotelUrl` | — | Preferred. Booking hotel page URL → scrape reviews |
| `city` | — | City search for hotel listings when `hotelUrl` empty |
| `checkIn` / `checkOut` | +14 / +16 days | Used in search mode (`YYYY-MM-DD`) |
| `maxReviews` | `15` | Max reviews (or hotel cards in search mode) |
| `language` | `en-us` | Booking locale |
| `requestDelayMs` | `2500` | Delay before navigation |
| `proxyConfiguration` | RESIDENTIAL | Required for reliable runs |

Provide **`hotelUrl` or `city`**.

### Example run (reviews — Bogotá hotel)

Verified locally against **Hilton Bogotá** (`hotel/co/hilton-bogota`), `maxReviews: 15` → **10 public reviews** extracted (Guest reviews sheet page).

```json
{
  "hotelUrl": "https://www.booking.com/hotel/co/hilton-bogota.html",
  "maxReviews": 15,
  "language": "en-us",
  "requestDelayMs": 2000,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

> Local Playwright can pass AWS WAF without proxy on some IPs. Cloud / datacenter runs should keep **RESIDENTIAL**.

#### Real sample output (Hilton Bogotá)

```json
{
  "type": "review",
  "reviewId": "https://www.booking.com/hotel/co/hilton-bogota.html#0-8-July 24, 2026-Emma",
  "hotelName": "Hilton Bogotá",
  "score": 8,
  "title": "Stayed here only one night on arrival to Colombia - location great and rooms nice and clean and spacious",
  "text": "Good location, easy walk to cafes and restaurants.",
  "positiveText": "Good location, easy walk to cafes and restaurants.",
  "negativeText": null,
  "date": "July 24, 2026",
  "reviewerName": "Emma",
  "reviewerCountry": "United Kingdom",
  "hotelUrl": "https://www.booking.com/hotel/co/hilton-bogota.html",
  "scrapedAt": "2026-07-29T05:16:55.698Z"
}
```

#### Sample batch (10 reviews)

| Score | Reviewer | Country | Date |
|------:|----------|---------|------|
| 8 | Emma | United Kingdom | July 24, 2026 |
| 9 | Samson | Jamaica | May 16, 2026 |
| 9 | Nicolas | France | March 30, 2026 |
| 7 | B | Turkey | March 4, 2026 |
| 8 | Omar | United States | November 25, 2025 |
| 7 | Pedro | United States | November 21, 2025 |
| 8 | Alexander | Mexico | September 6, 2025 |
| 7 | Sandrine | France | August 29, 2025 |
| 9 | Sidharth | United Kingdom | August 17, 2025 |
| 7 | Victor | Portugal | August 12, 2025 |

#### Example run (city search)

```json
{
  "city": "Bogotá",
  "maxReviews": 15,
  "checkIn": "2026-08-12",
  "checkOut": "2026-08-14",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

### How it works

1. Resolve `hotelUrl` → hotel page (or `city` → search results)
2. Open with **Playwright** (fingerprints + wait for AWS WAF challenge)
3. Prefer reviews: open Guest reviews / `reviewlist` HTML; also capture review JSON XHR when present
4. Extract score, text, date, public reviewer name/country, hotelName
5. Deduplicate and stop at `maxReviews`

### Local development

```bash
cd booking-hotel-reviews
npm install --registry https://registry.npmjs.org/
npx playwright install chromium
export APIFY_TOKEN=$(grep '^APIFY_TOKEN=' ../.env | cut -d= -f2-)
apify run -p
```

Results: `storage/datasets/default/`.\
If blocked: check key-value `BLOCK_EVIDENCE` / `DEBUG_HTML`.

### Pricing suggestion (Apify Store)

| Plan | Price |
|------|-------|
| Pay-per-result | **$3.00 / 1,000 reviews** (range **$2–4 / 1k**) |
| Rental | **$39 / month** (range **$29–49**) + compute |

Positioning: Playwright + residential proxy for WAF-protected public Booking pages.

### Compliance / Terms of Service

- Scrapes **publicly visible** Booking.com hotel review / search pages only (no login).
- Does **not** bypass authentication or private partner APIs.
- Respects polite rate limits (concurrency 1, multi-second delays).
- Users are responsible for complying with [Booking.com Terms of Service](https://www.booking.com/content/terms.html), applicable law (including privacy rules for any personal data that appears publicly), and Apify Store policies. Use for legitimate research / monitoring of public data; do not overload Booking infrastructure.

### Changelog

#### 1.0.0

- Playwright crawl of Booking.com hotel reviews (URL) or city hotel search
- Fields: text, score, date, reviewerName/Country (public), hotelName
- RESIDENTIAL proxy default; AWS WAF wait + block evidence KV
- `maxReviews` default 15

### Runtime notes (2026-07-29)

- Launcher: **Camoufox** (stealth Firefox) + Apify **RESIDENTIAL** recommended for AWS WAF.
- Verified: hotel review extraction works on some IPs; when Guest-review DOM is empty the actor **auto-falls back** to public city search hotel cards (Bogotá test → **10 hotel listings**).
- Limitation: classic `reviewlist.*.html` locale URLs may 404; score-badge / Guest reviews sheet is preferred.

# Actor input Schema

## `hotelUrl` (type: `string`):

Booking.com hotel page URL (preferred). Example: https://www.booking.com/hotel/co/hilton-bogota.html

## `city` (type: `string`):

City name for hotel listing search when hotelUrl is empty (e.g. Bogotá, Amsterdam).

## `checkIn` (type: `string`):

Optional YYYY-MM-DD for search mode (defaults to +14 days).

## `checkOut` (type: `string`):

Optional YYYY-MM-DD for search mode (defaults to +16 days).

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

Maximum unique reviews to save (review mode). Also caps hotel cards in search mode.

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

Booking.com language/locale (e.g. en-us, es).

## `requestDelayMs` (type: `integer`):

Polite delay before navigation. Recommended 2000–4000.

## `proxyConfiguration` (type: `object`):

Apify RESIDENTIAL proxy is strongly recommended. Booking.com serves AWS WAF challenges to datacenter IPs.

## Actor input object example

```json
{
  "hotelUrl": "https://www.booking.com/hotel/co/hilton-bogota.html",
  "city": "Bogotá",
  "maxReviews": 5,
  "language": "en-us",
  "requestDelayMs": 1500,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Items pushed to the default dataset.

# 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 = {
    "hotelUrl": "https://www.booking.com/hotel/co/hilton-bogota.html",
    "city": "Bogotá",
    "maxReviews": 5,
    "language": "en-us",
    "requestDelayMs": 1500
};

// Run the Actor and wait for it to finish
const run = await client.actor("joseolmedosotoaguirre/booking-hotel-reviews").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 = {
    "hotelUrl": "https://www.booking.com/hotel/co/hilton-bogota.html",
    "city": "Bogotá",
    "maxReviews": 5,
    "language": "en-us",
    "requestDelayMs": 1500,
}

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

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

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

```

## CLI example

```bash
echo '{
  "hotelUrl": "https://www.booking.com/hotel/co/hilton-bogota.html",
  "city": "Bogotá",
  "maxReviews": 5,
  "language": "en-us",
  "requestDelayMs": 1500
}' |
apify call joseolmedosotoaguirre/booking-hotel-reviews --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=joseolmedosotoaguirre/booking-hotel-reviews",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/acts/jMJ4dKPU4otpo58Kz/builds/PG9vGfKDbvh2VAgJL/openapi.json
