# Booking Hotels Scraper - Most Comprehensive (`kaix/booking-hotel-scraper`) Actor

🔥 ~$0.1/1K hotels 🔥 Get hotel profiles, guest reviews, facilities, photos, nearby places, and stay availability by hotel or destination.

- **URL**: https://apify.com/kaix/booking-hotel-scraper.md
- **Developed by:** [Kai](https://apify.com/kaix) (community)
- **Categories:** E-commerce, Travel, Real estate
- **Features:** Limited permissions
- **Stats:** 10 total users, 4 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.08 / 1,000 hotels

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Hotels

Search Booking.com by destination, or collect details for known hotels by URL
or ID. Each Dataset item can include property details, photos, facilities,
reviews, nearby places, rooms, availability, and rates.

### Choose how to find hotels

| Your starting point | Use | The Actor returns |
| --- | --- | --- |
| A city, area, landmark, airport, or hotel name | `destination` and `stay` | Matching properties and, when available, rooms and rates for the stay |
| One or more known properties | `hotels` | The exact properties identified by Booking.com URL or numeric ID |

Use one route in a new run. If you provide both, the destination search takes
precedence.

### Search a destination and check a stay

Use exact dates in `YYYY-MM-DD` format, or dates relative to the UTC run date.
Relative dates keep a saved input useful for later runs.

```json
{
  "destination": "Tokyo, Japan",
  "stay": {
    "checkIn": "60 days",
    "checkOut": "63 days",
    "adults": 2,
    "childrenAges": [],
    "rooms": 1,
    "currency": "JPY"
  },
  "results": {
    "maxHotels": 10,
    "sortBy": "guest_rating",
    "includeReviews": false
  },
  "filters": {
    "starRatings": ["4", "5"],
    "minimumReviewScore": 8,
    "propertyTypes": ["Hotels"],
    "hotelAmenities": ["Free WiFi"]
  }
}
```

The filters in this example keep four- and five-star hotels with a guest score
of at least 8 and free Wi-Fi.

### Collect known hotels

Use a Booking.com URL or numeric hotel ID when you do not need a destination
search:

```json
{
  "hotels": [
    "https://www.booking.com/hotel/jp/park-tokyo.html"
  ],
  "results": {
    "includeReviews": false
  }
}
```

Add `stay` when you also need current availability. Add
`results.includeReviews: true` when you need individual guest reviews.

### Check one known hotel with prices and reviews

```jsonc
{
  "hotels": [
    "https://www.booking.com/hotel/jp/park-tokyo.html"
  ],
  "stay": {
    "checkIn": "60 days",
    "checkOut": "63 days",
    "adults": 2,
    "childrenAges": [4, 9],
    "rooms": 1,
    "currency": "JPY"
  },
  "results": {
    "includeReviews": true,
    "maxReviewsPerHotel": 10
  },
  "language": "en-us"
}
```

Settings such as `maxHotels` and `sortBy` apply only to destination searches.

### Search for one named hotel

A hotel name can also be a destination. This route can return the
`availableRooms` field shown in the output reference.

```jsonc
{
  "destination": "Park Hotel Tokyo, Tokyo",
  "stay": {
    "checkIn": "60 days",
    "checkOut": "63 days",
    "adults": 2,
    "childrenAges": [],
    "rooms": 1,
    "currency": "JPY"
  },
  "results": {
    "maxHotels": 1,
    "sortBy": "recommended",
    "includeReviews": false,
    "maxReviewsPerHotel": 20
  },
  "language": "en-us"
}
```

### Input reference

Use a destination search or a list of exact hotels. Choose one method for a new
run. Dates can be exact, such as `2027-12-15`, or relative to the UTC run date,
such as `60 days`.

New runs in Apify Console start with the Tokyo destination and stay values from
the first destination example. API calls do not add a destination or stay.

#### Complete destination-search input

Select only the filters that match your search. A narrow combination can return
no hotels.

```json
{
  "destination": "Tokyo, Japan",
  "stay": {
    "checkIn": "60 days",
    "checkOut": "63 days",
    "adults": 2,
    "childrenAges": [],
    "rooms": 1,
    "currency": "JPY"
  },
  "results": {
    "maxHotels": 1,
    "sortBy": "guest_rating",
    "includeReviews": false,
    "maxReviewsPerHotel": 20
  },
  "filters": {
    "starRatings": [
      "4",
      "5"
    ],
    "minimumTotalPrice": 30000,
    "maximumTotalPrice": 60000,
    "minimumReviewScore": 8,
    "freeCancellation": true,
    "distanceFromCenter": "3km",
    "propertyTypes": [
      "Hotels"
    ],
    "neighborhoods": [
      "Shinjuku Ward"
    ],
    "mealPlans": [
      "Breakfast included"
    ],
    "hotelAmenities": [
      "Free WiFi"
    ],
    "roomAmenities": [
      "Balcony"
    ],
    "bedPreferences": [
      "Double bed"
    ],
    "brands": [
      "Mitsui Garden"
    ],
    "sustainabilityCertified": true,
    "minimumBedrooms": 1,
    "minimumBeds": 1,
    "travelPurpose": "business"
  },
  "language": "en-us",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

#### Main fields

| Field | Type | Default | How to use it | Example |
| --- | --- | --- | --- | --- |
| `destination` | string | none | Enter a city, area, landmark, airport, or hotel name to search. Add `stay` and leave `hotels` empty. | `"Tokyo, Japan"` |
| `stay` | object | none | Set dates and guests for availability. Partial or omitted dates are accepted; without both dates, no availability search is run. | `{"checkIn":"60 days","checkOut":"63 days"}` |
| `hotels` | string\[] | none | Add Booking.com hotel URLs or numeric IDs when you already know the exact hotels. Leave `destination` empty. Repeated entries are processed in input order and can produce repeated records. | `["179801"]` |
| `results` | object | shown below | Set search result limits, ordering, and review collection. With hotel URLs or IDs, change only the review settings. | `{"maxHotels":10,"includeReviews":true}` |
| `filters` | object | none | Narrow a text search. Filters are ignored when destination search is not selected. | `{"starRatings":["4","5"]}` |
| `language` | string | `en-us` | Choose the locale for returned text and localized filter labels. Common values are `en-us`, `en-gb`, `fr`, `de`, `es`, `it`, and `ja`. | `"fr"` |
| `proxyConfiguration` | object | `{"useApifyProxy":true}` | Optional connection settings for the run. | `{"useApifyProxy":true}` |

For the recommended nested form, provide one of `destination` or `hotels`. If
you provide both, destination search takes precedence and `hotels` is not used.
Filters, `results.maxHotels`, and `results.sortBy` apply only to destination
searches. Unknown fields are accepted, but they do not affect the run. In the
legacy flat form, `search` takes precedence when both `search` and `urls` are
present, so the URL list is not used for that request.

#### `stay`

| Field | Type | Default | How to use it | Example |
| --- | --- | --- | --- | --- |
| `checkIn` | string | none | Choose an exact date as `YYYY-MM-DD`, or a date relative to the UTC run date using days, weeks, months, or years. | `"60 days"` |
| `checkOut` | string | none | Choose an exact or relative checkout date. Relative dates are resolved when the run starts. | `"63 days"` |
| `adults` | integer | `2` | Set the number of adult guests for the whole stay, from 1 to 30. | `2` |
| `childrenAges` | integer\[] | `[]` | Add one age, from 0 to 17, for each child. The Actor derives the child count from this list; do not add a separate `children` field. | `[4,9]` |
| `rooms` | integer | `1` | Set the total number of rooms, from 1 to 30. Guests apply to the stay as a whole, not to individual rooms. | `2` |
| `currency` | string | none | Request stay prices in a three-letter uppercase currency. A price filter without currency is ignored. | `"JPY"` |

#### `results`

| Field | Type | Default | How to use it | Example |
| --- | --- | --- | --- | --- |
| `maxHotels` | integer | `20` | Limit a text search to at most `250` hotels. Use `0` to collect all available results. Do not change it for hotel URLs or IDs. | `10` |
| `sortBy` | string | `recommended` | Order text-search results by `recommended`, `guest_rating`, `price_lowest`, `distance`, `stars_highest`, or `stars_lowest`. Do not change it for hotel URLs or IDs. | `"guest_rating"` |
| `includeReviews` | boolean | `false` | Set `true` to add individual reviews to each hotel record. This works for searches and specific hotels. | `true` |
| `maxReviewsPerHotel` | integer | `20` | When reviews are enabled, stop after this many reviews per hotel, up to `1000`. Use `0` to collect all available reviews. | `50` |

#### `filters`

All filters apply only to `destination` searches.

| Field | Type | Default | How to use it | Example |
| --- | --- | --- | --- | --- |
| `starRatings` | string\[] | `[]` | Keep hotels with any selected star rating. Values are strings from `1` through `5`; you can select more than one. | `["4","5"]` |
| `minimumTotalPrice` | number | none | Set the lowest total price for the full stay. The price filter is used only when both bounds and `stay.currency` are present. | `30000` |
| `maximumTotalPrice` | number | none | Set the highest total price for the full stay. Incomplete price filters are ignored. | `60000` |
| `minimumReviewScore` | integer | none | Keep hotels with a guest score at or above this whole number, from 5 through 9. | `8` |
| `propertyTypes` | string\[] | `[]` | Keep selected property types. Use full labels available for the same destination, stay, and language. | `["Hotels"]` |
| `neighborhoods` | string\[] | `[]` | Limit results to named neighborhoods or districts available for the destination. | `["Shinjuku Ward"]` |
| `mealPlans` | string\[] | `[]` | Keep stays offering the selected meal plans. Use the full localized labels. | `["Breakfast included"]` |
| `hotelAmenities` | string\[] | `[]` | Keep properties with the selected hotel-wide amenities. | `["Free WiFi"]` |
| `roomAmenities` | string\[] | `[]` | Keep stays with the selected in-room amenities. | `["Balcony"]` |
| `bedPreferences` | string\[] | `[]` | Request the selected bed option when it is available for the destination and stay. | `["Double bed"]` |
| `brands` | string\[] | `[]` | Keep hotels from the selected chains or brands available at the destination. | `["Mitsui Garden"]` |
| `freeCancellation` | boolean | `false` | Set `true` to keep stays that offer a free-cancellation option. | `true` |
| `distanceFromCenter` | string | none | Set the maximum distance from the destination center: `1km`, `3km`, or `5km`. | `"3km"` |
| `sustainabilityCertified` | boolean | `false` | Set `true` to keep properties marked with a sustainability certification. | `true` |
| `minimumBedrooms` | integer | none | For apartments or homes, require at least this many bedrooms, from 1 to 10. | `2` |
| `minimumBeds` | integer | none | Require at least this many beds, from 1 to 10. | `2` |
| `travelPurpose` | string | none | Set the stay context to `business` or `leisure`. | `"business"` |

Property, neighborhood, meal, amenity, bed, and brand names depend on the
destination, stay, and selected `language`. Copy the full localized label shown
in Booking.com's filters for the same search, such as `Hotels` or `Free WiFi`.
Matching ignores capitalization and extra spaces. Names that are unavailable
or ambiguous are ignored without failing the run.

<details>
<summary>Legacy input format</summary>

The original flat fields remain available for existing integrations. New runs
can use the nested fields above.

This runnable example uses the flat fields:

```jsonc
{
  "urls": ["179801", "not-a-booking-url"],
  "includeReviews": false,
  "maxReviews": 20,
  "language": "en-us"
}
```

Each value in `urls` is resolved separately. An invalid or unavailable value
does not prevent valid sibling values from running.

| Legacy field | Maps to | Legacy default |
| --- | --- | --- |
| `urls` | Specific hotel references | none |
| `search` | Destination text | none |
| `maxResults` | Maximum search results; `0` means all available | `20` |
| `checkIn`, `checkOut` | Stay dates, used exactly as entered | none |
| `adults` | Adult guests | `2` |
| `children` | Child count | `0` |
| `childrenAges` | Child ages | none |
| `rooms` | Room count | `1` |
| `sortBy` | `relevance`, `rating_highest`, `rating_lowest`, `newest_first`, or `oldest_first` | `relevance` |
| `includeReviews` | Include individual reviews | `true` |
| `maxReviews` | Reviews per hotel; `0` means all available | `20` |
| `filterStarRating` | Star-rating filter | none |
| `filterPrice` | `{min,max,currency}` total-price filter | none |
| `filterReviewScore` | Review-score bucket such as `8+` | none |
| `filterPropertyType` | Property type IDs or values | none |
| `filterNeighborhood` | District IDs or values | none |
| `filterMeals` | Meal-plan IDs or values | none |
| `filterFacilities` | Hotel facility IDs or values | none |
| `filterRoomFacilities` | Room facility IDs or values | none |
| `filterBedPreference` | Bed preference IDs or values | none |
| `filterBrands` | Brand IDs or values | none |
| `filterFreeCancellation` | Require free cancellation | `false` |
| `filterDistanceFromCenter` | Maximum distance from center | none |
| `filterSustainability` | Require sustainability marker | `false` |
| `filterNumberOfBedrooms` | Minimum bedrooms | none |
| `filterNumberOfBeds` | Minimum beds | none |
| `filterTravelPurpose` | `business` or `leisure` | none |
| `language` | Result locale | `en-us` |

</details>

### Hotel record reference

The Actor saves one Dataset record for each returned hotel. Optional sections
appear only when they apply. A `null` value means that Booking.com did not
return a value. An empty array means that the section returned no items.

The examples shorten long arrays to one item. Review objects can contain the
`guestName` and `guestAvatarUrl` keys. The JSON examples omit both keys because
their values can identify individual guests. The exact keys remain in the field
reference, so the shortened JSON is not an all-fields record.

#### Hotel details and rates

This example includes property details, rates, facilities, photos, food,
reviews, and stay availability.

<details>
<summary>Open the hotel field-shape example</summary>

```jsonc
{
  "recordType": "hotel",
  "status": "complete",
  "failedSections": [],
  "inputSource": "https://www.booking.com/hotel/jp/park-tokyo.html",
  "hotelId": 179801,
  "name": "Park Hotel Tokyo",
  "url": "https://www.booking.com/hotel/jp/park-tokyo.html",
  "accommodationType": "HOTEL",
  "address": "Tokyo-to, Tokyo, Minato-ku Higashi Shimbashi 1-7-1, Japan",
  "city": "Tokyo",
  "countryCode": "jp",
  "latitude": 35.66335895215537,
  "longitude": 139.7596174478531,
  "starRating": {
    "value": 4,
    "symbol": "STARS"
  },
  "preferredLevel": "PREFERRED_PLUS",
  "isTravelProud": true,
  "isSustainable": false,
  "description": "Featuring stunning views of Tokyo and a convenient location just steps from Shiodome Subway Station, Park Hotel Tokyo offers stylish accommodations with free WiFi.\n\nRooms feature large picture windows. Each includes exclusive THANN amenities. Guests can relax and enjoy sweeping city views.\n\nPark Hotel Tokyo is only a 10-minute walk to Hamarikyu Gardens. Shinbashi Train Station is 984 feet away, and Tsukiji Fish Market and the Ginza shopping area are both just a 5-minute taxi ride from the hotel.\n\nPark Hotel Tokyo also offers a fully equipped concierge services.\n\nThe hotel offers 3 food and beverage options, including Hanasanshou (Japanese cuisine). A cafe, lounge and bar are also located on-site.",
  "summary": "The 4-star hotel features full-day security and a range of amenities including a restaurant, bar, and <b>free WiFi</b>, ensuring comfort for families. Previous visitors appreciated the scenic <b>location</b> and nearby art attractions. The Shinbashi Shiogama Shrine is just a 7-minute walk away.",
  "reviewScore": 9,
  "reviewsCount": 3494,
  "ratingScores": [
    {
      "name": "hotel_clean",
      "translation": "Cleanliness",
      "value": 9.331888198852539,
      "reviewsCount": 660
    }
  ],
  "houseRules": {
    "checkinFrom": "3:00 PM",
    "checkinUntil": null,
    "checkoutFrom": null,
    "checkoutUntil": "11:00 AM"
  },
  "facilities": [
    {
      "id": 304,
      "groupId": 1,
      "title": "Shuttle service",
      "chargeMode": "PAID"
    }
  ],
  "photos": [
    {
      "id": 747996076,
      "url": "https://cf.bstatic.com/xdata/images/hotel/original/747996076.jpg?k=9a1fe7b35e6f2ec1baf2913b574bfc663007e36aa269d00db9974349b8625833&o=",
      "altText": "a view of a city skyline from a window at Park Hotel Tokyo in Tokyo",
      "type": "PROPERTY",
      "tags": [
        {
          "name": "Day",
          "id": 41
        }
      ]
    }
  ],
  "surroundings": {
    "landmarks": [
      {
        "name": "Shiodome Italian Town",
        "distance": "1,000 ft"
      }
    ],
    "restaurants": [
      {
        "name": "比内や",
        "distance": "300 ft"
      }
    ],
    "cafeBars": [
      {
        "name": "Borracho",
        "distance": "750 ft"
      }
    ],
    "supermarkets": [
      {
        "name": "旬八青果店",
        "distance": "2,850 ft"
      }
    ],
    "beaches": [
      {
        "name": "Odaiba Beach",
        "distance": "2.1 mi"
      }
    ],
    "skiLifts": [],
    "bus": [],
    "metro": [
      {
        "name": "Shiodome",
        "distance": "100 ft"
      }
    ],
    "train": [
      {
        "name": "Shiodome",
        "distance": "150 ft"
      }
    ],
    "airports": [
      {
        "name": "Tokyo Haneda Airport",
        "distance": "6 mi"
      }
    ]
  },
  "meals": [
    {
      "mealType": "BREAKFAST",
      "price": "¥4,500",
      "style": "Buffet",
      "cuisine": "American"
    }
  ],
  "restaurants": [
    {
      "name": "Restaurant",
      "cuisines": [
        "Japanese"
      ]
    }
  ],
  "legalInfo": {
    "isTrader": true,
    "companyName": "株式会社芝パークホテル",
    "email": "reservation@parkhoteltokyo.com",
    "phone": "+810362521111"
  },
  "finePrints": [
    "In response to the coronavirus (COVID-19), additional safety and sanitation measures are in effect at this property."
  ],
  "languagesSpoken": [],
  "featuredReviews": [
    {
      "score": 10,
      "reviewUrl": "dd416fb43355a837",
      "title": "Very helpful staff and beautiful resort",
      "positiveText": "Staff , room , location , amenities and breakfast and concierge were all excellent \nCappuccino in lobby all day",
      "negativeText": "",
      "date": 1786223456,
      "guestCountry": "us",
      "language": "xu",
      "isTranslatable": false,
      "guestCountryName": "United States"
    }
  ],
  "reviews": [
    {
      "score": 7,
      "reviewUrl": "f75a4aaf3f2e608c",
      "positiveText": "The hotel location is exceptional, I don’t need to write anything else. Breakfast is very good also and the views are great!",
      "negativeText": "The hotel seems a bit outdated, specially the rooms. Have in mind I went during the summer so it was very hot outside but the A/C was very weak.",
      "title": "Okay.",
      "date": 1786717351,
      "guestCountry": "us",
      "language": "xu",
      "isTranslatable": false,
      "guestCountryName": "United States"
    }
  ],
  "reviewsMetadata": {
    "advertisedCount": 3494,
    "returnedCount": 10,
    "complete": true,
    "topicIds": []
  },
  "stayRequest": {
    "checkIn": "2026-10-15",
    "checkOut": "2026-10-18",
    "adults": 2,
    "children": 2,
    "childrenAges": [
      4,
      9
    ],
    "rooms": 1,
    "currency": "JPY"
  },
  "availability": {
    "hasAvailability": true,
    "price": {
      "total": {
        "amount": "379578.1818",
        "currency": "JPY",
        "formatted": "¥379,578"
      },
      "originalTotal": null,
      "averagePerNight": null,
      "chargesText": [],
      "taxExceptionsText": []
    },
    "freeCancellationAvailable": true,
    "rateComponents": [
      {
        "roomId": "17980105",
        "occupancy": 2,
        "mealPlanId": 2,
        "policyGroupId": "366275015",
        "packageId": "0",
        "finalPrice": {
          "amount": "189789.0909",
          "currency": "JPY",
          "formatted": null
        },
        "originalPrice": {
          "amount": "189789.0909",
          "currency": "JPY",
          "formatted": null
        },
        "freeCancellationUntil": "2026-10-13T15:00:00.000Z"
      }
    ],
    "matchingUnitConfiguration": null
  },
  "pricing": {
    "displayPrice": "¥379,578",
    "currency": "JPY",
    "averagePricePerNight": "",
    "showFreeCancellation": true
  },
  "scrapedAt": "2026-08-16T14:57:59.466Z"
}
```

</details>

#### Room availability from a search

The direct-hotel record above did not contain `availableRooms`, and its
`matchingUnitConfiguration` was `null`. This destination-search example shows
both fields.

```jsonc
{
  "hotelId": 179801,
  "name": "Park Hotel Tokyo",
  "availability": {
    "price": {
      "originalTotal": {
        "amount": "189789.09090909088",
        "currency": "JPY",
        "formatted": "¥189,789"
      }
    },
    "matchingUnitConfiguration": {
      "name": "Twin Room - Non Smoking - Above 26th floor",
      "area": null,
      "beds": 2,
      "bedrooms": 0,
      "livingRooms": 0,
      "kitchens": 0,
      "bathrooms": 0,
      "unitCount": 1,
      "units": [
        {
          "unitTypeId": 8,
          "name": "Twin Room - Non Smoking - Above 26th floor",
          "unitCount": 1
        }
      ]
    }
  },
  "availableRooms": [
    {
      "roomId": "17980105",
      "name": "Twin Room - Non Smoking - Above 26th floor",
      "occupancy": 2,
      "beds": 2,
      "bathrooms": 0
    }
  ]
}
```

#### Retained hotel projection

This selected-field projection matches retained Actor output captured on 31
July 2026. The shown values are unchanged. That run had
`results.includeReviews: false`, so review fields are absent.

```json
{
  "recordType": "hotel",
  "status": "complete",
  "failedSections": [],
  "hotelId": 179801,
  "name": "Park Hotel Tokyo",
  "city": "Tokyo",
  "countryCode": "jp",
  "starRating": {
    "value": 4,
    "symbol": "STARS"
  },
  "reviewScore": 9,
  "reviewsCount": 3489,
  "stayRequest": {
    "checkIn": "2026-09-29",
    "checkOut": "2026-10-01",
    "adults": 2,
    "children": 0,
    "childrenAges": [],
    "rooms": 1,
    "currency": "JPY"
  },
  "availability": {
    "hasAvailability": true,
    "price": {
      "total": {
        "amount": "97988.9328",
        "currency": "JPY",
        "formatted": "¥97,989"
      },
      "originalTotal": null,
      "averagePerNight": null,
      "chargesText": [],
      "taxExceptionsText": []
    },
    "freeCancellationAvailable": true,
    "rateComponents": [
      {
        "roomId": "17980101",
        "occupancy": 2,
        "mealPlanId": 2,
        "policyGroupId": "366275015",
        "packageId": "0",
        "finalPrice": {
          "amount": "97988.9328",
          "currency": "JPY",
          "formatted": null
        },
        "originalPrice": {
          "amount": "97988.9328",
          "currency": "JPY",
          "formatted": null
        },
        "freeCancellationUntil": "2026-09-27T15:00:00.000Z"
      }
    ],
    "matchingUnitConfiguration": {
      "name": "Queen Room - Non Smoking - Above 27th floor",
      "area": null,
      "beds": 1,
      "bedrooms": 0,
      "livingRooms": 0,
      "kitchens": 0,
      "bathrooms": 0,
      "unitCount": 1,
      "units": [
        {
          "unitTypeId": 9,
          "name": "Queen Room - Non Smoking - Above 27th floor",
          "unitCount": 1
        }
      ]
    }
  },
  "scrapedAt": "2026-07-31T13:43:40.200Z"
}
```

#### Top-level field reference

| Field | Type | Meaning |
| --- | --- | --- |
| `recordType` | string | Always `hotel`. |
| `status` | string | `complete` when all requested sections succeeded; otherwise `partial`. |
| `failedSections` | string\[] | Requested sections that did not complete. |
| `inputSource` | string | The URL, hotel ID, or destination that produced the record. |
| `hotelId` | integer | Booking.com hotel ID. |
| `name` | string | Hotel name. |
| `url` | string or null | The hotel URL from your input. A numeric hotel ID gives `https://www.booking.com/hotel/<id>`. Search results have `null`. |
| `accommodationType` | string or null | Property type. |
| `address`, `city`, `countryCode` | string or null | Property address data. |
| `latitude`, `longitude` | number or null | Property coordinates. |
| `starRating` | object or null | Star value and symbol. |
| `preferredLevel` | string or null | Booking.com preferred-property level. |
| `isTravelProud`, `isSustainable` | boolean | Property markers. |
| `description`, `summary` | string or null | Property description and summary. |
| `reviewScore`, `reviewsCount` | number or null | Overall guest score and advertised review count. |
| `ratingScores` | object\[] | Scores for categories such as cleanliness and location. |
| `houseRules` | object or null | Check-in and check-out times. |
| `facilities` | object\[] | Hotel facilities and charge information. |
| `photos` | object\[] | Original photo URLs, text, types, and tags. |
| `surroundings` | object or null | Nearby places grouped by category. |
| `meals` | object\[] | Available meal details. |
| `restaurants` | object\[] | On-site restaurants and cuisines. |
| `legalInfo` | object or null | Trader and company contact data. |
| `finePrints` | string\[] | Important notices and conditions. |
| `languagesSpoken` | string\[] | Spoken languages. This list can be empty. |
| `featuredReviews` | object\[] | Reviews selected for the hotel profile. |
| `reviews` | object\[] | Requested individual reviews. Present only when reviews are enabled. |
| `reviewsMetadata` | object | Review count and completion data. Present only when reviews are enabled. |
| `stayRequest` | object | Resolved dates, guests, rooms, and currency. Present when complete dates are supplied. |
| `availability` | object | Structured stay availability and rates. Present when complete dates are supplied. |
| `pricing` | object | Compact price data from the hotel or search result. |
| `availableRooms` | object\[] | Matching rooms from a destination result when Booking.com supplies them. |
| `scrapedAt` | string | UTC time when the record was created. |

Possible `failedSections` values are `propertyInfo`, `reviewSummary`,
`facilities`, `photos`, `surroundings`, `food`, `availability`,
`location`, and `reviews`.

#### Nested field reference

| Path | JSON type and presence | Child contract |
| --- | --- | --- |
| `starRating` | object or `null` | `value`: number; `symbol`: string |
| `ratingScores` | object array | Each item has string `name` and `translation`, plus number `value` and `reviewsCount`. |
| `houseRules` | object or `null` | `checkinFrom`, `checkinUntil`, `checkoutFrom`, and `checkoutUntil` are strings or `null`. |
| `facilities` | object array | `id` and `groupId`: number; `title`: string; `chargeMode`: string or `null` |
| `photos` | object array | `id`: number; `url`: string; `altText` and `type`: string or `null`; `tags`: object array |
| `photos[].tags` | object array | Each item has number `id` and string `name`. |
| `surroundings` | object or `null` | Category keys map to arrays of `{name: string, distance: string}`. |
| `meals` | object array | `mealType`: string; `price`, `style`, and `cuisine`: string or `null` |
| `restaurants` | object array | `name`: string; `cuisines`: string array |
| `legalInfo` | object or `null` | `isTrader`: boolean; `companyName`, `email`, and `phone`: string or `null` |
| `featuredReviews` | object array | Each item uses the review contract below. |
| `reviews` | optional object array | Present only when reviews are enabled. Each item uses the review contract below. |
| Review item | object | `score` and `date`: number; `positiveText` and `negativeText`: string; `reviewUrl`, `title`, `guestName`, `guestCountry`, `language`, `guestAvatarUrl`, and `guestCountryName`: string or `null`; `isTranslatable`: boolean or `null` |
| `reviewsMetadata` | optional object | `advertisedCount`: number or `null`; `returnedCount`: number; `complete`: boolean; `topicIds`: string array |
| `stayRequest` | optional object | `checkIn` and `checkOut`: string; `adults`, `children`, and `rooms`: number; `childrenAges`: number array; `currency`: string or `null` |
| `availability` | optional object | `hasAvailability`: boolean; `price`: object or `null`; `freeCancellationAvailable`: boolean or `null`; `rateComponents`: object array; `matchingUnitConfiguration`: object or `null` |
| `availability.price` | object or `null` | `total`: money object; `originalTotal` and `averagePerNight`: money object or `null`; `chargesText` and `taxExceptionsText`: string array |
| Money object | object | `amount` and `currency`: string; `formatted`: string or `null` |
| `availability.rateComponents` | object array | `roomId`: string; `occupancy`: number; `mealPlanId`: number or `null`; `policyGroupId`, `packageId`, and `freeCancellationUntil`: string or `null`; `finalPrice`: money object; `originalPrice`: money object or `null` |
| `availability.matchingUnitConfiguration` | object or `null` | `name`: string; `area`: string or `null`; `beds`, `bedrooms`, `livingRooms`, `kitchens`, `bathrooms`, and `unitCount`: number; `units`: object array |
| `availability.matchingUnitConfiguration.units` | object array | `unitTypeId` and `unitCount`: number; `name`: string |
| `pricing` | optional object | `displayPrice`, `currency`, and `averagePricePerNight`: string; `showFreeCancellation`: boolean |
| `availableRooms` | optional object array | Each item has string `roomId` and `name`, plus number `occupancy`, `beds`, and `bathrooms`. |

`reviewsMetadata.returnedCount` equals the saved `reviews.length`.
`reviewsMetadata.complete` is `true` when the requested review limit was
reached or all reviews made available by Booking.com were collected. The
advertised review count can still be higher than `returnedCount`.

The `surroundings` keys depend on the property. The example includes
`landmarks`, `restaurants`, `cafeBars`, `supermarkets`, `beaches`,
`skiLifts`, `bus`, `metro`, `train`, and `airports`. Empty arrays are
valid. Search prices and room lists also depend on the selected dates and
Booking.com availability.

### Availability and result behaviour

- `results.maxHotels: 0` and `results.maxReviewsPerHotel: 0` collect all
  currently available results and can make a run much longer.
- Review arrays stay inside their hotel record. If a record becomes too large,
  review collection stops and the record is marked `partial`.
- A valid destination, filter combination, or dated stay can return no matching
  hotel. Dated hotel records report this with
  `availability.hasAvailability: false`.
- Hotel URLs and IDs are handled independently. Malformed or unavailable
  references are skipped while valid siblings are still saved. If none can be
  returned, the run completes with zero records.
- An omitted selection or an empty `hotels`/legacy `urls` list is a successful
  zero-work run that saves no records.
- Guest counts apply to the stay as a whole. Room-by-room guest allocation is
  not supported.
- The Actor does not verify that checkout is after check-in.
- Results do not include every bookable rate plan, complete payment and
  cancellation terms, every tax schedule, or a checkout flow.
- Booker country, platform-specific rates, and membership deals cannot be
  selected independently.
- Flexible dates and coordinate-radius search are not input options.
- Review sorting, traveler filters, topic filters, and review-text search are
  not input options.
- Optional sections can be temporarily unavailable. Check `status` and
  `failedSections` before treating a hotel record as complete.
- Booking.com can change or remove public values. Prices, room availability,
  ratings, and review totals are point-in-time results.

# Actor input Schema

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

Enter a city, area, landmark, airport, or hotel name. Then choose check-in and check-out below. You do not need a hotel URL.

## `stay` (type: `object`):

Required for a destination search. Choose exact dates or dates relative to the run date. Dates are optional for specific hotels.

## `hotels` (type: `array`):

Use this instead of Destination when you already know the exact hotels. Add one or more Booking.com hotel URLs or numeric IDs. Dates are optional.

## `results` (type: `object`):

Set search result limits, ordering, and review collection. With hotel URLs or IDs, change only the review settings.

## `filters` (type: `object`):

Use these only for a destination or hotel-name search. Text labels must be available for the same search, stay, and language; capitalization and extra spaces are ignored.

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

Choose the locale for returned text and localized filter labels. You can enter another supported locale instead of the suggested values.

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

Leave the default for normal runs. Change it only when your Apify account requires different connection settings.

## Actor input object example

```json
{
  "destination": "Tokyo, Japan",
  "stay": {
    "checkIn": "60 days",
    "checkOut": "63 days",
    "adults": 2,
    "childrenAges": [],
    "rooms": 1,
    "currency": "EUR"
  },
  "hotels": [
    "https://www.booking.com/hotel/jp/park-tokyo.html"
  ],
  "results": {
    "maxHotels": 10,
    "sortBy": "guest_rating",
    "includeReviews": true,
    "maxReviewsPerHotel": 50
  },
  "filters": {
    "starRatings": [
      "4",
      "5"
    ],
    "minimumReviewScore": 8,
    "freeCancellation": true
  },
  "language": "fr",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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": "Tokyo, Japan",
    "stay": {
        "checkIn": "60 days",
        "checkOut": "63 days",
        "adults": 2,
        "childrenAges": [],
        "rooms": 1
    },
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kaix/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 = {
    "destination": "Tokyo, Japan",
    "stay": {
        "checkIn": "60 days",
        "checkOut": "63 days",
        "adults": 2,
        "childrenAges": [],
        "rooms": 1,
    },
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("kaix/booking-hotel-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 '{
  "destination": "Tokyo, Japan",
  "stay": {
    "checkIn": "60 days",
    "checkOut": "63 days",
    "adults": 2,
    "childrenAges": [],
    "rooms": 1
  },
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call kaix/booking-hotel-scraper --silent --output-dataset

```

## MCP server setup

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