# Booking.com Hotel Scraper - Guest Score & Reviews (`thenetaji/booking-property-scraper`) Actor

Get any Booking.com property by its URL or slug: guest score with the full subscore breakdown, address, description, lead photo, and up to ten featured guest reviews. No Booking.com account needed.

- **URL**: https://apify.com/thenetaji/booking-property-scraper.md
- **Developed by:** [The Netaji](https://apify.com/thenetaji) (community)
- **Categories:** Travel, Real estate, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.10 / 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?

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 Scraper

The Actor retrieves one Booking.com property by its slug and returns a structured record: guest score with its full subscore breakdown, address, description, lead photo, and up to ten featured guest reviews. It accepts either the bare slug or a full Booking.com hotel URL; a pasted URL is reduced to the slug automatically.

### Accepted input

| Field | Type | Default | Description |
|---|---|---|---|
| `slug` | string | required | The property slug from its Booking.com URL: the part after `/hotel/<country>/` and before `.html`. A full `https://www.booking.com/hotel/us/...` URL is accepted too. |
| `country_code` | string | `us` | The two-letter country code from the same URL, e.g. the `us` in `/hotel/us/luma-san-francisco.html`. Part of the address, not a preference. |

```json
{
  "slug": "luma-san-francisco",
  "country_code": "us"
}
```

### Response fields

| Field | Contents |
|---|---|
| `slug` | The slug that was fetched, echoed back |
| `country_code` | The country code that was fetched, echoed back |
| `name` | The property name |
| `url` | The property's page on Booking.com |
| `description` | Booking's own description of the property |
| `image` | The property's lead photo |
| `price_range` | schema.org `priceRange`, frequently `null` |
| `address` | Structured postal address: `street_address`, `locality`, `region`, `postal_code`, `country` |
| `rating` | Guest score, out of ten |
| `rating_scale_max` | Top of the rating scale, always `10` |
| `review_count` | Exact total review count the score is computed over |
| `subscores` | The rating broken down by category (staff, cleanliness, comfort, location, facilities, value), each out of ten |
| `reviews` | Up to ten featured guest reviews, each with `author`, `country`, and `text` |
| `review_sample_size` | How many reviews are in `reviews` |
| `reviews_note` | What `reviews` is and is not |

```json
{
  "slug": "luma-san-francisco",
  "country_code": "us",
  "name": "LUMA Hotel San Francisco",
  "rating": 9.1,
  "rating_scale_max": 10,
  "review_count": 1019,
  "review_sample_size": 10
}
```

### Behaviour on an unknown property

A slug that does not exist for the given `country_code` is not treated as an error; Booking answers such a lookup with no data at all, and the run finishes with an empty dataset rather than failing. A slug looked up under the wrong country behaves the same way, since the country code is part of the address rather than a filter: `/hotel/fr/luma-san-francisco` is a different path from `/hotel/us/luma-san-francisco`, and one existing does not imply the other does.

### Frequently asked questions

**Why is `rating` a number like 9.1 rather than out of five?**
Booking's own guest score is out of ten. `rating_scale_max` states this on every response rather than leaving it to documentation, because Yelp and TripAdvisor scores in the same catalogue are out of five, and treating 9.1 as a five-point score would be wrong by a factor of two.

**Why does `reviews` only contain ten entries when `review_count` is in the thousands?**
`reviews` is the curated sample of featured reviews Booking renders into the property page itself, not the full review list. A property with 1,019 reviews still returns the same ten featured ones, and they are neither the most recent ten nor a random sample. The complete list is not reachable through this endpoint: Booking's fragment review endpoint answers 404, and the property page itself makes no further review request. `reviews_note` restates this on every response so an empty or short sample does not read as a failed fetch.

**Why is `price_range` usually empty?**
Booking prices a stay, not a hotel; a property page states no price band without specific dates attached. The Booking.com Search Scraper, with `checkin` and `checkout` set, returns real, dated prices per property.

**What happens if a run is interrupted partway through?**
The Actor produces exactly one row per run. A run resumed after being interrupted before that row reached the dataset fetches and saves it as normal. A run resumed after the row was already saved finishes immediately without repeating it.

### Related

[Booking.com Search Scraper](https://apify.com/thenetaji/booking-search-scraper) searches Booking.com by destination and returns every property found, with star rating, guest review score, coordinates, and, when `checkin`/`checkout` are set, real prices for the stay. Each result row carries the `slug` and `country_code` this Actor takes as input, so a search feeds directly into it once a specific property is of interest.

# Actor input Schema

## `slug` (type: `string`):

Paste the property's Booking.com page URL, e.g. https://www.booking.com/hotel/us/luma-san-francisco.html — the slug and country are read out of it for you. The bare slug ("luma-san-francisco") also works on its own.

## `country_code` (type: `string`):

The two-letter country code from the same URL, e.g. the "us" in /hotel/us/luma-san-francisco.html. Filled in for you when Property Slug is a full URL. Part of the address, not a preference — a slug looked up under the wrong country returns no property rather than an error.

## Actor input object example

```json
{
  "slug": "luma-san-francisco",
  "country_code": "us"
}
```

# Actor output Schema

## `dataset` (type: `string`):

All records scraped by this run

# 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 = {
    "slug": "luma-san-francisco",
    "country_code": "us"
};

// Run the Actor and wait for it to finish
const run = await client.actor("thenetaji/booking-property-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 = {
    "slug": "luma-san-francisco",
    "country_code": "us",
}

# Run the Actor and wait for it to finish
run = client.actor("thenetaji/booking-property-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 '{
  "slug": "luma-san-francisco",
  "country_code": "us"
}' |
apify call thenetaji/booking-property-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thenetaji/booking-property-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/JdtdOra1Osy0wC3YW/builds/vtHSWYyE7yhFuSe2E/openapi.json
