Booking.com All-in-One API
Pricing
from $39.00 / 1,000 hotels
Booking.com All-in-One API
Unofficial always-on REST API for live Booking.com data: hotel search (real price/amenity filters + sort), hotel detail, paginated reviews, flights, car rentals, airport taxi, and attractions — search and full detail. Real multi-region pricing, no account needed.
What does Booking.com All-in-One API do?
Booking.com All-in-One API is a REST endpoint for live Booking.com data — destination search, hotel search with real price/amenity filters and sort, full hotel detail, paginated reviews with topic filters, plus flights, car rentals, airport taxi, and attractions search. All from a single always-on API powered by Apify Standby.
It talks directly to the same internal API the official Booking.com Android app uses, reverse-engineered by capturing live traffic from a real device. Auth uses a standard, publicly-documented token-exchange mechanism — not a proprietary signing scheme — generated fresh server-side. No Booking.com account, no API key of your own, and not limited to one region — call the endpoint, get JSON back.
Why use Booking.com All-in-One API?
- Real filters and sort that genuinely work — price range and sort order confirmed live by comparing results before/after: a narrower price range returns fewer, correctly-bounded properties, not an ignored parameter
- Real multi-region pricing — confirmed live: an identical search with different currency codes (USD/EUR/IDR tested) returns genuinely different prices for the same rooms, not a symbol swap
- Real paginated reviews — confirmed live end-to-end: requesting the next page of reviews returns entirely new review ids with zero overlap with the previous page, using Booking.com's own real offset-based pagination
- A dedicated review-topic filter endpoint — the same topic/category breakdown (with counts) the app's own review-filter screen shows
- Four more verticals beyond hotels — flights, car rentals, airport taxi, and attractions are each a genuinely separate backend, confirmed live by opening every tab in the app and capturing real traffic — every one returns real, current prices matching the app's own screen
- Always-on — Standby mode means no cold start, responds in milliseconds
- No account needed — every endpoint works fully anonymously
- Use cases: travel content aggregation, price monitoring across currencies, review analysis, destination research bots
Endpoints
| Method | Path | Description |
|---|---|---|
GET | /search | Destination autocomplete |
GET | /home | Home tab feed |
GET | /hotels | Hotel search for a destination, with real filters/sort |
GET | /hotels/{id} | Full hotel detail |
GET | /hotels/{id}/reviews | Paginated hotel reviews |
GET | /hotels/{id}/reviews/filters | Review-topic filter schema for one hotel |
GET | /flights/search-locations | Flight-specific airport/city autocomplete |
GET | /flights | Round-trip or one-way flight search |
GET | /flights/detail | Full flight detail — baggage policy, fare rules |
GET | /car-rentals/search-locations | Car rental pickup-location autocomplete |
GET | /car-rentals | Car rental search |
GET | /car-rentals/detail | Full car detail — specs, inclusions, cancellation terms |
GET | /taxi/search-locations | Airport taxi location resolution (Google Place ID) |
GET | /taxi/rates | Airport taxi prices for a route |
GET | /attractions | Things-to-do search |
GET | /attractions/{slug} | Full attraction detail |
GET | /attractions/{id}/reviews | Paginated attraction reviews |
GET | /attractions/{id}/reviews/filters | Review filter/sort schema for one attraction |
How to use Booking.com All-in-One API
- Open this Actor's Standby API URL (shown on the Actor's page, under the API tab).
- Call any endpoint — for example:
Every call needs your Apify API token, either ascurl "https://romy--booking-all-in-one-api.apify.actor/search?query=Bangkok"curl "https://romy--booking-all-in-one-api.apify.actor/home"curl "https://romy--booking-all-in-one-api.apify.actor/hotels?dest_id=-3414440&dest_name=Bangkok"curl "https://romy--booking-all-in-one-api.apify.actor/hotels?dest_id=-3414440&dest_name=Bangkok&price_min=50&price_max=150¤cy=USD"curl "https://romy--booking-all-in-one-api.apify.actor/hotels/27229"curl "https://romy--booking-all-in-one-api.apify.actor/hotels/27229/reviews?rows=25&offset=25"curl "https://romy--booking-all-in-one-api.apify.actor/hotels/27229/reviews/filters"curl "https://romy--booking-all-in-one-api.apify.actor/flights/search-locations?q=Bangkok"curl "https://romy--booking-all-in-one-api.apify.actor/flights?from=BKK.AIRPORT&to=SIN.CITY&depart=2026-09-19&return=2026-09-26¤cy=USD"# /flights/detail needs a token field copied from a /flights result — e.g. flightOffers[0].tokencurl "https://romy--booking-all-in-one-api.apify.actor/flights/detail?token=<token from a /flights result>"curl "https://romy--booking-all-in-one-api.apify.actor/car-rentals/search-locations?term=Bangkok"curl "https://romy--booking-all-in-one-api.apify.actor/car-rentals?location=Bangkok&lat=13.7563&lng=100.5018&pickup=2026-09-24T10:00:00.000Z&dropoff=2026-09-27T10:00:00.000Z¤cy=USD"# /car-rentals/detail needs search_key + vehicle_id copied from a /car-rentals resultcurl "https://romy--booking-all-in-one-api.apify.actor/car-rentals/detail?search_key=<search_context.searchKey from a /car-rentals result>&vehicle_id=<content.metadata.vehicleId from the same result>"curl "https://romy--booking-all-in-one-api.apify.actor/taxi/search-locations?q=Sukhumvit&lat=13.6934&lng=100.751"curl "https://romy--booking-all-in-one-api.apify.actor/taxi/rates?pickup=Suvarnabhumi%20Airport&pickup_place_id=ChIJTydCFXdnHTERB3oVT1UZDRI&dropoff=Sukhumvit%20Soi%2011&dropoff_place_id=ChIJ5yhiwOae4jARWAUxwZD2wE4&pickup_datetime=2026-09-19T10:00:00"curl "https://romy--booking-all-in-one-api.apify.actor/attractions?ufi=-3414440"curl "https://romy--booking-all-in-one-api.apify.actor/attractions/prvajppfwe7k-the-newest-luxury-5-star-bangkok-chao-phraya-dinner-cruise"curl "https://romy--booking-all-in-one-api.apify.actor/attractions/PRvAjpPfwE7K/reviews?rating=5"curl "https://romy--booking-all-in-one-api.apify.actor/attractions/PRvAjpPfwE7K/reviews/filters"Authorization: Bearer <token>or?token=<token>— the Actor's page API tab has a ready-to-copy version with your token filled in. - Read the JSON response — no setup required.
Parameters
GET /search — query required (free-text destination name).
GET /home — no required parameters.
GET /hotels — dest_id required (from /search).
| Param | Type | Example | Meaning |
|---|---|---|---|
dest_id | string | -3414440 | From /search |
dest_name | string | Bangkok | |
checkin / checkout | string (date) | 2026-09-08 | YYYY-MM-DD, default tomorrow/day-after |
adults | int, default 2 | 2 | |
rooms | int, default 1 | 1 | |
price_min / price_max | int | 50 / 150 | Confirmed live to genuinely narrow results |
sort | string | best_value | Confirmed live values: popularity, best_value, price |
currency | string | USD | Confirmed live to change returned prices — works for any region, not just one |
GET /hotels/{id} — id required (a hotel id from /hotels). currency optional.
GET /hotels/{id}/reviews — id required.
| Param | Type | Example | Meaning |
|---|---|---|---|
offset | int, default 0 | 25 | Confirmed live: real pagination, zero id overlap between offsets |
rows | int, default 25 | 25 | Reviews per page |
rating | string | Filter to one review-score band |
GET /hotels/{id}/reviews/filters — id required. Returns the review-topic breakdown (with counts) for that hotel.
GET /flights/search-locations — q required (free-text). type optional (from/to) — narrows suggestions by leg.
GET /flights — from, to, depart required.
| Param | Type | Example | Meaning |
|---|---|---|---|
from / to | string | BKK.AIRPORT / SIN.CITY | From /flights/search-locations |
depart | string (date) | 2026-09-19 | YYYY-MM-DD |
return | string (date) | 2026-09-26 | Omit for a one-way search |
adults | int, default 1 | 1 | |
cabin_class | string, default ECONOMY | ECONOMY | ECONOMY | PREMIUM_ECONOMY | BUSINESS | FIRST |
sort | string, default BEST | CHEAPEST | BEST | CHEAPEST | FASTEST |
page | int, default 1 | 1 | |
currency | string | USD | Confirmed live to change returned prices — a real ISO code, not just a display label |
GET /flights/detail — token required, the opaque token field from a /flights result (also duplicated as flightDeals[].offerToken). Returns full baggage policy and fare rules. Its currency is already baked into the token from whichever /flights search produced it — there's no separate currency param here.
GET /car-rentals/search-locations — term required (free-text).
GET /car-rentals — location, lat, lng, pickup, dropoff required.
| Param | Type | Example | Meaning |
|---|---|---|---|
location | string | Bangkok | From /car-rentals/search-locations |
lat / lng | number | 13.7563 / 100.5018 | Pickup coordinates |
pickup / dropoff | string (ISO 8601) | 2026-09-24T10:00:00.000Z | Pickup/drop-off datetime |
driver_age | int, default 30 | 30 | |
currency | string, default HOTEL | USD | Confirmed live to change returned prices |
GET /car-rentals/detail — search_key and vehicle_id both required, both copied as-is from a /car-rentals result (search_key is that response's own search_context.searchKey; vehicle_id is one result card's content.metadata.vehicleId). Returns full specs, what's included, and cancellation terms. Confirmed live: the same search_key works for every vehicle_id from that same search. currency optional, default HOTEL, confirmed live to change returned prices.
GET /taxi/search-locations — q required (free-text). lat/lng optional, bias suggestions toward a reference point.
GET /taxi/rates — pickup, pickup_place_id, dropoff, dropoff_place_id, pickup_datetime required.
| Param | Type | Example | Meaning |
|---|---|---|---|
pickup / dropoff | string | Suvarnabhumi Airport | Free-text label |
pickup_place_id / dropoff_place_id | string | ChIJTydCFXdnHTERB3oVT1UZDRI | Google Place ID, from /taxi/search-locations |
pickup_datetime | string | 2026-09-19T10:00:00 | A time too close to now can legitimately return "no suppliers available" — a real availability constraint, not a bug |
passengers | int, default 1 | 2 | |
currency | string, default HOTEL | USD |
GET /attractions — ufi required (from /search, same id space as hotels' dest_id).
GET /attractions/{slug} — slug required, the FULL slug string from an /attractions search result (e.g. prvajppfwe7k-the-newest-...). Confirmed live: the short id field alone does not resolve here (404) — the full slug is genuinely required.
GET /attractions/{id}/reviews — id required, but here it's the SHORT id field from a search result (e.g. PRvAjpPfwE7K), not the slug used for detail above — the two endpoints genuinely need different identifiers from the same search result.
| Param | Type | Example | Meaning |
|---|---|---|---|
page | int, default 1 | 2 | Real pagination — confirmed live, zero id overlap between pages |
limit | int, default 20 | 10 | Reviews per page |
rating | string | 5 | An option id from /attractions/{id}/reviews/filters's "score" filter group — confirmed live to genuinely narrow results, not just echo the parameter back |
GET /attractions/{id}/reviews/filters — id required, same short id as above.
| Param | Type | Example | Meaning |
|---|---|---|---|
ufi | int | -3414440 | Destination id |
page | int, default 1 | 1 | |
limit | int, default 20 | 20 |
Output
{"success": true,"list": {"total": 20,"properties": [{ "id": 27229, "name": "Ambassador Hotel Bangkok" }],"raw": { "...": "full server-driven-UI response, for anything not already pulled into properties[]" }}}
Data notes
- Auth is a standard token-exchange flow, not a proprietary scheme. A one-time anonymous request (self-generated device id only, no account) returns a short-lived access token — confirmed live and standalone-reproducible with a brand-new device id, no prior registration. This Actor renews by requesting a fresh token shortly before the cached one expires, generated entirely server-side.
- Real filters and sort, confirmed live. A price range narrows returned properties to that bound (compared results before/after); sort order genuinely reorders results.
- Multi-region pricing confirmed live. The exact same search with different currency codes returns genuinely different prices for the same rooms — this Actor isn't limited to one region's pricing.
currencyis also a real, caller-controlled parameter on/flights,/car-rentals, and/car-rentals/detail, confirmed live with the same before/after price comparison used for hotels — e.g. the exact same flight search returned176 USDvs3,359,469 IDR, and the same car rental returnedUS$78vsRp 1,386,012./flights/detail's currency is inherited from whichever/flightssearch produced its token, not independently settable. Attractions has no equivalent — three different ways of passing a currency override (as a search-input field, as a context field, and as a query-string parameter matching the pattern used elsewhere on the same host) were each tried live and every one was rejected by the API's own input validation, so prices there reflect a fixed account-level currency this Actor cannot override. Documented here rather than silently omitted.- The search/list response is a nested component tree, not a flat array — this Actor walks it and returns a clean
properties[]array of the structured fields (id, name, price, rating) callers actually want, alongside the full raw tree for anything not yet extracted. - Room photos are already included in the hotel-detail response — no separate photo-gallery call needed for the room-level photo set the app itself shows on the detail screen.
- Review pagination is real offset-based paging, confirmed live end-to-end — requesting the next
offsetreturns entirely new review ids, zero overlap with the previous page. - The review-topic filter schema is a genuinely separate endpoint, confirmed live — it isn't bundled into the reviews or search responses.
- Flights, car rentals, airport taxi, and attractions are each a genuinely separate backend from hotels, confirmed live by opening every tab in the app and capturing real traffic — not a re-skin of the hotel search. All four were confirmed standalone-reproducible with no session cookies at all, using only the same access-token headers hotels already need (flights and car rentals do use their own separate app-level credential from hotels; airport taxi and attractions reuse the hotel one, since both ride on the same underlying host).
- Flight search filter/sort options and the attractions search filter/sort schema both come embedded in their own search response (
includeAllFilterValues/extractFilterOptions), same self-describing pattern as the hotel vertical's price-range filter — no separate schema endpoint needed for either. This is distinct from attraction review filters (below), which do need a separate call. - Airport taxi needs a two-step flow, same as the app itself: resolve pickup/drop-off to a Google Place ID via
/taxi/search-locationsfirst, then pass both ids to/taxi/rates. Confirmed live: prices matched the app's own screen exactly for a real Suvarnabhumi Airport → Sukhumvit search. - Attraction detail and reviews are genuinely separate operations from search, each needing a different identifier from the same search result.
/attractions/{slug}needs the full slug string;/attractions/{id}/reviewsand its filters need the shortidfield instead — confirmed live that the short id alone does not resolve as a slug (404), so both fields genuinely have to be passed through from a search result as-is, not derived from each other. - Attraction review pagination is real page/pageSize paging, confirmed live end-to-end — 20 reviews per page, zero id overlap between pages.
- The attraction review filter schema is a genuinely separate endpoint from both the reviews and the search-result filters, confirmed live — and its rating filter genuinely narrows results (verified: a 5-star filter and a 1-star filter returned completely different review ids and ratings), not just an echoed-back parameter.
/flights/detailand/car-rentals/detailboth need an opaque identifier copied as-is from their respective search result, not constructed client-side./flights/detail'stokencomes straight from a/flightsresult's owntokenfield;/car-rentals/detailneeds bothsearch_key(the search response's ownsearch_context.searchKey) andvehicle_id(a result card'scontent.metadata.vehicleId). Confirmed live for car rentals: the samesearch_keyworks for everyvehicle_idfrom that same search, so no per-vehicle re-derivation is needed.- Attraction review pagination is real page/pageSize paging, confirmed live end-to-end — 20 reviews per page, zero id overlap between pages.
- The attraction review filter schema is a genuinely separate endpoint from both the reviews and the search-result filters, confirmed live — and its rating filter genuinely narrows results (verified: a 5-star filter and a 1-star filter returned completely different review ids and ratings), not just an echoed-back parameter.
Pricing
Pay-per-event, billed on each successful call. See the Actor's Pricing tab for current rates.
Known limitations
- This Actor only wraps guest-accessible endpoints. No login flow is implemented or planned — features requiring a real Booking.com account (saved properties, writing reviews, booking) are out of scope by design.
Restaurants and attractions aren't covered. Booking.com's mobile app is hotel-focused — its car rental/flights/taxi tabs are separate integrations outside this Actor's scope, and no dedicated restaurant/attraction browsing surface was found in the app.Correction: found in a later pass. An earlier version of this README reported flights/car rentals/taxi/attractions as out of scope after the first build only covered hotels. All four turned out to be genuinely real, separate backends — see the Endpoints table above. Restaurant browsing specifically still wasn't found as a distinct surface in the app.- This is an unofficial, reverse-engineered integration, not affiliated with or endorsed by Booking.com B.V. Behavior may change if Booking.com changes its API.
Found a bug or have a feature request? Use the Issues tab on this Actor's page.