---
title: "Booking.com scraper"
description: "Scrape Booking.com hotel pages as JSON: review scores, room types, house rules, location and descriptions. One API request from Python, Node.js, the CLI or MCP."
canonical: https://www.zenrows.com/scrape/booking
updated: 2026-10-20
---

# Booking.com scraper

The Zenrows Booking.com scraper turns any Booking.com hotel URL into structured JSON: property ID, type, description, cover image, overall review score, review count, category scores, room types with guest capacity, check-in rules and coordinates. You send the URL, Fetch in Adaptive Stealth Mode opens the page, and Extract returns the fields. Run it from an API call, the CLI or an AI agent.

- Site: booking.com
- Returns: Hotels, review scores, room types and house rules

## Run it: one Booking.com hotel in, JSON out

```json Input
{
  "url": "https://www.booking.com/hotel/us/the-plaza.html",
  "mode": "auto",
  "extract": "auto"
}
```

```json Output
{
  "property": {
    "property_id": "58958",
    "property_type": "Hotel",
    "canonical_url": "https://www.booking.com/hotel/us/the-plaza.html",
    "cover_image_url": "https://r-xx.bstatic.com/xdata/images/hotel/1200x630/914954799.jpg?k=162744612c…&o=",
    "description": "Located at the crossroads of Central Park and 5th Avenue, this internationally renowned Manhattan hotel is steps away from world class shopping.…"
  },
  "review_summary": {
    "overall_score": 8.6,
    "review_count": 508,
    "score_cleanliness": 9.1,
    "score_comfort": 9.4,
    "score_facilities": 8.7,
    "score_free_wifi": 8.6,
    "score_location": 9.8,
    "score_value_for_money": 7.6
  },
  "room_types": [
    { "name": "Plaza Room", "max_guests": 2, "room_type_id": "5895801" },
    { "name": "Edwardian Suite", "max_guests": 4, "room_type_id": "5895804" }
  ],
  "house_rules": {
    "checkin_from": "3:00 PM",
    "children_allowed": true
  },
  "location": {
    "latitude": 40.76443353778213,
    "longitude": -73.97424638271332
  }
}
```

Request and output of a live call to a Booking.com hotel page on Oct 20, 2026, trimmed for length. A field is returned when the page shows it.

## What data can you scrape from Booking.com?

A Booking.com property page comes back as a set of groups: the property, its review scores, its rooms, its rules and its location. These are the fields teams use most, with the path where each lives in the JSON.

| Field | What it holds | Example |
|---|---|---|
| `property.property_id` | Booking.com's numeric ID for the property, the key to join datasets | `58958` |
| `property.property_type` | Hotel, apartment, guest house and so on | `Hotel` |
| `property.description` | The property's own description from the page | `Located at the crossroads of Central Park and 5th Avenue…` |
| `property.cover_image_url` | The main photo at 1200x630 | `https://r-xx.bstatic.com/xdata/images/hotel/1200x630/…` |
| `property.canonical_url` | Clean URL of the property page | `https://www.booking.com/hotel/us/the-plaza.html` |
| `review_summary.overall_score` | Guest review score out of 10 | `8.6` |
| `review_summary.review_count` | Number of guest reviews behind the score | `508` |
| `review_summary.score_location` | Category score for location, out of 10 | `9.8` |
| `review_summary.score_value_for_money` | Category score for value, out of 10 | `7.6` |
| `review_summary.score_cleanliness` | Category score for cleanliness, with comfort, facilities and Wi-Fi next to it | `9.1` |
| `room_types[].name` | Each room type the property lists | `Deluxe King Room` |
| `room_types[].max_guests` | Guest capacity of that room type | `3` |
| `room_types[].room_type_id` | Booking.com's ID for the room type | `5895802` |
| `house_rules.checkin_from` | Earliest check-in time | `3:00 PM` |
| `house_rules.children_allowed` | Whether children are allowed | `true` |
| `location.latitude`, `location.longitude` | The property's coordinates | `40.7644, -73.9742` |
| `fine_print.notes` | The property's fine print | `Please note that photography is restricted at the property.` |

## How to scrape Booking.com with Zenrows

1. **Create a free Zenrows account** and copy your API key from the dashboard.
2. **Pick the property URL.** Booking.com hotel pages follow `https://www.booking.com/hotel/<country>/<name>.html`, such as `/hotel/us/the-plaza.html`. Strip the `aid`, `label` and `sid` tracking parameters.
3. **Send it with the default configuration**: Adaptive Stealth Mode to open the page and Extract to return the fields. Add a country when you want the page as a visitor from that market sees it.
4. **Read `parsed`** from the response. To keep only some groups or fields, list them with their paths and the response returns just those.
5. **Send your full property list to Batch** once one URL returns what you need.

```python Python
# pip install requests
import requests

params = {
    "apikey": "YOUR_ZENROWS_API_KEY",
    "url": "https://www.booking.com/hotel/us/the-plaza.html",
    "mode": "auto",          # Adaptive Stealth Mode
    "extract": "auto",       # structured JSON
}
response = requests.get("https://api.zenrows.com/v1/", params=params, timeout=180)
response.raise_for_status()

data = response.json()["parsed"]
scores = data["review_summary"]
print(data["property"]["property_id"], scores["overall_score"], scores["review_count"])
for room in data["room_types"]:
    print(room["room_type_id"], room["name"], "sleeps", room["max_guests"])
```

```javascript Node.js
// Node 18+ (built-in fetch)
const params = new URLSearchParams({
  apikey: "YOUR_ZENROWS_API_KEY",
  url: "https://www.booking.com/hotel/us/the-plaza.html",
  mode: "auto",
  extract: "auto",
});

const response = await fetch(`https://api.zenrows.com/v1/?${params}`, {
  signal: AbortSignal.timeout(180_000),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);

const { parsed } = await response.json();
const { overall_score, review_count, score_location, score_value_for_money } = parsed.review_summary;
console.log({ overall_score, review_count, score_location, score_value_for_money });
console.log(parsed.room_types.length, "room types");
```

```bash cURL
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.booking.com%2Fhotel%2Fus%2Fthe-plaza.html&mode=auto&extract=auto"

# Only the fields you need
curl "https://api.zenrows.com/v1/?apikey=YOUR_ZENROWS_API_KEY&url=https%3A%2F%2Fwww.booking.com%2Fhotel%2Fus%2Fthe-plaza.html&mode=auto&extract=auto&extract_fields=property.property_id%2Creview_summary.overall_score%2Creview_summary.review_count%2Croom_types.name"
```

```python Python SDK
# pip install zenrows
from zenrows import ZenRowsClient

client = ZenRowsClient("YOUR_ZENROWS_API_KEY")
for url in (
    "https://www.booking.com/hotel/us/the-plaza.html",
    "https://www.booking.com/hotel/gb/the-savoy.html",
):
    response = client.get(url, params={"mode": "auto", "extract": "auto"})
    s = response.json()["parsed"]["review_summary"]
    print(url, s["overall_score"], s["score_location"], s["score_value_for_money"])
```

## Input

The scraper takes one Booking.com URL per request, plus the options below. A Batch job applies the same parameters to every task, so the input for a thousand hotels is a list of property URLs with these settings.

| Parameter | Type | Default | Description |
|---|---|---|---|
| `url` | string | required | A Booking.com property page (`/hotel/<country>/<name>.html`), with or without stay dates in the query |
| `mode` | string | `auto` | Adaptive Stealth Mode: starts with the lightest setup and adds rendering and protected-site handling only when Booking.com needs them |
| `extract` | string | `auto` | Returns the page's fields as JSON in `parsed`, next to the raw `html` |
| `extract_fields` | string | all fields | Comma-separated paths to keep, such as `review_summary.overall_score,room_types.name` |
| `proxy_country` | string | any | Two-letter country code. Booking.com sets currency and what it shows by the visitor's location, so pick the market you report on |
| `wait_for` | string | none | A CSS selector to wait for before the page is read |
| `session_id` | integer | none | Keep the same session for up to 10 minutes across several pages of one property |

```json Batch input
{
  "type": "regular",
  "status": "closed",
  "zenrows_params": {
    "mode": "auto",
    "extract": "auto"
  },
  "tasks": [
    { "url": "https://www.booking.com/hotel/us/the-plaza.html", "external_id": "58958" },
    { "url": "https://www.booking.com/hotel/gb/the-savoy.html", "external_id": "the-savoy-london" }
  ]
}
```

## Output

Every response is JSON with two keys: `html`, the page as Booking.com served it, and `parsed`, the structured record. A property page returns the groups below. The sample keeps more of the same live response: every category score, more rooms and the rules.

```json Property page
{
  "property": {
    "property_id": "58958",
    "property_type": "Hotel",
    "canonical_url": "https://www.booking.com/hotel/us/the-plaza.html",
    "cover_image_url": "https://r-xx.bstatic.com/xdata/images/hotel/1200x630/914954799.jpg?k=162744612c…&o=",
    "description": "Located at the crossroads of Central Park and 5th Avenue, this internationally renowned Manhattan hotel is steps away from world class shopping.\nThe luxurious and spacious rooms at The Plaza boast modern bathrooms with 24-karat gold-plated fixtures and separate rain showers.…"
  },
  "review_summary": {
    "overall_score": 8.6,
    "review_count": 508,
    "score_cleanliness": 9.1,
    "score_comfort": 9.4,
    "score_facilities": 8.7,
    "score_free_wifi": 8.6,
    "score_location": 9.8,
    "score_value_for_money": 7.6
  },
  "room_types": [
    { "name": "Plaza Room", "max_guests": 2, "room_type_id": "5895801" },
    { "name": "Deluxe King Room", "max_guests": 3, "room_type_id": "5895802" },
    { "name": "Grand Penthouse Two Bedroom Terrace Suite with Central Park View", "max_guests": 4, "room_type_id": "5895836" },
    { "name": "Grand Luxe Family Queen Room with Sofa Bed", "max_guests": 6, "room_type_id": "5895837" }
  ],
  "house_rules": {
    "checkin_from": "3:00 PM",
    "children_allowed": true
  },
  "fine_print": {
    "notes": "Please note that photography is restricted at the property."
  },
  "location": {
    "latitude": 40.76443353778213,
    "longitude": -73.97424638271332
  }
}
```

The live page listed 17 room types; the sample keeps four. Need a spreadsheet? Load `parsed["room_types"]` or the scores into pandas with `pd.json_normalize(...)` and write CSV or Excel. Need the page for an LLM? Ask for Markdown instead of JSON.

## Scrape Booking.com from your coding agent

Claude Code, Cursor, Codex and any MCP client can scrape Booking.com from a prompt.

The agent sends the same Fetch and Extract request a developer would, so it reads the property record above and can compare hotels for you. Connect the Zenrows MCP server once, or install the CLI and let the agent run it in the terminal.

```bash Connect the MCP server (Claude Code)
claude mcp add zenrows -e ZENROWS_API_KEY=YOUR_ZENROWS_API_KEY -- npx -y @zenrows/mcp
```

```json MCP config (Cursor, Claude Desktop, Windsurf)
{
  "mcpServers": {
    "zenrows": {
      "command": "npx",
      "args": ["-y", "@zenrows/mcp"],
      "env": { "ZENROWS_API_KEY": "YOUR_ZENROWS_API_KEY" }
    }
  }
}
```

```bash Or run the CLI
npx -y @zenrows/cli init
zenrows extract "https://www.booking.com/hotel/us/the-plaza.html"
```

```text Then ask your agent
Use Zenrows to scrape these Booking.com hotels and compare them in a table
with the overall score, review count, location score, value for money
score and the number of room types:
https://www.booking.com/hotel/us/the-plaza.html
https://www.booking.com/hotel/gb/the-savoy.html
```

## Scrape Booking.com at scale with Batch and Crawl

**Batch** runs a list of Booking.com property URLs as one job, in parallel, with your own ID on each result. Use the property ID or your internal hotel code as the ID, and rerun the job weekly to track review scores and room offers across a competitive set.

**Crawl** follows links from a Booking.com page and returns every page it reaches. Start it on a city page, keep the links that contain `/hotel/`, and it collects the property pages listed there. Send that list to Batch with Extract.

```bash Batch (cURL)
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "regular",
    "status": "closed",
    "zenrows_params": { "mode": "auto", "extract": "auto" },
    "tasks": [
      { "url": "https://www.booking.com/hotel/us/the-plaza.html", "external_id": "58958" },
      { "url": "https://www.booking.com/hotel/gb/the-savoy.html", "external_id": "the-savoy-london" }
    ]
  }'

# Read the results when the job finishes
curl "https://async.api.zenrows.com/v1/jobs/JOB_ID/results?status=successful" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY"
```

```bash Batch (CLI)
# hotels.jsonl: one {"url": "...", "external_id": "...", "extract": "auto"} per line
zenrows batch create hotels.jsonl --wait
zenrows batch results <job-id> --out booking-hotels.jsonl
```

```bash Crawl (cURL)
curl -X POST "https://api.zenrows.com/v1/crawls" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.booking.com/city/gb/london.html",
    "depth": 1,
    "max_pages": 200,
    "include_patterns": ["/hotel/gb/"]
  }'
```

**Scheduled jobs** run the same Batch job on a timetable, on Zenrows' side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can tell your app when a run finishes, and you can pause or resume the schedule at any time, with no cron server to keep alive.

```bash Scheduled job (cURL)
# Runs every day on Zenrows' side; each run keeps its own results
curl -X POST "https://async.api.zenrows.com/v1/jobs" \
  -H "X-API-Key: YOUR_ZENROWS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "type": "scheduled",
      "status": "closed",
      "schedule": {
        "rate": {
          "every": 1,
          "unit": "day"
        }
      },
      "zenrows_params": {
        "mode": "auto",
        "extract": "auto"
      },
      "tasks": [
        {
          "url": "https://www.booking.com/hotel/us/the-plaza.html",
          "external_id": "booking"
        }
      ]
    }'

# Or at set times: "schedule": { "calendar": { "times_of_day": ["09:00"],
#   "cadence": { "weekly": { "days": ["mon", "thu"] } } }, "timezone": "Europe/Madrid" }
```

## What teams do with Booking.com data

| Use case | Data they pull | Who runs it |
|---|---|---|
| Competitive set benchmarking | Overall and category review scores, review count, room types for nearby hotels | Hotel revenue and commercial teams |
| Reputation tracking | Score changes per category over time, week by week | Hotel groups and hospitality consultants |
| Travel content and listings | Description, cover image, coordinates, rules and rooms per property | Travel sites, OTAs and metasearch teams |
| Market and investment research | Property type, room inventory and scores across a city or region | Hospitality investors and analysts |
| Location intelligence | Coordinates and location score joined with your own map data | Data teams and urban researchers |
| AI travel assistants | The full property record, or the page as Markdown | AI and product teams |

## Tips for scraping Booking.com

- **Use the clean property URL.** `https://www.booking.com/hotel/us/the-plaza.html` returns the same property as the long link from a search, without the `aid`, `label` and `sid` parameters that change on every visit.
- **Pick the language with the file name.** Booking.com serves languages through the URL, as in `the-savoy.de.html` or `the-savoy.en-gb.html`. Keep one language per dataset so descriptions and room names compare.
- **Set the market with the country.** Currency and what Booking.com shows depend on where the visitor is. Request each property from the country you report on, and keep it the same between runs.
- **Add stay dates for a specific stay.** Booking.com reads `checkin`, `checkout` and `group_adults` from the query string, so a URL with dates opens the property for that stay.
- **Key rows on `property_id`.** Hotel names and URLs can change; the numeric property ID does not. Use it as the `external_id` in Batch.
- **Read scores as out of 10.** `overall_score` and every `score_*` field use Booking.com's 10-point scale, with the review count behind them in `review_count`.

## Frequently asked questions

### Is it legal to scrape Booking.com?

Collecting publicly available property data from Booking.com, such as descriptions, review scores and room types shown to every visitor, is common practice for market research. Guest reviews can include names and other personal data, which laws such as the GDPR and the CCPA protect, so collect only what you have a legitimate reason to use. Check Booking.com's terms for your use case and ask your lawyer if you are unsure.

### Is there an official Booking.com API?

Booking.com has APIs for partners. The Demand API serves approved affiliate partners that show and sell Booking.com stays, and the Connectivity APIs let properties and channel managers manage their own rates, availability and reservations. Both need an approved partnership, and neither returns any competitor's property page on demand, which is why teams use a scraper for market data.

### What Booking.com pages can I scrape?

Property pages at booking.com/hotel/<country>/<name>.html , in any language and with or without stay dates. City and district pages work as start points for Crawl to find property URLs.

### How do I scrape Booking.com with Python?

Send a GET request to https://api.zenrows.com/v1/ with your API key, the Booking.com property URL, Adaptive Stealth Mode and Extract turned on, as in the Python example above. The response's parsed key holds the property as a Python dictionary. The zenrows package on PyPI wraps the same request.

### Can I scrape Booking.com review scores?

Yes. Each property page returns the overall score, the number of reviews and the category scores for cleanliness, comfort, facilities, free Wi-Fi, location and value for money. Run your competitive set in Batch every week to see how the scores move. For reviews on another travel site, see the Tripadvisor scraper .

### How many Booking.com hotels can I scrape?

Send one URL per request, or a whole list as a Batch job that runs the URLs in parallel and keeps your own ID on each result. One Batch job accepts more than 10,000 URLs, sent inline or as a CSV file.

### Can AI agents scrape Booking.com with Zenrows?

Yes. Connect the Zenrows MCP server to Claude, Cursor, Codex or any MCP client, or give your agent the Zenrows CLI. Ask for the hotels you want in plain language and the agent calls Fetch and Extract for you.

### Can I scrape Booking.com on a schedule?

Yes. Create a scheduled Batch job with your Booking.com URLs and the same settings as a single request, and Zenrows runs it on its side: every few hours, once a day, at set times on chosen days, or once at a future date. Each run keeps its own results, a webhook can notify your app when a run finishes, and the schedule can be paused or resumed at any time.

### Which integrations work with the Booking.com scraper?

Zenrows works with n8n, Make, Zapier, Clay, Dify, LangChain, LlamaIndex, CrewAI and Mastra, plus the Python, Node.js and Go SDKs and any HTTP client. Send scores and rooms to Google Sheets, a database or a BI tool from the workflow tool you already use. See the integrations page for the full list.

### What format does the data come in?

JSON by default, with the structured record in parsed and the original page in html . You can also ask for the page as Markdown or plain text, which is what most LLM and RAG pipelines want.

All scrapers: https://www.zenrows.com/scrape. Start free: https://app.zenrows.com/register. Docs: https://docs.zenrows.com
