# Booking.com Hotel Prices (`superslowsloth/booking-hotels`) Actor

One search, one flat table: hotel name, id, address, lowest all-in price for the stay, star rating, review score and count, and the booking URL.

- **URL**: https://apify.com/superslowsloth/booking-hotels.md
- **Developed by:** [Superslow Sloth](https://apify.com/superslowsloth) (community)
- **Categories:** Travel, AI, Automation
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.40 / 1,000 hotel scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Prices

One search in, one flat table out. Give it a destination and a date; it returns
the hotels Booking.com would show you, each with its **lowest all-in price for
the whole stay** in the currency you asked for, its star rating, its guest
review score and review count, and the URL of the property page.

Built to be called by an agent or a script: small input, small output, one row
per hotel, no nested objects, no HTML.

### Input

| field | default | meaning |
|---|---|---|
| `destination` | *required* | City, region, district or landmark: `Bangkok`, `Osaka`, `Bali`, `Times Square` |
| `checkIn` | 30 days out | Check-in date, `YYYY-MM-DD` |
| `nights` | `1` | Length of stay; check-out is derived from it |
| `adults` | `2` | Adult guests the prices are quoted for |
| `rooms` | `1` | Rooms requested |
| `children`, `childAges` | `0`, `[]` | Children, and one age per child |
| `currency` | `USD` | Three-letter code the prices are quoted in |
| `maxResults` | `50` | Stop after this many hotels have been **delivered** |
| `includeUnpriced` | `false` | Also emit properties with nothing bookable, at a `null` price |

### Output

One item per hotel:

| field | meaning |
|---|---|
| `hotel_id` | Booking's numeric property id, stable across searches |
| `name` | Property name as Booking displays it |
| `url` | Property page on booking.com |
| `area` | Street address as Booking prints it on the card |
| `city` | City as Booking classifies the property — see the note below |
| `country_code` | Two-letter country code, e.g. `th` |
| `star_rating` | Official star rating, 1-5 |
| `review_score` | Booking guest score **out of 10** |
| `review_count` | Number of guest reviews behind that score |
| `total_price` | Lowest all-in price for the **whole stay**, not per night |
| `currency` | Currency `total_price` is quoted in |
| `check_in`, `check_out`, `nights`, `adults`, `rooms` | The search the prices belong to |
| `requested_destination` | The destination string you sent, echoed back |
| `resolved_destination`, `resolved_country_code`, `resolved_ufi` | The place Booking actually searched |
| `destination_matched` | `false` when Booking searched somewhere other than what you asked for |

#### `total_price` is the whole stay

Booking's search cards quote a total for the dates, so that is what this
returns. It is **not** divided by `nights` to make a nightly rate, because a
stay whose rate changes from night to night has no single nightly price and
inventing one would be wrong for exactly the bookings people care about. Divide
it yourself if an approximate nightly figure is what you need.

#### Always check `destination_matched`

Booking resolves free text on its own side and answers nearly any string with
*some* place, so a typo or a bad input can produce a complete, successful,
**charged** run about somewhere else. This actor cannot refuse that outright
without also refusing legitimate variants — Booking files "Koh Samui" as "Ko
Samui" and answers a city name with the surrounding region — so instead **every
row says what you asked for and what it got**. When `destination_matched` is
`false`, read `resolved_destination` before trusting the prices.

A destination Booking cannot place at all is not silently swapped for another:
the run ends with no items and says so.

#### `city` is not reliably in English

Measured 2026-08-25: the same Bangkok search answered `Bangkok` on one request
and `กรุงเทพมหานคร` minutes later, with an English language setting on both.
Booking localises this field to the property's own language some of the time,
and no request-side setting changes it. It is passed through exactly as sent
rather than transliterated, because a guessed translation would put an invented
value in a column you might join on. **`resolved_destination` is consistently
in the requested language** — group by that.

#### Nulls are never zeros

A property with nothing bookable for those dates has `total_price: null` and
`currency: null`, and by default is not emitted at all. A property nobody has
reviewed yet has `review_score: null` and `review_count: null`. None of these
ever come back as `0`, because a `0` would read as a measurement — "free", or
"rated nought" — which is the one thing it never means.

### Use a residential proxy

Booking.com sits behind an AWS WAF. A challenged request comes back as
`HTTP 202` carrying a JavaScript proof-of-work instead of data, and no HTTP
client can solve it — only a different exit address clears it. The input's
default proxy configuration is `RESIDENTIAL`, and it should be left that way.
The actor rotates its exit address before every retry, which is the thing that
actually clears a block; re-asking from the blocked address never does.

### What it costs

Pay per event: a small charge when the run starts, and one charge per hotel
row delivered. Properties skipped for having no price are not charged for, and
a hotel that appears on two pages is charged once. A run rejected for a
malformed date is not charged the start event at all.

# Actor input Schema

## `destination` (type: `string`):

A city, region, district or landmark such as Bangkok, Osaka, Bali or Times Square. Booking resolves the text on its own side and answers almost any string with some place, so a typo can return a real but unrelated destination. Every output row carries requested\_destination, resolved\_destination and destination\_matched so you can tell the difference.

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

Check-in date as YYYY-MM-DD. Defaults to 30 days from the day the run starts.

## `nights` (type: `integer`):

Length of stay in nights. The check-out date is derived from it.

## `adults` (type: `integer`):

Number of adult guests. Prices are quoted for this occupancy.

## `rooms` (type: `integer`):

Number of rooms requested.

## `children` (type: `integer`):

Number of children. Leave at 0 for an adults-only search.

## `childAges` (type: `array`):

One age per child. Booking prices some rooms differently by child age; leave empty if you set no children.

## `currency` (type: `string`):

Three-letter currency code the prices are quoted in, e.g. USD, THB, JPY, EUR, GBP. Worth setting: without it Booking picks a currency from the exit address, and a rotating proxy would put more than one currency in the same dataset column.

## `maxResults` (type: `integer`):

Stop after this many hotels have been delivered. Properties with no price for those dates do not count against it. Booking serves 25 per page, so a lower number usually costs fewer requests as well as fewer charged items.

## `includeUnpriced` (type: `boolean`):

Off by default. When on, properties with nothing bookable for those dates are emitted too, with a null price - they are never given a price of 0.

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

Required in practice, and residential is what works. Booking.com sits behind an AWS WAF that challenges addresses it does not like; a challenged request comes back as HTTP 202 with no data, and only a different exit address clears it.

## Actor input object example

```json
{
  "destination": "Bangkok",
  "nights": 1,
  "adults": 2,
  "rooms": 1,
  "children": 0,
  "childAges": [],
  "currency": "USD",
  "maxResults": 50,
  "includeUnpriced": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `hotels` (type: `string`):

No description

# 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 = {
    "destination": "Bangkok",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/booking-hotels").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 = {
    "destination": "Bangkok",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/booking-hotels").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 '{
  "destination": "Bangkok",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call superslowsloth/booking-hotels --silent --output-dataset

```

## MCP server setup

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

```

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/u9MSwkV9mbaNEixrO/builds/hqNieSqOzmsPbMERo/openapi.json
