Sign inTry it

Search hotels and stays with total price, rating and cancellation terms.

Searches Booking.com like its search page, for a destination, dates and guests: name, total price for the stay and the price before discounts with currency, review score, number of reviews and rating word, star rating, address and coordinates, distance to the centre, free cancellation (and until when), sold-out flag and link. Filters: budget, minimum review score, stars, free cancellation; sort by popularity, price, rating or distance. Sponsored results are dropped by default.

No reports yetRead-only, no login
Site
Booking.com, Netherlands
Version
v1
Runs, last 7 days
No reports yet
sha256
fae43b40ccb1…

Run it with your agent

after installing Wield

Ask in plain words. Your agent finds this recipe and calls it:

“Search hotels and stays with total price, rating and cancellation terms.”

Read-only: it changes nothing on the site. No login needed.

{
  "tool": "run",
  "arguments": {
    "recipe_id": "booking.com/search-stays",
    "params": {
      "adults": 2,
      "checkin": "2026-12-11",
      "checkout": "2026-12-13",
      "destination": "Lisbon"
    }
  }
}

Requests

sent from your browser, in order
  1. 1GET/searchresults.{{params.language}}.html?age&checkin&checkout&group_adults&group_children&nflt&no_rooms&offset&order&selected_currency&ssThe search results page. Results come from the page state (script[data-capla-store-data], an Apollo cache): ROOT_QUERY.searchQueries holds one entry whose results are the property cards. The one-item foreach builds Booking's filter string (nflt), sort code and offset.repeats, max 1

Parameters

from your agent
adultsinteger = 2
checkinstringrequiredYYYY-MM-DD
checkoutstringrequiredYYYY-MM-DD, after checkin
children_agesinteger[] = []
currencystring = "EUR"
destinationstringrequiredCity, region, landmark or hotel name, e.g. 'Lisbon', 'Porto Ribeira', 'Berlin Mitte'
free_cancellationboolean = false
include_sponsoredboolean = false
languageenum "en-gb" | "en-us" | "de" | "fr" | "es" | "it" | "nl" | "pt-pt" = "en-gb"
max_priceintegerBudget per night in the chosen currency
min_review_scoreenum6 = pleasant, 7 = good, 8 = very good, 9 = wonderful 6 | 7 | 8 | 9
pageinteger = 1
roomsinteger = 1
sortenum "popularity" | "price" | "rating" | "distance" = "popularity"
starsintegerExact star rating

Returns

to your agent
checkinstring
checkoutstring
destinationstring
nightsinteger
pageinteger
staysobject[]address, center_distance, charges_excluded, city, country, currency, deals, district, free_cancellation, free_cancellation_until, id, latitude, longitude, name, no_prepayment, price_before_discount, price_total, rating_word, review_score, reviews, sold_out, sponsored, stars, url
totalintegerMatching stays (Booking's count)

Where it can send

  • www.booking.com

Anything else is blocked by the extension.

Reads from your session

Nothing. Your browser attaches the site's cookies by itself.

Used only in requests to the addresses on the left. Never sent to wield.run or your agent.

Checks

a run passes when
  • length(output.stays) > `5`
  • output.stays[0].price_total > `0`
  • length(output.stays[?currency == 'EUR']) == length(output.stays)
  • length(output.stays[?sponsored]) == `0`
  • output.nights == `2`
  • starts_with(output.stays[0].url, 'https://www.booking.com/hotel/')

Raw recipe

Served as canonical JSON from /api/v1/recipes/booking.com/search-stays, so its sha256 matches the ETag and the index.

Check it yourself
curl -s https://wield.run/api/v1/recipes/booking.com/search-stays | shasum -a 256
# fae43b40ccb1133aba0110f06ca55831a82a4221e1951c6b54ecb65538149801
booking.com/search-stays.json, v1
{
  "description": "Searches Booking.com like its search page, for a destination, dates and guests: name, total price for the stay and the price before discounts with currency, review score, number of reviews and rating word, star rating, address and coordinates, distance to the centre, free cancellation (and until when), sold-out flag and link. Filters: budget, minimum review score, stars, free cancellation; sort by popularity, price, rating or distance. Sponsored results are dropped by default.",
  "effect": "read",
  "id": "booking.com/search-stays",
  "keywords": [
    "booking",
    "hotel",
    "unterkunft",
    "übernachtung",
    "ferienwohnung",
    "reise",
    "hotel buchen",
    "hotels",
    "stay",
    "accommodation",
    "travel",
    "where to stay",
    "price per night",
    "free cancellation"
  ],
  "output": {
    "schema": {
      "properties": {
        "checkin": {
          "type": "string"
        },
        "checkout": {
          "type": "string"
        },
        "destination": {
          "type": "string"
        },
        "nights": {
          "type": [
            "integer",
            "null"
          ]
        },
        "page": {
          "type": "integer"
        },
        "stays": {
          "items": {
            "properties": {
              "address": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "center_distance": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "charges_excluded": {
                "description": "Taxes/fees payable on top, when Booking lists them",
                "type": [
                  "number",
                  "null"
                ]
              },
              "city": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "country": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "currency": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "deals": {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "district": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "free_cancellation": {
                "type": "boolean"
              },
              "free_cancellation_until": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "id": {
                "type": "string"
              },
              "latitude": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "longitude": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "name": {
                "type": "string"
              },
              "no_prepayment": {
                "type": "boolean"
              },
              "price_before_discount": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "price_total": {
                "description": "Total for the stay incl. taxes Booking includes",
                "type": [
                  "number",
                  "null"
                ]
              },
              "rating_word": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "review_score": {
                "description": "0–10",
                "type": [
                  "number",
                  "null"
                ]
              },
              "reviews": {
                "type": "integer"
              },
              "sold_out": {
                "type": "boolean"
              },
              "sponsored": {
                "type": "boolean"
              },
              "stars": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "url": {
                "type": "string"
              }
            },
            "type": "object"
          },
          "type": "array"
        },
        "total": {
          "description": "Matching stays (Booking's count)",
          "type": [
            "integer",
            "null"
          ]
        }
      },
      "type": "object"
    },
    "value": "let $s = steps.search[0].s, $inc = params.include_sponsored == `true`, $lang = params.language || 'en-gb', $ci = params.checkin, $co = params.checkout, $ad = to_string(params.adults || `2`), $ro = to_string(params.rooms || `1`) in {destination: params.destination, checkin: params.checkin, checkout: params.checkout, nights: $s.searchMeta.dates.lengthOfStayInDays || `null`, total: $s.pagination.nbResultsTotal || `null`, page: params.page || `1`, stays: map(&(let $r = @, $b = @.basicPropertyData, $p = @.priceDisplayInfoIrene in {id: to_string($b.id), name: $r.displayName.text, price_total: ($p.displayPrice.amountPerStay.amountUnformatted && floor(($p.displayPrice.amountPerStay.amountUnformatted) * `100` + `0.5`) / `100`) || `null`, price_before_discount: ($p.priceBeforeDiscount.amountPerStay.amountUnformatted > `0` && floor(($p.priceBeforeDiscount.amountPerStay.amountUnformatted) * `100` + `0.5`) / `100`) || `null`, currency: $p.displayPrice.amountPerStay.currency || `null`, charges_excluded: ($p.excludedCharges.excludeChargesAggregated.amountPerStay.amountUnformatted > `0` && floor(($p.excludedCharges.excludeChargesAggregated.amountPerStay.amountUnformatted) * `100` + `0.5`) / `100`) || `null`, review_score: ($b.reviews.totalScore > `0` && $b.reviews.totalScore) || `null`, reviews: $b.reviews.reviewsCount || `0`, rating_word: $b.reviews.totalScoreTextTag.translation || `null`, stars: ($b.starRating.value > `0` && $b.starRating.value) || `null`, address: $b.location.address || `null`, city: $b.location.city || `null`, country: $b.location.countryCode || `null`, latitude: $b.location.latitude || `null`, longitude: $b.location.longitude || `null`, district: $r.location.displayLocation || `null`, center_distance: $r.location.mainDistance || `null`, free_cancellation: $r.policies.showFreeCancellation == `true`, free_cancellation_until: ($r.blocks || `[]`)[0].freeCancellationUntil || `null`, no_prepayment: $r.policies.showNoPrepayment == `true`, sold_out: $r.soldOutInfo.isSoldOut == `true`, deals: ($p.badges || `[]`)[].name.translation, sponsored: $r.sponsoredListingData != `null` || $r.persuasion.showNativeAdLabel == `true` || $r.showAdLabel == `true`, url: join('', ['https://www.booking.com/hotel/', $b.location.countryCode || 'xx', '/', $b.pageName || '', '.', $lang, '.html?checkin=', $ci, '&checkout=', $co, '&group_adults=', $ad, '&no_rooms=', $ro])}), $s.results || `[]`)[?$inc || !sponsored]}"
  },
  "params": {
    "additionalProperties": false,
    "properties": {
      "adults": {
        "default": 2,
        "maximum": 30,
        "minimum": 1,
        "type": "integer"
      },
      "checkin": {
        "description": "YYYY-MM-DD",
        "format": "date",
        "type": "string"
      },
      "checkout": {
        "description": "YYYY-MM-DD, after checkin",
        "format": "date",
        "type": "string"
      },
      "children_ages": {
        "default": [],
        "items": {
          "maximum": 17,
          "minimum": 0,
          "type": "integer"
        },
        "maxItems": 10,
        "type": "array"
      },
      "currency": {
        "default": "EUR",
        "pattern": "^[A-Z]{3}$",
        "type": "string"
      },
      "destination": {
        "description": "City, region, landmark or hotel name, e.g. 'Lisbon', 'Porto Ribeira', 'Berlin Mitte'",
        "maxLength": 100,
        "minLength": 2,
        "type": "string"
      },
      "free_cancellation": {
        "default": false,
        "type": "boolean"
      },
      "include_sponsored": {
        "default": false,
        "type": "boolean"
      },
      "language": {
        "default": "en-gb",
        "enum": [
          "en-gb",
          "en-us",
          "de",
          "fr",
          "es",
          "it",
          "nl",
          "pt-pt"
        ],
        "type": "string"
      },
      "max_price": {
        "description": "Budget per night in the chosen currency",
        "minimum": 1,
        "type": "integer"
      },
      "min_review_score": {
        "description": "6 = pleasant, 7 = good, 8 = very good, 9 = wonderful",
        "enum": [
          6,
          7,
          8,
          9
        ],
        "type": "integer"
      },
      "page": {
        "default": 1,
        "maximum": 20,
        "minimum": 1,
        "type": "integer"
      },
      "rooms": {
        "default": 1,
        "maximum": 30,
        "minimum": 1,
        "type": "integer"
      },
      "sort": {
        "default": "popularity",
        "enum": [
          "popularity",
          "price",
          "rating",
          "distance"
        ],
        "type": "string"
      },
      "stars": {
        "description": "Exact star rating",
        "maximum": 5,
        "minimum": 1,
        "type": "integer"
      }
    },
    "required": [
      "destination",
      "checkin",
      "checkout"
    ],
    "type": "object"
  },
  "provenance": {
    "method": "browser-inspect",
    "notes": "Servers get a JavaScript challenge (HTTP 202), so this runs only in the user's browser; there a same-origin fetch of /searchresults.<lang>.html returns the full page (200, ~1.7 MB, 20 cards) with the Apollo cache in script[data-capla-store-data] (its namespace attribute carries a build hash, so the recipe selects by the data attribute). Results: ROOT_QUERY.searchQueries[<search(...) key>].results (SearchResultProperty): basicPropertyData (id, location, reviews, starRating, pageName), priceDisplayInfoIrene (displayPrice.amountPerStay, priceBeforeDiscount, excludedCharges, badges), policies, blocks[].freeCancellationUntil, soldOutInfo, sponsoredListingData / persuasion.showNativeAdLabel / showAdLabel (sponsored). URL filters: nflt (price=EUR-min-<max>-1;review_score=80;class=4;fc=2), order (price, bayesian_review_score, distance_from_search), offset, selected_currency.",
    "recorded_at": "2026-11-07T18:46:00+01:00",
    "recorded_by": "C4"
  },
  "requires_login": false,
  "schema": "https://wield.run/schema/recipe/v1.json",
  "site": {
    "country": "NL",
    "id": "booking.com",
    "language": "en",
    "name": "Booking.com",
    "origin": "https://www.booking.com",
    "origins": [
      "https://www.booking.com"
    ]
  },
  "steps": [
    {
      "description": "The search results page. Results come from the page state (script[data-capla-store-data], an Apollo cache): ROOT_QUERY.searchQueries holds one entry whose results are the property cards. The one-item foreach builds Booking's filter string (nflt), sort code and offset.",
      "expect": {
        "assert": "contains(body, 'data-capla-store-data')",
        "content_type": "html",
        "status": [
          200
        ]
      },
      "extract": {
        "embedded_json": {
          "selector": "script[type=\"application/json\"][data-capla-store-data]",
          "vars": {
            "s": "values(ROOT_QUERY.searchQueries)[?results] | [0]"
          }
        }
      },
      "foreach": {
        "as": "f",
        "in": "[{offset: (params.page - `1`) * `25`, children: length(params.children_ages || `[]`), order: (params.sort == 'price' && 'price') || (params.sort == 'rating' && 'bayesian_review_score') || (params.sort == 'distance' && 'distance_from_search') || `null`, nflt: join(';', [params.max_price && join('', ['price=', params.currency || 'EUR', '-min-', to_string(params.max_price), '-1']) || '', params.min_review_score && join('', ['review_score=', to_string(params.min_review_score * `10`)]) || '', params.stars && join('', ['class=', to_string(params.stars)]) || '', params.free_cancellation == `true` && 'fc=2' || ''][?@ != '']) || `null`}]",
        "max": 1
      },
      "id": "search",
      "request": {
        "headers": {
          "Accept": "text/html"
        },
        "method": "GET",
        "query": {
          "age": "{{params.children_ages}}",
          "checkin": "{{params.checkin}}",
          "checkout": "{{params.checkout}}",
          "group_adults": "{{params.adults}}",
          "group_children": "{{f.children}}",
          "nflt": "{{f.nflt}}",
          "no_rooms": "{{params.rooms}}",
          "offset": "{{f.offset}}",
          "order": "{{f.order}}",
          "selected_currency": "{{params.currency}}",
          "ss": "{{params.destination}}"
        },
        "url": "/searchresults.{{params.language}}.html"
      }
    }
  ],
  "task": "Search hotels and stays with total price, rating and cancellation terms",
  "tos": {
    "notes": "Booking.com's terms prohibit scraping and automated bulk access. The recipe loads one search page per call in the user's own browser session, as the user would, and never books.",
    "reviewed": false
  },
  "verify": {
    "checks": [
      "length(output.stays) > `5`",
      "output.stays[0].price_total > `0`",
      "length(output.stays[?currency == 'EUR']) == length(output.stays)",
      "length(output.stays[?sponsored]) == `0`",
      "output.nights == `2`",
      "starts_with(output.stays[0].url, 'https://www.booking.com/hotel/')"
    ],
    "example_params": {
      "adults": 2,
      "checkin": "2026-12-11",
      "checkout": "2026-12-13",
      "destination": "Lisbon"
    },
    "max_ms": 6000
  },
  "version": 1
}