Apify Toolkits

Recipes

Eight worked Booking.com runs, each with the exact input that produces it: family stays, price monitoring, cheapest well-rated hotels, apartments only, reviews, radius search, full enrichment, and sold-out detection.

Describes build 1.0.173 of rl1987/booking-api-scraper, deployed 2026-10-29. The column set last changed 2026-10-29. Earlier builds can return a different one.

Eight worked runs, each with the input that produces it. They are the fastest way to see what the Actor does; the input reference explains the fields they set, and what each mode bills says what each one costs.

Every input below validates against the actor’s input schema; every output is a trimmed record from a real run on 2026-09-17 (fields not relevant to the scenario are replaced with …). The complete record shape is on the Output tab of the Store page.

1. Family stay with children

Two adults with a 5- and a 9-year-old want two nights in Amsterdam and need to know what it will actually cost, per room type. childrenAges makes Booking price the party by age; includeRooms adds the room list. By default (onlyFittingProducts: true) products holds only rates Booking would sell this party, while rooms lists every room type offered for it — including ones that do not fit, flagged fitsParty: false.

That is every room type Booking offers, which at some party sizes is fewer than the property has: Booking withholds a room’s rates entirely when the party cannot use it, and a room with no rates cannot appear in rooms. On one property, 2 adults returned six room types while 1 and 4 returned all seven — the missing one was a single room. roomsOnlyFitting: false returns every rate Booking will offer, but cannot recover one it withheld. Query a smaller party for the fullest inventory.

{
  "search": "Amsterdam",
  "checkin": "2026-12-10",
  "checkout": "2026-12-12",
  "currency": "EUR",
  "adults": 2,
  "childrenAges": [5, 9],
  "includeRooms": true,
  "maxItems": 3
}
{
  "id": 10422,
  "name": "ibis Amsterdam Centre",
  "url": "https://www.booking.com/hotel/nl/ibiscentre.html?…&group_adults=2&group_children=2&age=5&age=9",
  "price": { "total": 599.17, "extra_charges": { "excluded": 200.72, "…": "…" } },
  "rooms": [
    { "name": "Family Room", "maxOccupancy": 4, "fitsParty": true,
      "productCount": 4, "minPrice": 799.9, "bedCount": 3, "hasSofaBed": false,
      "beds": [ { "type": "double", "count": 1, "label": "1 full bed" },
                { "type": "twin",   "count": 2, "label": "2 twin beds" } ],
      "childrenPolicy": { "maxChildrenFree": 0, "maxChildrenFreeAge": 3 } },
    { "name": "Standard Double Room", "maxOccupancy": 2, "fitsParty": false,
      "productCount": 0, "minPrice": null, "…": "…" }
  ],
  "products": [
    { "id": "1042225_95453819_4_2_0", "room": 1042225, "roomName": "Family Room",
      "fitsParty": true, "maxOccupancy": 4,
      "occupancy": { "adults": 4, "children": 0,
                     "requestedAdults": 2, "requestedChildrenAges": [5, 9] },
      "price": { "base": 599.17, "total": 799.9,
                 "extra_charges": { "included": [
                   { "charge": "CITYTAX", "name": "City tax", "mode": "percentage", "percentage": 12.5, "total_amount": 74.9 },
                   { "charge": "VAT", "name": "VAT", "mode": "percentage", "percentage": 21, "total_amount": 125.83 } ] } },
      "policies": { "cancellation": { "type": "free_cancellation", "…": "…" }, "…": "…" } }
  ]
}

occupancy.adults / children is how Booking allocates the party to this rate (a 9-year-old may count as an adult-equivalent); requestedAdults / requestedChildrenAges echo what you asked for. The search-path price.total (599.17) is the display price before the listed taxes, and price.total + extra_charges.excluded is the room’s gross 799.9.

2. Price-monitor a fixed list of properties

You know the Booking ids of your competitors and want their headline price for a date every morning, taxes itemised. hotel_ids skips the search and fetches each property directly; the top-level price is the cheapest rate fitting the party (2 adults by default), and extra_charges lists every tax and fee behind it.

{
  "hotel_ids": ["1392565", "235613", "10422"],
  "checkin": "2026-12-10",
  "checkout": "2026-12-12",
  "currency": "EUR",
  "adults": 2,
  "includeExtraCharges": true
}
{
  "id": 1392565,
  "name": "Mercure Amsterdam Sloterdijk Station",
  "currency": "EUR",
  "checkin": "2026-12-10", "checkout": "2026-12-12", "datesAdjusted": false,
  "price": {
    "base": 191.74, "book": 275.97, "total": 275.97,
    "extra_charges": {
      "included": 84.23, "excluded": 0,
      "details": [
        { "charge": "VAT",     "name": "VAT",      "mode": "percentage", "percentage": 21,   "total_amount": 40.26, "currency": "EUR", "inclusion": "included" },
        { "charge": "CITYTAX", "name": "City tax", "mode": "percentage", "percentage": 12.5, "total_amount": 23.97, "…": "…" },
        { "charge": "SERVICECHARGE", "name": "Service charge", "mode": "per_night", "unit_amount": 10, "total_amount": 20, "…": "…" }
      ]
    },
    "priced_block": { "block": "139256509_91477112_2_34_0", "room": 139256509, "source": "hotelPage" }
  },
  "availability": { "status": "available", "requestedNights": 2, "minStayNights": null, "alternatives": [] },
  "deep_link_url": "booking://hotel/1392565?affiliate_id=337862&checkin=2026-12-10&checkout=2026-12-12&mcid=10"
}

Add includeRooms: true to price from the full rate table instead of the recommended rate (priced_block.source becomes roomList), or childrenAges to monitor a family price.

Taxes and point of sale. Booking decides per point of sale whether taxes sit inside the displayed price. Through Apify Proxy (US datacenter) the same Mercure rate is total: 191.74 with those three charges "excluded" (extra_charges.excluded: 84.23); from an EU IP they are included and total is 275.97. total + extra_charges.excluded is the all-in figure in both cases — compare that across runs.

3. Cheapest well-rated hotels in a city

The five cheapest hotels in Amsterdam scoring 8+ and at most €300 for the stay. Rating, price and sort are applied client-side on top of Booking’s own order, so the actor keeps paging until it has enough.

{
  "search": "Amsterdam",
  "checkin": "2026-12-10",
  "checkout": "2026-12-12",
  "currency": "EUR",
  "minReviewScore": 8,
  "maxPrice": 300,
  "sortBy": "price",
  "maxItems": 5
}
{
  "id": 2374707,
  "name": "Hotel Levell",
  "accommodationType": "Hotels",
  "starRating": 3,
  "reviewScore": 8.4,
  "reviewScoreWord": "Very Good",
  "reviewsCount": 15170,
  "address": "…", "city": "Amsterdam", "countryCode": "nl",
  "latitude": 52.36, "longitude": 4.88,
  "currency": "EUR",
  "checkin": "2026-12-10", "checkout": "2026-12-12",
  "price": { "book": 113.86, "total": 113.86,
             "extra_charges": { "excluded": 38.14, "included": 0,
               "details": [ { "charge": "CITYTAX", "mode": "percentage", "total_amount": 14.23, "chargeTypeId": 22 },
                            { "charge": "VAT",     "mode": "percentage", "total_amount": 23.91, "chargeTypeId": 21 } ] } },
  "freeCancellation": true,
  "availability": { "status": "available", "soldOutMessage": null },
  "url": "https://www.booking.com/hotel/nl/lowell.html?aid=337862&checkin=2026-12-10&…",
  "deep_link_url": "booking://hotel/2374707?…"
}

Name, address, star rating, review score, coordinates and the badges (free cancellation, Preferred) come back on every search result at no extra cost. This plain record is the baseline; rooms, products, reviews and details are added only when you switch them on.

4. Apartments and holiday homes only

Restrict a destination search to self-catering places. accommodationTypes takes Booking’s numeric ids (201 Apartments, 220 Vacation Homes — see Accommodation types ); the API also accepts names, e.g. "accommodation_types": ["Apartments", "holiday homes"]. With includeRooms each unit reports its bedroom and bathroom count.

{
  "search": "Amsterdam",
  "checkin": "2026-12-10",
  "checkout": "2026-12-12",
  "currency": "EUR",
  "accommodationTypes": ["201", "220"],
  "includeRooms": true,
  "maxItems": 3
}
{
  "id": 2197656,
  "name": "houseboat Rose",
  "accommodationType": "Apartments",
  "accommodationTypeId": 201,
  "address": "Amstel 171G", "city": "Amsterdam",
  "price": { "total": 475.5, "…": "…" },
  "rooms": [
    { "name": "Two-Bedroom Apartment", "maxOccupancy": 3, "fitsParty": true,
      "bedroomCount": 2, "bathroomCount": 1, "privateBathroom": true,
      "bedCount": 2, "hasSofaBed": false,
      "beds": [ { "type": "double", "count": 2, "label": "2 full beds", "size": "131–150 cm wide" } ],
      "surfaceM2": 60, "productCount": 1, "minPrice": 634.8, "currency": "EUR" }
  ],
  "url": "https://www.booking.com/hotel/nl/houseboat-rose.html?…"
}

bedroomCount is null for ordinary hotel rooms — Booking publishes a count only for apartment-like units — so you never guess it from the room name.

5. Guest reviews for competitive analysis

The 50 most recent guest reviews of a property, in British English, for a sentiment pipeline. Reviews page 10 at a time, so maxReviews goes well beyond the first page.

{
  "hotel_ids": ["1392565"],
  "checkin": "2026-12-10",
  "checkout": "2026-12-12",
  "includeReviews": true,
  "maxReviews": 50,
  "language": "en-gb"
}
{
  "id": 1392565,
  "name": "Mercure Amsterdam Sloterdijk Station",
  "price": { "…": "…" },
  "reviews": [
    { "id": "a32af29c3af79834",
      "title": "Excellent hotel close to Amsterdam, Haarlem as well as Schiphol.",
      "pros": "Very friendly and helpful staf. Great clean rooms with plenty of space and a great bathroom.",
      "cons": "N/a",
      "score": 10,
      "date": "2026-09-12",
      "author": { "name": "Johan", "countryCode": "se", "countryName": "Sweden" } },
    "… 49 more"
  ]
}

6. Radius search around coordinates

Everything within 1 km of Dam Square, nearest first. Coordinates run Booking’s own lat/long search; the radius (km) cut-off applies to the returned coordinates, and paging stops once a whole page falls outside it.

{
  "latitude": 52.3731,
  "longitude": 4.8926,
  "radius": 1,
  "checkin": "2026-12-10",
  "checkout": "2026-12-12",
  "currency": "EUR",
  "maxItems": 5
}
{
  "id": 10502,
  "name": "Swissôtel Amsterdam",
  "latitude": 52.37350156398789,
  "longitude": 4.893312156200409,
  "address": "Damrak 96", "district": null, "city": "Amsterdam", "countryCode": "nl",
  "reviewScore": 8.2, "starRating": 4,
  "price": { "total": 353.31, "…": "…" },
  "url": "https://www.booking.com/hotel/nl/swissotel-amsterdam.html?…"
}

district is Booking’s neighbourhood label, null where it has none (as in the Amsterdam centre); latitude / longitude are always present.

7. Full property details for enrichment

One property, everything static: address, stars, review score, coordinates, the full facility list, photos, languages, family amenities. On the hotel_ids path the actor also looks the property up by coordinates to fill the fields the hotel page lacks (web URL, star rating, review score, accommodation type, facilities, photos).

{
  "hotel_ids": ["1392565"],
  "checkin": "2026-12-10",
  "checkout": "2026-12-12",
  "includeDetails": true
}
{
  "id": 1392565,
  "name": "Mercure Amsterdam Sloterdijk Station",
  "url": "https://www.booking.com/hotel/nl/mercure-amsterdam-sloterdijk-station-opening-july-2015.html?…",
  "starRating": 4, "reviewScore": 8.6, "accommodationType": "Hotels",
  "price": { "…": "…" },
  "details": {
    "name": "Mercure Amsterdam Sloterdijk Station",
    "accommodationType": "Hotels", "accommodationTypeId": 204,
    "starRating": 4, "reviewScore": 8.6, "reviewScoreWord": "Excellent", "reviewsCount": 3899,
    "address": "Naritaweg 1, Westpoort, 1043 BP Amsterdam, Netherlands",
    "city": "Amsterdam", "countryCode": "nl", "ufi": -2140479,
    "latitude": 52.387911, "longitude": 4.834296, "timezone": "Europe/Amsterdam",
    "facilities": ["Parking", "Room service", "24-hour front desk", "… 106 more"],
    "familyFacilities": ["…"], "photos": ["…"],
    "languagesSpoken": ["pl", "nl", "fr", "es", "en-gb", "de", "ar"],
    "isFamilyFriendly": false, "wifiReviewScore": 8.4,
    "minCheckinAge": 18, "checkinAgeRestriction": "The minimum age for check-in is 18",
    "mainPhotoUrl": "https://cf.bstatic.com/xdata/images/hotel/max1024x768/873579185.webp?…",
    "isBookingHome": null, "bedroomCount": null, "houseRules": null
  }
}

For apartment-like properties details adds isBookingHome, isSingleUnitProperty, bookingHomeGroup, the unit’s bedroomCount / bathroomCount and houseRules.

8. Sold out or minimum stay?

A property that cannot host the stay never appears in a destination search — that is Booking’s behaviour. On the hotel_ids path the actor always emits one record per id and explains itself in availability. Here Hotel Hortus enforces a 2-night minimum over New Year’s Eve, and id 100 does not exist.

{
  "hotel_ids": ["235613", "1392565", "100"],
  "checkin": "2026-12-31",
  "checkout": "2027-01-01",
  "currency": "EUR"
}
[
  { "id": 235613, "name": "Hotel Hortus",
    "checkin": "2026-12-31", "checkout": "2027-01-01", "datesAdjusted": false,
    "price": { "book": null, "total": null, "extra_charges": { "excluded": 0, "included": 0, "details": [] } },
    "availability": {
      "status": "min_stay_not_met", "requestedNights": 1, "minStayNights": 2,
      "soldOutMessage": "Sold out on Booking.com",
      "alternatives": [
        { "checkin": "2026-12-31", "checkout": "2027-01-02", "nights": 2, "price": 440.22, "currency": "EUR" },
        { "checkin": "2027-01-02", "checkout": "2027-01-03", "nights": 1, "price": 209.63, "…": "…" },
        "…" ] } },
  { "id": 1392565, "name": "Mercure Amsterdam Sloterdijk Station",
    "price": { "total": 314.57, "…": "…" },
    "availability": { "status": "available", "requestedNights": 1, "minStayNights": null, "alternatives": [] } },
  { "id": 100, "name": null,
    "price": { "book": null, "total": null },
    "availability": { "status": "not_found", "message": "hotelPage: Hotel with id 100 was not found." } }
]

availability.status is available, min_stay_not_met (with minStayNights), sold_out, closed, no_fit_for_party (rates exist but none fits — only detectable with includeRooms) or not_found. alternatives are the nearby bookable stays Booking suggests. If Booking moved the dates, datesAdjusted is true and checkin / checkout carry the echoed ones. Not-found records are free. On the search path availability is { "status": "available" | "sold_out" }, and the log reports how many results your filters or radius dropped client-side.