# Booking.com Hotel Scraper - Ratings, Review Counts & Prices (`memo23/booking-scraper`) Actor

Scrape Booking.com hotels by destination, or paste hotel URLs directly. Get the overall guest rating, total review count, star rating, full address, GPS coordinates, price per night and room type. One clean row per hotel. Fast, HTTP-only, no browser. JSON, CSV or Excel.

- **URL**: https://apify.com/memo23/booking-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Travel, AI, Agents
- **Stats:** 29 total users, 5 monthly users, 93.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 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.
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

## Booking.com Scraper 🏨

Scrape **Booking.com** hotels and accommodations by destination — prices, ratings, guest review scores, coordinates, room types, photos, cancellation policies, and direct booking URLs. Fast, HTTP-only, and structured JSON/CSV/Excel out.

![Booking.com Scraper](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-booking.png)

### Why use Booking.com Scraper?

- **Search any destination, or paste hotel URLs** — city, region, country, a hotel name, or a list of direct Booking.com hotel page URLs.
- **URLs resolve exactly, even after a rename** — a hotel's URL slug and its listed name are independent (`/hotel/tc/the-alexandra` is listed as "Alexandra Resort - All-Inclusive"). Each URL is read from the property's own page, so renamed hotels come back rather than going missing.
- **Rich per-hotel data** — name, star rating, guest review score & count, total & per-night price, room type, bed/bathroom counts, GPS coordinates, full address, photo, and the direct Booking.com URL.
- **Full control** — set check-in/check-out dates, guests, rooms, currency, language, sort order, price range, star filters, and property type.
- **Unlimited results** — paginate through every matching property, not just the first page.
- **No login, no browser** — talks directly to Booking's data API, so runs are fast and cheap.
- **Runs on any plan** — the standard Apify proxy is enough, no residential subscription required.
- **Pay only for what you scrape** — pay-per-result pricing with volume discounts, no monthly rental.

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

| Field | Type | Description |
|-------|------|-------------|
| name | string | Hotel or property name |
| hotelId | number | Booking.com internal hotel ID |
| ufi | number | Booking.com destination (city) ID |
| url | string | Direct Booking.com hotel page URL |
| propertyType | number | Accommodation type ID (204 = Hotel, 201 = Apartment, …) |
| address | string | Street address |
| city | string | City |
| countryCode | string | ISO country code |
| latitude | number | GPS latitude |
| longitude | number | GPS longitude |
| starRating | number | Star rating (1–5) |
| reviewScore | number | Guest review score (0–10) |
| reviewScoreWord | string | Rating label (e.g. "Exceptional", "Very Good") |
| reviewCount | number | Total number of guest reviews |
| price | number | Total price for the stay (numeric) |
| priceFormatted | string | Total price, formatted with currency symbol |
| priceBeforeDiscount | number | Original price before discount, if any |
| currency | string | Currency code (USD, EUR, GBP, …) |
| roomType | string | Recommended room/unit type |
| bedrooms | number | Number of bedrooms |
| bathrooms | number | Number of bathrooms |
| beds | number | Total number of beds |
| freeCancellation | boolean | Whether free cancellation is available |
| noPrepayment | boolean | Whether no-prepayment is available |
| petsAllowed | boolean | Whether pets are allowed for free |
| mealPlan | string | Included meal plan text, if any |
| isSustainable | boolean | Whether the property has a sustainability certification |
| distanceFromCenter | string | Distance from city centre |
| photoUrl | string | Main hotel photo URL |
| description | string | Short property description, if available |
| checkin / checkout | string | The searched stay dates |
| scrapedAt | string | ISO 8601 timestamp of collection |

### Use cases

- **Rate & availability monitoring** — track competitor hotel prices across dates and markets.
- **Travel content & metasearch** — power a hotel directory, deals site, or comparison tool.
- **Market research** — analyse pricing, star ratings, and review scores across a destination.
- **Lead lists** — build accommodation-partner prospect lists with locations and contact-ready URLs.
- **Data science** — feed structured hotel data into pricing models and dashboards.

### How to scrape Booking.com hotels

You can work two ways, and they can be mixed in one run.

**By destination** — set **Destination** to a city, region, country, or hotel name (`London`, `Paris, France`, `The Savoy`), pick your **check-in** and **check-out** dates, set guests, rooms and any filters, then set **Max results** (0 = unlimited) and run.

**By hotel URL** — paste Booking.com hotel page URLs into **Start URLs** and run. You get one row per URL, each read from that property's own page, so the name, rating and review count are exact.

Download the results as JSON, CSV, Excel, HTML, or XML — one row per property.

### Input configuration

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| startUrls | array | — | Direct Booking.com hotel page URLs, e.g. `https://www.booking.com/hotel/gb/the-savoy.html`. One row per URL. Use this, `locationQuery`, or both. |
| resolveUrlsViaPage | boolean | true | Read each start URL's own page for its exact name, rating and review count. Leave this on — it is what makes renamed properties resolve. |
| locationQuery | string | — | City, region, country, or hotel name to search. Optional when you supply `startUrls`. |
| checkin | string | tomorrow | Check-in date, `YYYY-MM-DD`. |
| checkout | string | check-in + 2 days | Check-out date, `YYYY-MM-DD`. |
| adults | integer | 2 | Number of adult guests. |
| rooms | integer | 1 | Number of rooms. |
| children | integer | 0 | Number of children. |
| maxResults | integer | 100 | Max hotels to return. `0` = unlimited. |
| sortBy | enum | popularity | `popularity`, `price`, `review_score`, `class`, `distance`. |
| propertyType | enum | any | `hotels`, `apartments`, `hostels`, `guesthouses`, `villas`, `resorts`, `bnb`. |
| currency | string | USD | Currency code for prices (USD, EUR, GBP, …). |
| language | string | en-us | Language code (en-us, de, fr, es, it, …). |
| minPrice | integer | — | Minimum price-per-night filter. |
| maxPrice | integer | — | Maximum price-per-night filter. |
| starsFilter | string\[] | — | Star ratings to include, e.g. `["4","5"]`. |
| proxyConfiguration | object | Apify proxy | Proxy settings. The standard Apify proxy is the default and is enough; residential is supported but costs more and is not required. |

### Output sample

```json
{
  "name": "Sansi Pedralbes",
  "hotelId": 91017,
  "ufi": -372490,
  "url": "https://www.booking.com/hotel/es/sansipedralbes.html",
  "propertyType": 204,
  "address": "Avenida Pearson, 1-3",
  "city": "Barcelona",
  "countryCode": "es",
  "latitude": 41.3937882727419,
  "longitude": 2.1118788421154,
  "starRating": 4,
  "reviewScore": 9.7,
  "reviewScoreWord": "Exceptional",
  "reviewCount": 567,
  "price": 790.42,
  "priceFormatted": "€ 790",
  "currency": "EUR",
  "roomType": "Double Room",
  "bedrooms": 0,
  "bathrooms": 0,
  "beds": 2,
  "freeCancellation": true,
  "noPrepayment": true,
  "petsAllowed": false,
  "isSustainable": false,
  "distanceFromCenter": "4.9 km from downtown",
  "photoUrl": "https://cf.bstatic.com/xdata/images/hotel/square600/36537530.jpg",
  "checkin": "2026-09-10",
  "checkout": "2026-09-12",
  "scrapedAt": "2026-07-12T04:05:09.746Z"
}
```

### FAQ

**Do I need a Booking.com account or API key?**
No. The scraper pulls public search-results data directly — no login, cookies, or key required.

**Do I need residential proxies?**
No. The default Apify proxy is enough for both destination search and hotel pages, and it is what the Actor uses out of the box. Residential is supported if you prefer it, but it costs considerably more per run and buys you nothing here.

**A hotel URL returned nothing. Why?**
Almost always because the property has been delisted. A removed hotel redirects to a generic destination page with no property record left to read, so no scraper can recover it. If the hotel is still live on Booking and you get an empty result, send the URL via the Issues tab.

**The name in my output doesn't match the URL. Is that wrong?**
No, that is correct behaviour. A slug and a listed name are independent, and properties get renamed. `/hotel/tc/leeward-resort` is listed as "Blue Haven Resort", `/hotel/tc/bianca-sands-on-grace-bay` as "The Regent Grand". The Actor returns the name Booking currently shows.

**Why is `roomType` / `mealPlan` sometimes empty?**
Search-results pages expose a recommended room and a summary. Fields like full room lists, amenities, and reviews live on the individual hotel page — see *Additional services* below for a detail/reviews-focused run. Rows resolved from a start URL also have no price fields, because rates are per-stay and only exist in a dated search.

**Can I control the currency and language?**
Yes — set the `currency` (e.g. `EUR`, `GBP`) and `language` (e.g. `fr`, `de`) inputs.

**How many results can I get?**
Set `maxResults` to `0` for unlimited — the scraper paginates through every matching property for your search.

### Support

Found a bug or need a field added? Open an issue on the Actor's **Issues** tab and we'll take a look.

### Additional services

Need **individual hotel details** (full room matrix, amenities, all photos) or **guest reviews** at scale? Those are available as companion runs on the same fast, HTTP-only pipeline — get in touch via the Issues tab.

### Explore more scrapers

Check the Apify Store for more travel and accommodation data tools.

### 🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (actor: `memo23/booking-scraper`).

**Purpose:** Scrape Booking.com hotels by destination or by direct hotel URL — prices, review scores, coordinates, room types, cancellation policies, and booking URLs, one row per property.

**Minimal input (destination search):**

```json
{
  "locationQuery": "London",
  "adults": 2,
  "rooms": 1,
  "children": 0,
  "maxResults": 25,
  "sortBy": "popularity",
  "currency": "USD",
  "language": "en-us",
  "proxyConfiguration": { "useApifyProxy": true }
}
```

**Minimal input (specific hotels):**

```json
{
  "startUrls": [
    { "url": "https://www.booking.com/hotel/gb/the-savoy.html" },
    { "url": "https://www.booking.com/hotel/tc/the-alexandra.html" }
  ],
  "proxyConfiguration": { "useApifyProxy": true }
}
```

`checkin`/`checkout` default to tomorrow and +2 nights (set `YYYY-MM-DD` to override). Optional filters: `propertyType`, `minPrice`, `maxPrice`, `starsFilter`.

**Output:** one row per hotel — name, hotelId, ufi, url, propertyType, address, city, countryCode, latitude, longitude, starRating, reviewScore, reviewScoreWord, reviewCount, price, priceFormatted, priceBeforeDiscount, currency, roomType, bedrooms, bathrooms, beds, freeCancellation, noPrepayment, petsAllowed, mealPlan, isSustainable, distanceFromCenter, photoUrl, description, checkin, checkout, scrapedAt.

**Behaviors an agent should know:**

- Supply `locationQuery`, `startUrls`, or both. At least one is required.
- `startUrls` resolves each URL from the property's own page, so the returned `name` is the hotel's current listed name and may differ from the URL slug. That is correct: slugs and names are independent, and properties get renamed.
- A start URL that yields no row means the property is delisted, not that the run failed. Live hotels always resolve.
- Rows from `startUrls` carry no price fields — rates are per-stay and exist only in a dated search. Use `locationQuery` if you need pricing.
- `maxResults` caps hotels returned and billed from the search path; set 0 for unlimited.
- `currency` and `language` control regional pricing and result locale.
- Filter with `sortBy`, `propertyType`, `minPrice`, `maxPrice`, `starsFilter`.
- The default Apify proxy is sufficient. Residential is supported but unnecessary and more expensive.
- Search-results data only — full room matrix, amenities, and guest reviews live on hotel-detail pages (a separate run).
- Billing: pay per result — one charge per hotel row.

### ⚠️ Disclaimer

This Actor scrapes only publicly available information from Booking.com. It does not log in, bypass access controls, or collect personal data. You are responsible for how you use the extracted data, including compliance with Booking.com's Terms of Service, applicable laws (such as GDPR), and any copyright or database rights. Use the data lawfully and ethically.

### SEO Keywords

booking.com scraper, booking scraper, hotel scraper, booking.com api, scrape booking.com, hotel price scraper, accommodation data, hotel data extraction, booking.com data, travel data scraper, hotel rates api, hotel availability scraper, booking hotels export, hotel review scraper, accommodation prices, hotel listings scraper

# Actor input Schema

## `startUrls` (type: `array`):

Direct Booking.com hotel page URLs, e.g. https://www.booking.com/hotel/gb/the-savoy.html. Each URL is resolved to one hotel row with its overall guest score, review count, star rating, address and coordinates. Use this instead of (or alongside) a destination query when you already know the exact properties you want.

## `resolveUrlsViaPage` (type: `boolean`):

Read each start URL's own page to get its exact name, guest rating and review count. A hotel's URL slug and its listed name are independent (booking.com/hotel/tc/the-alexandra is listed as 'Alexandra Resort - All-Inclusive'), so resolving a URL by searching its name misses renamed properties — on a real 41-hotel list, 13 of them. Turn this off to use name-search resolution only, which is faster but drops those.

## `locationQuery` (type: `string`):

City, region, country, or hotel name to search (e.g. 'London', 'Paris, France', 'The Savoy London'). Optional if you supply Start URLs.

## `checkin` (type: `string`):

Check-in date in YYYY-MM-DD format. Defaults to tomorrow.

## `checkout` (type: `string`):

Check-out date in YYYY-MM-DD format. Defaults to 2 days after check-in.

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

Number of adult guests.

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

Number of rooms.

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

Number of children.

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

Maximum number of hotels to return. Set to 0 for unlimited (all available results).

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

Sort order for search results.

## `propertyType` (type: `string`):

Restrict results to a single accommodation type.

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

Currency code for prices (e.g. USD, EUR, GBP).

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

Language code for results (e.g. en-us, de, fr, es, it).

## `minPrice` (type: `integer`):

Minimum price per night filter (in the selected currency).

## `maxPrice` (type: `integer`):

Maximum price per night filter (in the selected currency).

## `starsFilter` (type: `array`):

Filter by hotel star rating. Enter star values (1-5) to include.

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

Proxy settings. The default Apify proxy is enough: Booking's data API is not geo-gated and hotel pages load fine from a datacenter exit. Residential is supported if you prefer it, but it costs considerably more per run and is not required.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.booking.com/hotel/gb/the-savoy.html"
    }
  ],
  "resolveUrlsViaPage": true,
  "locationQuery": "London",
  "adults": 2,
  "rooms": 1,
  "children": 0,
  "maxResults": 100,
  "sortBy": "popularity",
  "propertyType": "",
  "currency": "USD",
  "language": "en-us",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "startUrls": [
        {
            "url": "https://www.booking.com/hotel/gb/the-savoy.html"
        }
    ],
    "locationQuery": "London",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/booking-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 = {
    "startUrls": [{ "url": "https://www.booking.com/hotel/gb/the-savoy.html" }],
    "locationQuery": "London",
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/booking-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 '{
  "startUrls": [
    {
      "url": "https://www.booking.com/hotel/gb/the-savoy.html"
    }
  ],
  "locationQuery": "London",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call memo23/booking-scraper --silent --output-dataset

```

## MCP server setup

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