# Booking.com Hotels & Prices Scraper (`barefoot_grade/booking-hotels-scraper`) Actor

Search Booking.com by destination, dates and guests. Each property is one row with its price for the stay, currency, taxes and fees, room offer, review score and count, stars, address and map coordinates. Optionally add every room type with its price. Pages through all results up to your limit.

- **URL**: https://apify.com/barefoot_grade/booking-hotels-scraper.md
- **Developed by:** [Philip Kirkbride](https://apify.com/barefoot_grade) (community)
- **Categories:** Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 hotels

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?

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 Hotels & Prices Scraper

Search Booking.com the way a traveller does: type a destination, pick your dates and guests, and get every matching property as one clean row. Each row has the hotel's name, link, address and map coordinates, star rating, guest review score and review count, and the price for your whole stay in your currency, with the taxes and fees note, the room the price is for, meal plan, free cancellation and "rooms left" messages. Turn on room details to also get every bookable room type on the hotel's page with its own price, cancellation terms and meals.

Results come back in Booking.com's own order (or the sort order you choose) and page through automatically until your limit, so a big city search can return hundreds or thousands of properties in one run.

### Use cases

- **Hotel price tracking**: re-run the same destination and dates on a schedule and watch how prices move as the stay gets closer.
- **Rate comparison**: compare your property's price, score and position against every competitor in the same area.
- **Travel research**: build a shortlist of well-reviewed places in a price range, with coordinates for mapping.
- **Market analysis**: count properties, star mix and average prices by city or neighbourhood.
- **Room-level pricing**: see every room type and rate a hotel sells for specific dates.

### Quick Start

```json
{
  "destinations": ["Lisbon"],
  "checkIn": "2026-12-10",
  "checkOut": "2026-12-13",
  "adults": 2,
  "rooms": 1,
  "currency": "USD",
  "maxItems": 50
}
```

Leave the dates empty to search a 2-night stay 30 days from today. You can also paste a link copied from a Booking.com search results page into `searchUrls`; its own dates and guests are used.

### Input

| Input | Type | Default | Meaning |
| --- | --- | --- | --- |
| `destinations` | array | `[]` | Places as you would type them on Booking.com: a city, region, district or landmark (for example `Lisbon`, `Manhattan`, `Eiffel Tower`). Each one is searched separately. |
| `searchUrls` | array | `[]` | Links copied from Booking.com search results pages. |
| `checkIn` | string | 30 days from today | Arrival date, `YYYY-MM-DD`. |
| `checkOut` | string | 2 nights after check-in | Departure date, `YYYY-MM-DD`. Stays can be up to 30 nights. |
| `adults` | integer | `2` | Adult guests. |
| `childrenAges` | array | `[]` | One age (0-17) per child, for example `[5, 9]`. |
| `rooms` | integer | `1` | Rooms for the group. |
| `currency` | string | `USD` | Currency for every price, for example `EUR` or `GBP`. |
| `sortBy` | string | `popularity` | `popularity`, `price_lowest`, `price_highest`, `review_score`, `review_score_and_price`, `stars_highest`, `stars_lowest` or `distance`. |
| `maxItems` | integer | `100` | Total hotels to return, up to 5,000. With several destinations the limit is shared evenly, and a destination with fewer hotels passes its unused share on. |
| `includeRoomDetails` | boolean | `false` | Also add every bookable room type and its price from each hotel's page. Slower; charged as an add-on per hotel that returns rooms. |

### Example queries

- `{"destinations": ["Paris"], "sortBy": "price_lowest", "maxItems": 200}`: the 200 cheapest places in Paris for a 2-night stay next month.
- `{"destinations": ["New York"], "checkIn": "2026-12-31", "checkOut": "2027-01-02", "currency": "USD", "sortBy": "review_score"}`: New Year's Eve, best reviewed first.
- `{"destinations": ["Barcelona"], "adults": 2, "childrenAges": [6, 10], "rooms": 1}`: a family of four.
- `{"destinations": ["Rome"], "maxItems": 20, "includeRoomDetails": true}`: 20 hotels with every room type and rate.

### What it returns

The dataset contains one row per property:

| Field | Meaning |
| --- | --- |
| `kind` | `hotel` for every dataset row. |
| `hotelId`, `name`, `url` | Booking.com property id, name and its page for your dates and guests. |
| `address`, `city`, `district`, `countryCode` | Where it is, as Booking.com lists it. |
| `latitude`, `longitude`, `distanceFromCenter` | Map position and the distance note shown in results. |
| `stars` | Star or quality rating (1-5) as shown in the results. |
| `reviewScore`, `reviewScoreWord`, `reviewCount` | Guest score out of 10, its label (for example Excellent) and the number of reviews. |
| `price`, `currency`, `priceText` | Price for the whole stay for your guests and rooms, and the price as displayed. Empty when sold out. |
| `priceBeforeDiscount` | The struck-through price when a discount is shown. |
| `taxesAndFees` | Whether taxes and fees are included, or the extra amount. |
| `roomOffer`, `beds`, `mealPlan` | The room the price is for, its bed count and any included meals. |
| `freeCancellation`, `noPrepayment`, `roomsLeftMessage` | Booking terms and scarcity notes shown with the price. |
| `available` | True when the property has a price for your dates. |
| `photoUrl` | Main photo. |
| `checkIn`, `checkOut`, `nights`, `adults`, `children`, `rooms` | The stay the price is for. |
| `destination`, `searchRank` | The destination as Booking.com matched it, and the position in the results. |
| `roomTypes` | With `includeRoomDetails`: every room offer with `roomName`, `roomId`, `offerId`, `maxGuests`, `price` (one room, whole stay), `priceText`, `cancellation`, `mealPlan`, `includedTaxesAndFees`, `excludedTaxesAndFees` and `roomsAvailable`. Otherwise `null`. |
| `scrapedAt` | Collection time (UTC). |
| `error` | Always `null` in the dataset. Failures are reported in the run summary instead. |

The run summary (`OUTPUT`) lists each destination with the place Booking.com matched, its total number of available properties, how many hotels were returned and any error, plus `hotels`, `hotelsWithRoomDetails` and `errors`.

### Output example

```json
{
  "kind": "hotel",
  "hotelId": "10990731",
  "name": "Easy Host Porto",
  "url": "https://www.booking.com/hotel/pt/easy-host-porto.html?checkin=2026-11-19&checkout=2026-11-21&group_adults=2&no_rooms=1&group_children=0&selected_currency=EUR",
  "address": "352 Avenida de Camilo",
  "city": "Porto",
  "district": "Bonfim, Porto",
  "countryCode": "pt",
  "latitude": 41.148359797018,
  "longitude": -8.597949513527,
  "distanceFromCenter": "1.1 km from downtown",
  "stars": null,
  "reviewScore": 7.9,
  "reviewScoreWord": "Good",
  "reviewCount": 2568,
  "price": 46.02,
  "priceBeforeDiscount": 49.8,
  "currency": "EUR",
  "priceText": "€ 46.02",
  "taxesAndFees": "Includes taxes and fees",
  "roomOffer": "Single Bed in Dormitory Room",
  "beds": 2,
  "mealPlan": null,
  "freeCancellation": false,
  "noPrepayment": false,
  "roomsLeftMessage": null,
  "available": true,
  "photoUrl": "https://cf.bstatic.com/xdata/images/hotel/square600/503127088.jpg?k=26c54a43bb5ce75638e275bddf4be2cb458c34414a7a18716d9503577c791db9&o=",
  "checkIn": "2026-11-19",
  "checkOut": "2026-11-21",
  "nights": 2,
  "adults": 2,
  "children": 0,
  "rooms": 1,
  "destination": "Porto, Norte Region, Portugal",
  "searchRank": 1,
  "roomTypes": [
    {
      "roomName": "Single Bed in Dormitory Room",
      "roomId": "1099073105",
      "offerId": "1099073105_382770871_1_10_0_139926",
      "maxGuests": 1,
      "price": 24.9,
      "priceText": "€ 25",
      "cancellation": "free_cancellation",
      "mealPlan": null,
      "includedTaxesAndFees": 7.07,
      "excludedTaxesAndFees": 0.0,
      "roomsAvailable": 7
    }
  ],
  "scrapedAt": "2026-10-20T01:59:15Z",
  "error": null
}
```

### Good to know

- Prices are what a signed-out visitor sees for your dates, guests and currency. Member-only and app-only rates are not included, and Booking.com may show slightly different prices to visitors in other countries.
- A place name is matched to Booking.com's own destination list; the matched destination is shown in `destination` and in the run summary. For an exact area, paste a search results link instead.
- Sold-out properties that Booking.com still lists come back with `available: false` and no price.
- Each destination returns at most the number of properties Booking.com lists for it. Hotels found under two destinations are returned once.
- Room details read one extra page per hotel, so allow a few seconds per hotel. If a hotel's page cannot be read, the hotel is still returned with `roomTypes: null` and no room-details charge.
- If no destination returns any hotel, the run fails with a clear message instead of finishing with an empty dataset.
- Reviews text is not included.
- Automated access is subject to Booking.com's terms; use this actor only where you have the necessary permissions and a lawful basis.

### Price

**$0.0015 per hotel** delivered, plus **$0.00055 per hotel** that comes back with room details when `includeRoomDetails` is on ($0.00205 in total for such a hotel), plus **$0.00125 per run start**. The run-start event is charged per GB of memory; the default 4096 MB run is four start events ($0.005). The start is charged even if the run saves no results. Failed destinations are not charged. A hotel whose page could not be read is still charged the $0.0015 hotel price, but not the room-details add-on. Platform usage is included in these prices.

# Actor input Schema

## `destinations` (type: `array`):

City, region, district or landmark names as you would type them on Booking.com, for example Lisbon, Manhattan or Eiffel Tower. Each destination is searched separately.

## `searchUrls` (type: `array`):

Optional. Links copied from a Booking.com search results page (booking.com/searchresults.html?...). The link's own dates and guests are used when it has them.

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

Arrival date (YYYY-MM-DD). Leave empty for 30 days from today.

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

Departure date (YYYY-MM-DD). Leave empty for a 2-night stay. Stays can be up to 30 nights.

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

Number of adult guests.

## `childrenAges` (type: `array`):

One age (0-17) per child, for example \[5, 9]. Leave empty for no children.

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

Number of rooms for the group.

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

Three-letter currency code for every price, for example USD, EUR or GBP.

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

The order Booking.com ranks the results in.

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

Total number of hotels to return. With several destinations the limit is shared evenly; a destination with fewer hotels passes its unused share on.

## `includeRoomDetails` (type: `boolean`):

Also open each hotel's page for your dates and add every bookable room offer (room name, guests, price, cancellation, meals, taxes). Slower, and charged as an add-on per hotel that returns rooms.

## Actor input object example

```json
{
  "destinations": [
    "Lisbon"
  ],
  "searchUrls": [],
  "adults": 2,
  "childrenAges": [],
  "rooms": 1,
  "currency": "USD",
  "sortBy": "popularity",
  "maxItems": 50,
  "includeRoomDetails": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {
    "destinations": [
        "Lisbon"
    ],
    "adults": 2,
    "rooms": 1,
    "currency": "USD",
    "maxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("barefoot_grade/booking-hotels-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 = {
    "destinations": ["Lisbon"],
    "adults": 2,
    "rooms": 1,
    "currency": "USD",
    "maxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("barefoot_grade/booking-hotels-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 '{
  "destinations": [
    "Lisbon"
  ],
  "adults": 2,
  "rooms": 1,
  "currency": "USD",
  "maxItems": 50
}' |
apify call barefoot_grade/booking-hotels-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,barefoot_grade/booking-hotels-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/9g7oXVIe8wxdrhmCP/builds/bOTAQSh5aVO7L6BgU/openapi.json
