# Booking.com Hotel & Price Scraper (`bovi/booking-hotel-scraper`) Actor

Scrape Booking.com hotels from search — name, address, rating, reviews, nightly price, coordinates, image. Needs a browser-capable proxy (Apify Residential or Bright Data) due to Booking AWS WAF. Each record has parse\_confidence.

- **URL**: https://apify.com/bovi/booking-hotel-scraper.md
- **Developed by:** [Vitalii Bondarev](https://apify.com/bovi) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 4 total users, 3 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.18 / 1,000 hotel 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 — Price, Rating & Coords | from $2/1K

**For travel market researchers, hotel chains doing competitive pricing, and hospitality lead-gen agencies** that need Booking.com data at scale without managing browser infrastructure.

**$2.00 per 1,000 hotels (search card). Add $1.00/1k for hotel detail pages (`fetchHotelDetail=true`)** — full address, GPS coords, and Hotel JSON-LD. Only pay for what you pull. No Booking.com account required. Works in 40+ countries.

| Scraper | Price / 1k | Detail page? | Coords? | parse_confidence? |
|---|---|---|---|---|
| **This actor** | $2 base + $1 detail | Yes | Yes | Yes |
| Apify booking-scraper (official) | $3-5/1k | Partial | Sometimes | No |
| outscraper Booking | $5-10/1k | Yes | Yes | No |

Scrape Booking.com hotel search results into clean, structured JSON. For each hotel you get: name, address, city, country, star rating, review count, nightly price, currency, image URL, and GPS coordinates — every record stamped with `parse_confidence` for quality monitoring.

### Important: Managed Browser Included

Booking.com uses **AWS WAF with a JavaScript challenge page** that blocks all static HTTP requests (curl, requests, httpx). A browser-capable proxy is mandatory:

This actor uses a publisher-managed browser backend to clear the challenge. You do not need to bring your own Booking.com account or proxy for the default path.

`proxyConfiguration` is kept as a compatibility input, but the production data path is the managed browser backend.

### What You Get

```json
{
  "hotel_name": "Hotel Minerve",
  "address": "13 Rue des Ecoles, 75005 Paris, France",
  "city": "Paris",
  "country": "France",
  "rating": 8.6,
  "review_count": 1204,
  "price": 199.0,
  "currency": "USD",
  "url": "https://www.booking.com/hotel/fr/hotel-minerve.html",
  "image_url": "https://cf.bstatic.com/xdata/images/hotel/max500/...",
  "latitude": 48.8506,
  "longitude": 2.3524,
  "parse_confidence": 1.0,
  "warnings": []
}
````

### Input

| Field | Type | Description |
|---|---|---|
| `searchQueries` | string\[] | City / destination names (e.g. "Paris", "New York") |
| `hotelUrls` | string\[] | Direct Booking.com hotel page URLs |
| `checkIn` | string | YYYY-MM-DD. Defaults to 30 days from today |
| `checkOut` | string | YYYY-MM-DD. Defaults to checkIn + 1 night |
| `maxItems` | integer | Max hotels per query (default 5; quality-test prefill 1) |
| `proxyConfiguration` | object | Optional compatibility field; managed browser is used by default |
| `fetchHotelDetail` | boolean | Visit each hotel page for richer data (default false; slower) |
| `language` | string | UI language code (default "en") |
| `currency` | string | Price currency code (default "USD") |

### How It Works

1. Launches a managed remote Chromium browser.
2. Navigates to the Booking.com search results page and waits for JS to settle.
3. Parses hotel cards using structural `data-testid` anchors (not fragile CSS classes).
4. Optionally visits each hotel's detail page to extract Hotel JSON-LD for richer address/coords.
5. Merges card + detail into the flat output schema.

### parse\_confidence

Every record includes `parse_confidence` (0.0–1.0) and a `warnings` list. A score below 0.7 suggests the page structure may have changed. Common warnings:

- `price_missing` — price not found on the search card
- `no_hotel_jsonld` — Hotel JSON-LD not found on detail page (detail fetch degraded)
- `coords_missing` — coordinates unavailable

### Integrations

Built for travel market researchers and hotel chains pulling competitive pricing, ratings, and coordinates at scale — the JSON/dataset output drops into the tools you already run, no glue code:

- **n8n / Make / Zapier** — trigger a run or pipe every new dataset item into 500+ apps (Google Sheets, Airtable, Slack, HubSpot, your database) with no code: [n8n](https://docs.apify.com/platform/integrations/n8n), [Make](https://docs.apify.com/platform/integrations/make), [Zapier](https://docs.apify.com/platform/integrations/zapier).
- **Webhooks** — fire your own endpoint the moment a run finishes, to push results straight into your pipeline ([docs](https://docs.apify.com/platform/integrations/webhooks)).
- **MCP server** — expose this actor as a tool to Claude, Cursor, or any [MCP client](https://mcp.apify.com) so an AI agent can pull this data mid-conversation ([guide](https://blog.apify.com/how-to-use-mcp/)).
- **API & SDKs** — fetch the dataset as JSON, CSV, or Excel through the Apify REST API or the Python / JS SDKs.

See all [Apify integrations](https://apify.com/integrations).

### Legal Notice

This actor scrapes publicly accessible hotel listings on Booking.com as seen by an anonymous browser. Use it for market research, competitive pricing analysis, and travel planning. You are responsible for ensuring your use complies with Booking.com's Terms of Service and applicable data protection laws in your jurisdiction.

This actor is not affiliated with, endorsed by, or sponsored by Booking.com or its parent Booking Holdings Inc.

### Access Resistance

Booking.com's AWS WAF challenge has been active since 2024 and requires:

- Real browser (Chromium) with valid JS execution
- Residential or Scraping Browser proxy (datacenter IPs are blocked)
- Sufficient wait time for the WAF token to be generated

If you see `awswaf_challenge_202` in warnings, your proxy is insufficient.

### Performance & Cost

- \~25 hotels per search-results page
- With `fetchHotelDetail=true`: 1 extra browser page load per hotel (search + detail enrichment)
- With `fetchHotelDetail=false`: 1 page load per 25 hotels (search card data only)
- Managed-browser bandwidth: ~1–2 MB per search page, ~1 MB per hotel detail page with media blocked.
- The default input is optimized to finish automated quality checks within 5 minutes and return at least one hotel.

### parse\_confidence trust score

Every record includes `parse_confidence` (0.0–1.0) and a `warnings` list. A score below 0.7 suggests the page structure may have changed — you get a loud signal instead of silent data corruption.

### Use with AI agents (MCP)

This actor is available as an MCP tool for Claude, GPT-4o, or any MCP-compatible agent.

Config: https://mcp.apify.com/?tools=bovi/booking-hotel-scraper

# Actor input Schema

## `searchQueries` (type: `array`):

One or more city or destination names to search on Booking.com (e.g. 'Paris', 'New York', 'Tokyo'). Each query fetches up to maxItems hotels from the search results page.

## `hotelUrls` (type: `array`):

Direct Booking.com hotel page URLs to scrape individually (e.g. https://www.booking.com/hotel/fr/...).

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

Check-in date in YYYY-MM-DD format. Required for pricing. Defaults to 30 days from today if omitted.

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

Check-out date in YYYY-MM-DD format. Must be after checkIn. Defaults to checkIn + 1 night.

## `maxItems` (type: `integer`):

Maximum number of hotels to extract per search query. Booking.com shows ~25 hotels per page. The default is intentionally small so the prefilled quality-test run finishes quickly; raise this for larger pulls.

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

Optional compatibility field. This actor uses the publisher-managed browser backend to clear Booking.com's AWS WAF; buyer proxy settings are not required for the default path.

## `fetchHotelDetail` (type: `boolean`):

If enabled, visits each hotel's detail page to extract structured Hotel JSON-LD (richer address, coordinates, image). This is much slower because it adds one browser navigation per hotel. Disabled by default for speed and quality-test reliability.

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

Language code for Booking.com UI (e.g. en, de, fr). Affects displayed text; prices are always in the site currency.

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

Three-letter currency code for displayed prices (e.g. USD, EUR, GBP). Booking.com may redirect to local currency.

## Actor input object example

```json
{
  "searchQueries": [
    "Paris"
  ],
  "maxItems": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "fetchHotelDetail": false,
  "language": "en",
  "currency": "USD"
}
```

# Actor output Schema

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

Dataset containing Booking Hotel Scraper records (hotel\_name, city, country, rating, review\_count, price, currency, latitude, longitude, parse\_confidence, warnings, url).

# 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 = {
    "searchQueries": [
        "Paris"
    ],
    "maxItems": 1,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    },
    "fetchHotelDetail": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("bovi/booking-hotel-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 = {
    "searchQueries": ["Paris"],
    "maxItems": 1,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
    "fetchHotelDetail": False,
}

# Run the Actor and wait for it to finish
run = client.actor("bovi/booking-hotel-scraper").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 '{
  "searchQueries": [
    "Paris"
  ],
  "maxItems": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "fetchHotelDetail": false
}' |
apify call bovi/booking-hotel-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Booking.com Hotel & Price Scraper",
        "description": "Scrape Booking.com hotels from search — name, address, rating, reviews, nightly price, coordinates, image. Needs a browser-capable proxy (Apify Residential or Bright Data) due to Booking AWS WAF. Each record has parse_confidence.",
        "version": "0.1",
        "x-build-id": "i4PlDmUN03epsTBhv"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/bovi~booking-hotel-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-bovi-booking-hotel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/bovi~booking-hotel-scraper/runs": {
            "post": {
                "operationId": "runs-sync-bovi-booking-hotel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/bovi~booking-hotel-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-bovi-booking-hotel-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "searchQueries": {
                        "title": "Search queries (cities / destinations)",
                        "type": "array",
                        "description": "One or more city or destination names to search on Booking.com (e.g. 'Paris', 'New York', 'Tokyo'). Each query fetches up to maxItems hotels from the search results page.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "hotelUrls": {
                        "title": "Hotel page URLs",
                        "type": "array",
                        "description": "Direct Booking.com hotel page URLs to scrape individually (e.g. https://www.booking.com/hotel/fr/...).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "checkIn": {
                        "title": "Check-in date",
                        "type": "string",
                        "description": "Check-in date in YYYY-MM-DD format. Required for pricing. Defaults to 30 days from today if omitted."
                    },
                    "checkOut": {
                        "title": "Check-out date",
                        "type": "string",
                        "description": "Check-out date in YYYY-MM-DD format. Must be after checkIn. Defaults to checkIn + 1 night."
                    },
                    "maxItems": {
                        "title": "Max hotels per query",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Maximum number of hotels to extract per search query. Booking.com shows ~25 hotels per page. The default is intentionally small so the prefilled quality-test run finishes quickly; raise this for larger pulls.",
                        "default": 5
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Optional compatibility field. This actor uses the publisher-managed browser backend to clear Booking.com's AWS WAF; buyer proxy settings are not required for the default path."
                    },
                    "fetchHotelDetail": {
                        "title": "Fetch hotel detail page",
                        "type": "boolean",
                        "description": "If enabled, visits each hotel's detail page to extract structured Hotel JSON-LD (richer address, coordinates, image). This is much slower because it adds one browser navigation per hotel. Disabled by default for speed and quality-test reliability.",
                        "default": false
                    },
                    "language": {
                        "title": "Language",
                        "type": "string",
                        "description": "Language code for Booking.com UI (e.g. en, de, fr). Affects displayed text; prices are always in the site currency.",
                        "default": "en"
                    },
                    "currency": {
                        "title": "Currency",
                        "type": "string",
                        "description": "Three-letter currency code for displayed prices (e.g. USD, EUR, GBP). Booking.com may redirect to local currency.",
                        "default": "USD"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
