Day-level bookability over a window, optionally with timeslots. Each timeslot date is a separate upstream request, capped at 14.
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.
Modes: attractionAvailability
Dataset view: attractionAvailability — ?view=attractionAvailability on the items API, or the matching tab in the Console.
Day-level bookability over a window, optionally with timeslots. Each timeslot date is a separate upstream request, capped at 14.
20 columns, in the order the view shows them.
| # | Column | Label | Type | Description | Example |
|---|---|---|---|---|---|
| 1 | scrapedAt | Scraped at | string, nullable | When the response that produced this row came back - the PRICED response where the row has a price, not when the row was pushed, which is batched and later by seconds to minutes. ISO-8601 UTC, to milliseconds. Note Booking’s own date strings in the same row are NOT ISO (freeCancellationUntil is “2026-10-28 23:59:59 +0000”), so do not point one parser at both. Prices are fetched live - nothing in this Actor is cached or reused - so this is the age of the price, and a dataset read a week later does not refresh it. | 2026-10-27T12:53:42.118Z |
| 2 | scrapedAtUnix | Scraped at (epoch) | integer, nullable | The same instant as scrapedAt, in epoch SECONDS, for consumers that diff timestamps arithmetically. Two keys rather than one selectable format, so a column’s type never moves with a run setting and two datasets always join. | 1793105622 |
| 3 | attractionId | Attraction ID | string, nullable | Booking’s attraction product id. | PRDF8MpWklG6 |
| 4 | provenance | Provenance | object, nullable | What produced this row’s price: the proxy exit it was fetched through, the generation of that exit, the currency you asked for and the endpoint that priced it. The point of sale follows the proxy exit country, not any input - bookerCountry was removed in this build because nothing read it. | |
| 5 | status | Status | string, nullable | Rates mode: “available”, “not_offered” or “lookup_failed” - the last means we could not ask, the middle means Booking answered and the rate is not on sale. attractionAvailability mode: null means dates were bookable inside your window; no_availability_in_window is the real negative - days were checked and none were bookable; window_outside_calendar means the attraction is real but your window falls outside the span Booking publishes, so nothing was checked at all and calendarFrom/calendarTo give that span; not_found means the id resolved to nothing. That last one is INFERRED rather than reported: Booking answers an unknown id with a successful but empty calendar rather than an error, so an empty calendar is the discriminator - and it also covers an attraction withdrawn from sale. Telling the three negatives apart matters, because only the middle one means the attraction has no dates for you. | available, not_offered |
| 6 | error | Error | string, nullable | Attractions modes: the upstream message when an id could not be looked up. | Not Found (attractions backend 404) |
| 7 | windowStart | Window start | string, nullable | Start of the window you asked about. | |
| 8 | windowEnd | Window end | string, nullable | End of the window you asked about. | |
| 9 | bookableInWindow | Bookable in window | boolean, nullable | Whether any day in the window is bookable. | |
| 10 | availableDayCount | Available days | integer | number, nullable | Bookable days inside the window. | |
| 11 | unavailableDayCount | Unavailable days | integer | number, nullable | Checked days that are not bookable. | |
| 12 | daysChecked | Days checked | integer | number, nullable | Days of the calendar inside your window. | |
| 13 | firstAvailableDate | First available | string, nullable | Earliest bookable day in the window. | |
| 14 | lastAvailableDate | Last available | string, nullable | Latest bookable day in the window. | |
| 15 | availableDates | Available dates | array, nullable | Dates bookable in the window. | |
| 16 | calendarFrom | Calendar from | string, nullable | First day Booking publishes for this product. | |
| 17 | calendarTo | Calendar to | string, nullable | Last day Booking publishes for this product. | |
| 18 | timeslotDatesFetched | Timeslot dates fetched | integer | number, nullable | How many dates timeslots were fetched for, capped by attractionsTimeslotDays (default 3, maximum 14). Each one is a separate upstream request. | |
| 19 | timeslots | Timeslots | array, nullable | Every timeslot on the fetched dates, with its offers, ticket types, prices and remaining inventory. | |
| 20 | recordType | Record type | string, nullable | Which kind of row this is. Absent on property rows (search, rooms, details, surroundings, reviews, reviewScores); “rate” in mode rates; “attraction”, “attractionDetail” or “attractionAvailability” in the attractions modes. One dataset can hold several kinds, so filter on this before reading kind-specific columns. | rate, attraction |
Some columns above carry an object, or a list of objects, with documented members of their own. Each table below lists the members documented at ONE level; a member that is itself an object names the table it continues in, and [] in a path means a list.
row
└─ provenance
provenance — Provenance
Parent chain: row → provenance
What produced this row’s price: the proxy exit it was fetched through, the generation of that exit, the currency you asked for and the endpoint that priced it. The point of sale follows the proxy exit country, not any input - bookerCountry was removed in this build because nothing read it.
| # | Field | Label | Type | Description | Example |
|---|---|---|---|---|---|
| 1 | exitCountry | Exit country | string, nullable | ISO country of the proxy exit this row was fetched through, sampled once per proxy generation from Apify’s own request echo. This is the market that priced the row: on the hotel_ids path taxes come back inside the display price from an EU exit and excluded through a US one. Null when the run’s pool rotates per request (a residential proxy with no session), when the probe failed, or past the per-run probe budget - null means not established, not “no market”. Pin country-XX or a session in the proxy configuration to make it exact for every row. | US, GB |
| 2 | proxyGeneration | Proxy generation | integer, nullable | Which exit fetched this row, counted from 0. The retry ladder draws a fresh exit when one fails - six generations in 30 seconds on one measured run - so two rows of one dataset can honestly carry different tax treatment. RUN_SUMMARY.request.exitCountries lists every generation and its country. | 0 |
| 3 | currencyRequested | Currency requested | string, nullable | The currency you asked for, beside the honoured currency. Not recoverable from the row otherwise: HOTEL resolves to the property’s own code, which the row then states as its own currency - so a row quoting MYR could have been asked for as HOTEL or as MYR. | EUR, HOTEL |
| 4 | surface | Surface | string, nullable | The endpoint that produced this row: search (the destination search), roomList (the per-property rate list) or hotelPage (the by-id path). The surfaces disagree in documented ways - roomList carries the structured meal price and hotelPage does not - so a buyer comparing two rows needs to know which answered. | roomList, hotelPage |
Captured from a live run. Lists are cut to two entries and deep nesting is elided — the shape is real, the bulk is not.
{
"status": null,
"recordType": "attractionAvailability",
"attractionId": "PRlcMuKM2k7R",
"windowStart": null,
"windowEnd": null,
"availableDates": [
"2026-10-24",
"2026-10-25",
"... 177 more"
],
"availableDayCount": 179,
"unavailableDayCount": 2,
"daysChecked": 181,
"bookableInWindow": true,
"firstAvailableDate": "2026-10-24",
"lastAvailableDate": "2027-04-20",
"calendarFrom": "2026-10-23",
"calendarTo": "2027-04-21",
"timeslots": [
{
"date": "2026-10-24",
"timeSlotId": "ATS-PRlcMuKM2k7R-202610240900-nullnull",
"start": "2026-10-24T09:00:00+03:00",
"fullDay": false,
"offerId": "OF5sZQfwtNtx",
"offerLabel": "Vilnius: The Women of Vilnius 2-Hour Tour",
"ticketLabel": "Adult",
"ticketType": "adult",
"ticketsAvailable": 10000,
"minPerReservation": 4,
"maxPerReservation": 4,
"price": 149,
"currency": "USD"
},
{
"date": "2026-10-24",
"timeSlotId": "ATS-PRlcMuKM2k7R-202610240900-nullnull",
"start": "2026-10-24T09:00:00+03:00",
"fullDay": false,
"offerId": "OF5sZQfwtNtx",
"offerLabel": "Vilnius: The Women of Vilnius 2-Hour Tour",
"ticketLabel": "Adult",
"ticketType": "adult",
"ticketsAvailable": 10000,
"minPerReservation": 3,
"maxPerReservation": 3,
"price": 199,
"currency": "USD"
},
"... 328 more"
],
"timeslotDatesFetched": 3
}