Booking.com Hotel Scraper – Prices, Room Rates & Reviews
Pricing
from $1.00 / 1,000 search results
Booking.com Hotel Scraper – Prices, Room Rates & Reviews
Scrape Booking.com hotel prices, room rates and availability via the mobile API. Full per-room rate table with itemised taxes and fees, family pricing by child age, guest reviews and property details — one actor, not four. Search by destination, GPS radius or hotel id. No API key needed.
Booking.com API Scraper – Hotel Prices, Rooms, Reviews & Availability
Scrape Booking.com at scale — extract hotels, live room prices, availability, full rate breakdowns, facilities, photos and guest reviews as clean, structured JSON. No login, no captchas, no browser automation to maintain. Just give it a destination and dates, and get back ready-to-use accommodation data you can export to CSV, Excel, JSON or the API.
Whether you're tracking competitor hotel prices, building a travel app, feeding a rate-shopping dashboard, or doing market research, this Booking.com data extractor turns the world's largest accommodation site into a structured feed.
Fast and reliable — calls Booking.com's own mobile app API (
mobile-apps.booking.com) directly instead of rendering pages, so it runs without browser automation or site login, and is dramatically faster and more stable than page-rendering scrapers. No partner contract needed — this Actor does not call the partner-gated Demand API and needs no affiliate ID, API key or partner approval. It reads Booking.com's public mobile app API and returns clean, search-style JSON.
What you can extract
- Hotel search results – every property for a city, region, free-text destination or GPS radius, with live total price, currency, and direct booking links.
- Live prices and itemised taxes – per-stay pricing with every tax and fee broken out (city tax, VAT, service charge, tourism fee, cleaning fee…), in the currency you choose.
- Family stays priced by child age – pass the children's ages and get the rates Booking would actually sell to your party, with family rooms surfacing and non-fitting rooms flagged.
- Rooms and availability – the full list of room types and bookable rates: occupancy, structured bed layout (sofa bed? how many beds?), bedrooms and bathrooms, size, board, cancellation policy, payment options, and how many rooms are left at each price.
- Availability status – for a fixed list of hotels you always get a record back, and it says why there is no price: sold out, minimum stay not met (with the required nights), closed, or unknown id.
- Guest reviews – paginated reviews with score, title, positive/negative text, date and reviewer country (fetch as many as you need per property).
- Property details – name, star rating, review score & count, GPS coordinates, address, 100+ named facilities, family amenities, languages spoken, house rules and photos.
Example use cases
- Hotel price monitoring & rate shopping – track competitor and market prices over time for revenue management.
- Family & group travel products – price stays correctly for parties with children, and only show rooms that fit.
- Travel & metasearch products – power a booking site, app or price-comparison tool with fresh inventory.
- Market & investment research – analyze pricing, occupancy signals, ratings and amenities across a destination.
- Review & reputation analysis – mine guest sentiment and review trends for any property.
- Lead lists & data enrichment – build accommodation datasets with geo, facilities and contact context.
Why this scraper, not a flat-listing one
Most Booking.com scrapers return one row per hotel with a single total price. That is enough to see who is cheapest today; it is not enough to do revenue management, price a family stay, or explain a number to a client. This actor returns the layer underneath:
- It returns the full per-stay price breakdown with every tax and fee itemised — city tax, VAT, service charge, tourism fee, cleaning fee — not one blended total.
- It prices family stays correctly by child age. Pass
childrenAgesand you get the rates Booking would actually sell to your party. A scraper that takes only a child count cannot do this, because Booking's pricing depends on the ages. - It returns every bookable room option per property, with occupancy, structured bed layout, board, cancellation policy, payment terms and how many rooms are left at each price.
- It tells you why a hotel has no price. Query a fixed list of hotel ids and you always get a record back, saying sold out, minimum stay not met (with the nights required), closed, or unknown id — instead of the property silently vanishing.
- It searches by GPS radius or bounding box, not just by destination name.
- It is one actor, not four. Search, property details, rooms and reviews come from the same run, so you do not chain a listing scraper into a separate reviews scraper and a separate photos scraper.
Compared with the alternatives
Prices are the vendors' own published per-event rates at the time of writing (BRONZE tier); check each Store page for current numbers.
| This actor | Typical flat-listing scraper | Reviews-only scrapers | |
|---|---|---|---|
| Rows per hotel | search row + details + every room rate | one flat row | n/a |
| Taxes & fees | each one itemised | blended total, or absent | n/a |
| Family pricing | by child age (childrenAges) | child count at best | n/a |
| Why no price | explicit status (sold out / min stay / closed / unknown id) | hotel just missing | n/a |
| Search by GPS radius | yes | rarely | n/a |
| Reviews | same run, $0.0001 each | separate actor | $0.0012 – $0.04 each |
| Per search result | $0.001 | $0.003 – $0.015 | n/a |
| Per-run start fee | none | $0.00005 – $0.10 | $0.00005 – $0.01 |
The per-run start fee matters more than it looks on a schedule: a fee charged per run is charged whether the run returns 2 rows or 2,000, so it falls hardest on exactly the small, frequent runs that price monitoring is made of.
How to use it
No coding required. Set up your search in the visual input form, then run it on demand, schedule it, or call it via the API and connect it to Make, Zapier, n8n, Google Sheets and more. Results land in a dataset you can download as JSON, CSV, Excel or HTML, or pull through the API.
Children / family stays
Child ages are supported — and required for correct family prices. Booking.com prices a stay by the age of each child (free cots, kids-stay-free rules, extra beds), so a party of 2 adults + children aged 2 and 9 pays a different price than 2 adults + teenagers, and a different one again than 4 adults. Give the actor the ages and it sends them on every request — the destination search, the hotel page and the room list — and every price you get back is for exactly your party.
Two equivalent ways to say it; the flat fields win when both are present:
{ "adults": 2, "rooms": 1, "childrenAges": [5, 9] }
{ "guests": { "number_of_adults": 2, "number_of_rooms": 1, "children": [5, 9] } }
Per-room guests.allocation[] ([{ "number_of_adults": 2, "children": [5] }, …])
is accepted too; the party is summed because the mobile API takes aggregate occupancy.
With children in the party:
- family rooms surface, and rooms that can't host the party are marked
fitsParty: false(and, by default, left out ofproducts), - each product carries
occupancy.requestedChildrenAgesso you can confirm the ages reached Booking, - the web
urlof every result includesgroup_children/ageparameters, so clicking through lands on the same party.
Verified on Hotel Hortus, Amsterdam (2026-12-10 → 12, EUR): 2 adults + children (2, 9) = 452.80, 2 adults + children (12, 15) = 603.73, 4 adults = 603.73 — the same 0.75 ratio the booking.com website shows.
Ready-made examples (one click, no setup)
Each of these is a published task: open it, press run, and it works with the input already filled in. Running one copies it into your own account, so you can change anything afterwards without affecting the original.
| Example | What it does |
|---|---|
| Rate shop your competitive set daily | Tracks a fixed compset by property ID, room by room, taxes itemised |
| Monitor hotel prices in Amsterdam | City-wide price monitoring with taxes and fees |
| Monitor hotel availability and sell-outs | Flags sold-out properties instead of dropping them, for spotting compression dates |
| Get full room rate tables with taxes in Tokyo | Every bookable rate per property, with board, cancellation terms and taxes |
| Collect guest reviews and reputation scores | Reviews plus per-category subscores: cleanliness, staff, location, value |
| Find the cheapest well-rated hotels in Barcelona | 8.0+ rated properties, cheapest first |
| Price family rooms in Rome by children's ages | Real family pricing, keeping only rates that fit the party |
| Scrape apartments and holiday homes in Lisbon | Self-catering supply with bedroom and bathroom counts |
| Find hotels within walking distance of a landmark | Coordinate search with a radius, nearest first |
None of them pins a date: check-in defaults to 30 days ahead, so every example returns live availability rather than going stale.
Which example matches my job?
| I want to… | Example | Key input fields |
|---|---|---|
| price a stay for a family and see which rooms fit | 1. Family stay with children | search, childrenAges, includeRooms |
| watch prices for a fixed list of hotels | 2. Price-monitor a fixed list of properties | hotel_ids, currency, includeExtraCharges |
| find the cheapest well-rated hotels in a city | 3. Cheapest well-rated hotels in a city | search, minReviewScore, maxPrice, sortBy |
| only get apartments / holiday homes | 4. Apartments and holiday homes only | accommodationTypes |
| pull guest reviews for competitor analysis | 5. Guest reviews | hotel_ids, includeReviews, maxReviews |
| search around a GPS point | 6. Radius search around coordinates | latitude, longitude, radius |
| enrich a property with everything static | 7. Full property details | includeDetails |
| know why a hotel has no price | 8. Sold out or minimum stay? | hotel_ids (always emits a record) |
Use cases
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
A family of two adults with a 5- and a 9-year-old wants a two-night stay in
Amsterdam and needs to know what it will actually cost them, per room type.
Passing childrenAges makes Booking price the party by age; includeRooms adds
the room list, and by default (onlyFittingProducts: true) products only holds
rates Booking would sell to this party. rooms still lists every room type, so
you can see which ones do not fit.
{"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, "minPriceFitting": 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, "minPriceFitting": 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, a 2-year-old as a child in an
existing bed); requestedAdults / requestedChildrenAges echo what you asked for.
The search-path price.total (599.17) is Booking's display price before the
listed taxes; price.total + extra_charges.excluded = the room's gross 799.9.
2. Price-monitor a fixed list of properties
You know the Booking ids of the properties you compete with and want their
headline price for a date, with taxes itemised, every morning. hotel_ids skips
the search and fetches each property directly; the top-level price is the
cheapest rate that fits 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, "currency": "EUR", "inclusion": "included" },{ "charge": "SERVICECHARGE", "name": "Service charge", "mode": "per_night", "unit_amount": 10, "total_amount": 20, "currency": "EUR", "inclusion": "included" }]},"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 are part of the displayed price. Through Apify Proxy (US datacenter) the same Mercure rate comes back as
total: 191.74with the same three charges underinclusion: "excluded"(extra_charges.excluded: 84.23); from an EU IP they areincludedandtotalis 275.97.total + extra_charges.excludedis the all-in amount in both cases, so compare that when monitoring across runs.
3. Cheapest well-rated hotels in a city
Find the five cheapest hotels in Amsterdam scoring at least 8 and costing at most €300 for the stay. Rating, price and sort are applied client-side on top of Booking's own result 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&checkout=2026-12-12&no_rooms=1&group_adults=2&selected_currency=EUR","deep_link_url": "booking://hotel/2374707?…"}
Name, address, star rating, review score, coordinates and the persuasion 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 type ids (201 = Apartments, 220 = Vacation Homes —
see the full table); via the API you can also pass the
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 have to guess it from the room name.
5. Guest reviews for competitive analysis
Pull the 50 most recent guest reviews of a property, in British English, to feed a
sentiment pipeline. Reviews are paginated 10 at a time, so maxReviews can go 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 is applied on the returned coordinates,
and paging stops as soon as 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 and is null where Booking has none
(as for the Amsterdam centre); latitude / longitude are always present.
7. Full property details for enrichment
One property, everything static: address, stars, review score, coordinates, the
complete facility list, photos, languages spoken, family amenities. On the
hotel_ids path the actor also looks the property up by its coordinates to fill
in the fields the hotel page itself lacks (web URL, star rating, review score,
accommodation type, 100+ 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", "Fitness center", "Non-smoking rooms", "Laundry", "… 106 more"],"familyFacilities": ["…"],"languagesSpoken": ["pl", "nl", "fr", "es", "en-gb", "de", "ar"],"isFamilyFriendly": false, "wifiReviewScore": 8.4,"mainPhotoUrl": "https://cf.bstatic.com/xdata/images/hotel/max1024x768/873579185.webp?…","photos": ["…"],"isBookingHome": null, "bedroomCount": null, "houseRules": null}}
For apartment-like properties details adds isBookingHome,
isSingleUnitProperty, bookingHomeGroup, the unit's bedroomCount /
bathroomCount and Booking's houseRules.
8. Sold out or minimum stay?
A property that cannot host the requested stay never shows up in a destination
search — that is Booking's behaviour. On the hotel_ids path the actor instead
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, "currency": "EUR" },"…" ] } },{ "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 one of available, min_stay_not_met (with
minStayNights), sold_out, closed, no_fit_for_party (rates exist but none
fits the party — 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
dates. Not-found records are free (no search-result charge). On the search
path, availability is { "status": "available" | "sold_out" } and the run log
reports how many results were dropped client-side by your filters or radius.
Input reference
| Field | Description |
|---|---|
search | Mode 1. Destination name (city, region, landmark) — e.g. "Amsterdam". Also resolves specific hotel names, but matching a full/exact property name isn't guaranteed — for a specific property, prefer hotel_ids. |
hotel_ids | Mode 2. Scrape specific properties by numeric Booking id instead of searching. Always yields one record per id (see scenario 8). |
cityId / regionId | Modes 3 and 4. Target a specific Booking destination by numeric id. Renamed from city/region; the old names still work. |
latitude / longitude / radius | Mode 5. Search around a GPS point, nearest first; radius in km is optional and applied client-side. |
swLat / swLon / neLat / neLon | Mode 6. Sweep a custom rectangle. All four corners required together. |
What a run does: one mode, and a sub-mode for search
Two dropdowns, answering different questions.
mode — what this run does. Either a search, or one enrichment surface for
properties you already have ids for:
mode | Does | Its own ids field |
|---|---|---|
search (default) | find properties and price them | hotel_ids (sub-mode below) |
rooms | room pricing and availability | hotelIdsRooms |
reviews | guest reviews | hotelIdsReviews (+ ufi) |
reviewScores | review score summary and subscores | hotelIdsScores |
surroundings | nearby places | hotelIdsSurroundings |
details | static property details | hotelIdsDetails |
Each mode has its own input group, and the mode dropdown sits above all of
them. Nothing is shared between two modes: every mode has its own Hotel IDs
field, and the options a mode needs are repeated in its group rather than
borrowed from another — rooms has its own "only rates that fit" and "itemise
taxes" switches, reviews its own "max reviews". A value left in one group
cannot change what another mode does, and filling in the wrong group is refused
by name:
Mode "rooms" works on properties you already have ids for.Put them in "hotelIdsRooms" (the Hotel IDs field in that mode's own group).
Inputs that several modes legitimately read sit above the groups, next to the
mode dropdown, rather than inside any one group where they would look
mode-specific: the stay dates, guests, currency and language. A Search prices
that stay, rooms re-prices it, and reviews uses it when no ufi is given.
The universal-but-rarely-touched settings — output shape, limits, file exports and the proxy — stay in their own groups at the end, so they do not sit between the mode dropdown and the mode groups.
hotel_ids still works as a fallback for every mode, so existing tasks and API
callers keep running unchanged.
searchBy — how a search finds properties. Six sub-modes of search, ignored
by the enrichment modes:
searchBy | Fill in |
|---|---|
auto (default) | anything — the sub-mode is inferred |
destination | search |
hotelIds | hotel_ids |
cityId / regionId | cityId / regionId |
point | latitude, longitude, optional radius |
area | swLat, swLon, neLat, neLon |
auto keeps the original behaviour: the sub-mode is inferred from whichever field
you filled in, and if you filled in more than one the run says which it used and
which it ignored — in the log and the status message — instead of choosing
silently:
You set 2 location modes. Used Hotel IDs; ignored destination name.
Precedence, highest first:
hotel_ids → cityId → regionId → point → bounding box → search.
Choosing a sub-mode explicitly drops the other sub-modes' fields, so a leftover
value cannot change where the run searches, and a sub-mode picked with nothing
filled in is rejected rather than falling through to another one's input.
searchBy was called searchMode; the old name still works.
Giving no location at all is rejected, with a message naming the fields you could set. It used to default to Amsterdam and bill you for 100 properties.
country was retired. Booking's mobile backend has no country-level search,
so the field could only ever produce an error. Cover a country by its regions, or
with a bounding box.
Flexible dates: a window instead of one stay
"The cheapest single night in the next 30 days" is a different question from
"this exact night", and checkin/checkout can only express the second. Set
windowDays and stayNights to ask the first:
// every single night in the next 30 days, for one hotel{ "searchBy": "hotelIds", "hotel_ids": ["1392565"],"windowDays": 30, "stayNights": 1,"outputFields": ["price", "availability"] }// two-night stays starting any day next week, across a destination{ "search": "Ghent", "windowDays": 7, "stayNights": 2, "maxItems": 200 }
One row per property per stay, each carrying its own checkin/checkout, so
the output is a rate calendar you can sort by price:
2026-09-26 -> 2026-09-27 total=150.58 available2026-09-27 -> 2026-09-28 total=98.10 available2026-09-28 -> 2026-09-29 total=134.10 available
The window starts today, or at checkin if you set one — a checkin already in
the past is pulled forward to today rather than sweeping dates Booking cannot
quote.
Each day in the window is a separate search, billed separately. A 30-day window costs roughly 30× a single-date run. Two things keep that in hand:
maxItemsis a budget across the whole sweep, not per day. The run says when it stops early:maxItems (3) reached after 1 of 5 stays; the rest of the window was not searched.windowDaysis capped at 60.
Only the search and rooms modes accept a window — the others return the same
answer whatever the dates, so sweeping one would bill the same record repeatedly,
and that is refused with an explanation rather than run.
Enrichment modes: re-check what you already have
Each enrichment mode calls the one Booking endpoint that surface needs and bills only that surface — never a search result. Measured on one property:
mode | Requests | Charged |
|---|---|---|
rooms | 1 | room-details=5 |
reviews | 2 (1 if you pass ufi) | review=3, review-scores=1 |
reviewScores | 1 | review-scores=1 |
surroundings | 1 | surroundings=1 |
details | 1 | hotel-details=1 |
search-result=0 in all five: an enrichment row carries one surface and no
property summary, so there is no search result to bill.
// re-price a comp set every morning, no search{ "mode": "rooms", "hotel_ids": ["1392565", "235613"],"checkin": "2026-11-20", "checkout": "2026-11-22" }// reviews without the price payload; ufi from an earlier search run{ "mode": "reviews", "hotel_ids": ["1392565"], "ufi": "-1958757", "maxReviews": 50 }// nearby places only{ "mode": "surroundings", "hotel_ids": ["1392565"] }
Which surfaces need a search at all, once you have hotel ids:
| Surface | Needs a search? | Turn on with |
|---|---|---|
| Price and availability | no | (always returned) |
| Rooms and rates | no | includeRooms |
| Guest reviews | no | includeReviews |
| Review scores and subscores | no | includeReviewScores |
| Nearby places | no | includeSurroundings |
| Static details | yes, one lookup per property | includeDetails |
Static details is the one exception: Booking's property endpoint carries no slug,
star rating, review count, property type or photo list, so on the search path
those are read from the search result for the same property, found by its
coordinates. mode: "details" skips that lookup and returns the static content
endpoint alone.
Why reviews wants a ufi. Booking's review endpoint returns nothing without
the destination's ufi, so the mode needs one. Paste it from an earlier search
run's output and each property costs a single request; leave it empty and one
extra lookup per property derives it. A ufi identifies a destination, so one
value covers every property in it.
Exports by mode: what Excel and KML actually contain
Both exports are built from the rows a run delivers, so what they hold depends on which mode produced those rows. The map export is empty in every enrichment mode — enrichment rows carry no coordinates, so there is nothing to place. Measured on one property, with both exports on:
mode | Excel sheets that fill | Map (KML) |
|---|---|---|
search | Properties, and Rates / Rooms / Reviews for whatever was included | works — one pin per property |
rooms | Rates (33 rows), Rooms (5 rows); Properties holds the id only | 0 placemarks |
reviews | Reviews (2 rows); Properties holds the id only | 0 placemarks |
reviewScores | nothing beyond the id | 0 placemarks |
surroundings | nothing beyond the id | 0 placemarks |
details | nothing beyond the id | 0 placemarks |
Two things follow.
The Properties sheet is near-empty in enrichment modes. It keeps its full
column set — name, stars, review score, address, coordinates — but an enrichment
row carries none of those, because fetching them is what the search path is
for. The row is there so the sheet's ids line up with the other sheets; do not
read it as "the property has no name".
Nearby places, review scores and static details have no sheet of their own. They are nested structures rather than tables, so they reach you through the dataset (JSON/CSV via the API or the Console), not through the workbook.
The run says so as it goes. A map export with nothing to place logs it rather than leaving you to open the file:
Map export ready (0 placemarks): ...1 property was left off the map for having no coordinates.
If you want a map of properties you have ids for, run mode: "search" with
searchBy: "hotelIds" — that path returns coordinates, so the pins land.
Modular output: take only the blocks you need
By default every record carries everything — pricing, property facts, rooms, reviews, scores and nearby places, around 28 top-level keys. That is right for exploring and wrong for a job that runs every morning and wants a price and an availability status.
outputFields narrows the record to the blocks you pick:
| Block | Keeps |
|---|---|
price | price, freeCancellation, geniusRate, dealBadges |
availability | availability (status, min stay, alternatives) |
property | stars, review score, address, coordinates, accommodation type |
rooms | rooms, products — the full rate table |
details | facilities, photos, house rules, languages |
reviews | reviews |
reviewScores | reviewSubscores, reviewSummary |
surroundings | nearby places |
id, name, url, the stay dates, the currency and datesAdjusted are always
kept, so rows stay joinable and re-checkable. datesAdjusted in particular is
never dropped: it says Booking served a different stay than the one you asked
for, which is what makes a price comparable or not.
Recipes:
// price monitoring — 12 keys instead of 28{ "searchMode": "hotelIds", "hotel_ids": ["1392565", "235613"],"outputFields": ["price", "availability"] }// availability checking only{ "searchMode": "hotelIds", "hotel_ids": ["1392565"],"outputFields": ["availability"] }// review mining, no pricing payload{ "searchMode": "destination", "search": "Ghent","includeReviews": true, "includeReviewScores": true,"outputFields": ["reviews", "reviewScores"] }
This changes what you receive, not what you are charged. Billing follows what
was fetched and delivered: the search still ran, so the search result is still
billed. To spend less, turn off the include* toggles so the extra requests are
never made in the first place — narrowing the output afterwards does not refund
work already done.
One exception worth knowing: if exportKml is on, coordinates are kept even when
you did not select the property block, because a KML without them is an empty
map.
Upgrading: what changed for existing runs
Search-mode runs are unchanged. A saved task sending search, dates, guests and
the include* toggles produces the same records, the same fields and the same
charges as before — verified by running the old and new builds side by side on
the same input and diffing the output structure property by property.
Three things did change, and only one of them can affect a run you already have scheduled:
- Two flags that did nothing now work — and are billed.
includeSurroundingswithoutincludeDetails, andincludeReviewScoreswithoutincludeReviews, used to be silent no-ops: flag on, no request, no data, no charge. They now fetch what you asked for, which means a run with one of those combinations starts returning data and paying the matching per-item charge. If you had one set by accident, turn it off. - No location is rejected instead of defaulting to Amsterdam. A run with no
search,hotel_ids, ids, point or area used to return 100 Amsterdam properties and charge for them. It now finishes with an explanation and charges nothing. countrywas retired. It never worked — Booking's mobile backend has no country-level search — so it only ever produced an error.
Renames are aliased, not breaking: city and region still work alongside
cityId and regionId. searchMode defaults to auto, which is the old
inference. outputFields left empty gives the full record, which is the old
shape.
How many properties can you actually get?
Booking's search stops returning new properties at roughly 1,000 per destination, and it does not tell you it has stopped: past that point it keeps answering with full pages of properties it has already sent. Every scraper built on this API inherits that ceiling.
deepSearch works around it by asking several narrower questions instead of one
broad one. The actor reads how many properties the destination actually holds,
splits it by star rating, and splits any slice still too large into price bands
- bisecting until every slice fits under the ceiling - then pages each one and merges the results. Every slice keeps the destination, so results never wander into a neighbouring city, and a property is returned, and billed, only once however many slices happen to find it.
Because Booking reports the destination's true total, a run can state its own
coverage rather than guess at it. The log ends with, for example,
5,822 of 5,844 properties (99.6%).
Measured 2026-09-23, check-in 2026-11-10, two nights:
| Destination | Available | Returned | Coverage | Slices |
|---|---|---|---|---|
| Singapore | 401 | 400 | 99.8% | none needed |
| New York | 522 | 519 | 99.4% | none needed |
| Jakarta | 2,659 | 2,636 | 99.1% | 10 |
| Tokyo | 5,844 | 5,822 | 99.6% | 28 |
Planning is cheap - Tokyo costs 54 one-row count queries - and a destination under the ceiling is detected in a single query, so a small town triggers none of this and costs exactly what it did before.
Two honest caveats. Slices overlap, because a property matches a price band if any of its room rates falls inside it, so the run fetches more rows than it delivers; de-duplication means you are never billed twice, but the requests are real. And the mobile API this actor uses holds slightly less inventory than booking.com's website - 5,844 against 6,084 for Tokyo - so 100% here means 100% of what the API offers.
What a destination covers, and what it does not
A destination is Booking's own idea of a place, and it can be narrower than the
name suggests. "New York" is a city destination holding ~520 properties; the
surrounding metro - Jersey City, Hoboken, Brooklyn, North Bergen - sits under
separate destinations and is not reachable through it.
Three destination shapes work, and free text resolves to whichever fits:
| input | example | notes |
|---|---|---|
search | "Bali", "Tokyo" | resolves to a city or a region automatically |
cityId | -2140479 | a numeric destination id, if you already know it |
regionId | 835 | a numeric region id - broader than a city |
Autocomplete matches what Booking has a destination for, which is not always what
you would guess: "Queens" resolves to Queenstown, New Zealand, while
"Manhattan", "Newark" and "Long Island City" resolve to nothing at all. The
run logs what it resolved to — read that line before trusting a sweep. For ground
Booking has no destination for, use the area corners.
For an area with no destination of its own, use latitude/longitude with a
radius: results come back nearest-first and are trimmed to the radius.
Two gaps worth knowing before you plan around them:
- Countries are not searchable. Booking's mobile backend has no country
destination, so
"Lithuania"resolves to nothing. Cover a country by its regions or cities instead. - Districts usually are not either.
"Shinjuku","Manhattan"and"Newark"all resolve to nothing, while"Brooklyn"and"Jersey City"are their own destinations. If a district fails, search its city.
When a run returns nothing
A run that could not have worked finishes successfully with an empty dataset and an explanation in its status message, rather than failing. You are not charged for it, and it does not count against the Actor's failure rate - a mistyped city is your input to fix, not a fault in the Actor.
You will see this for a date that will not parse or is in the past, a check-out
before its check-in, a destination that cannot be resolved, or hotel_ids that
are not numeric Booking ids. The status message names the problem in each case,
for example Nothing to scrape: could not resolve destination: 'Delfr'.
An empty dataset from a valid search means something different: the search genuinely matched nothing for those dates. Widen the dates or drop filters.
What each charge event pays for
Every optional surface that costs a separate API request is its own charge event, so you pay for what you actually asked for and nothing else:
| event | charged | covers |
|---|---|---|
| Search result | per accommodation returned | the property result with live pricing |
| Hotel details | per property | two requests - property page + static content - deliberately billed as one |
| Room details | per room option | the per-rate products list comes from the same request and is not charged again |
| Review | per review returned | the paginated review list |
| Nearby places | per property | includeSurroundings only |
| Review scores | per property | includeReviewScores only, one request regardless of review count |
A surface that fails or comes back empty is free - charging happens on delivery, not on the request.
Changed in 1.0.50.
details.surroundings,reviewSubscoresandreviewSummaryused to be fetched automatically withincludeDetails/includeReviewsand were not charged. They are now opt-in and billed separately. Runs that do not set the new toggles get cheaper and no longer receive those three fields; setincludeSurroundings/includeReviewScoresto keep them.
Accommodation types
accommodationTypes takes Booking's numeric type ids as strings ("201");
the snake_case spelling accommodation_types also accepts integers and the names
below (and common synonyms such as apartment, B&B, aparthotel,
holiday home, guest house, campsite, glamping), case-insensitively. Names are Booking's own en-us
labels, verified live on 2026-09-17 across 15 destinations; the accommodationType
field of every result uses the same labels.
| Id | Name | Also accepted as |
|---|---|---|
| 201 | Apartments | apartment, flat |
| 203 | Hostels | hostel |
| 204 | Hotels | hotel |
| 205 | Motels | motel |
| 206 | Resorts | resort |
| 208 | Bed and Breakfasts | B&B, bed & breakfast |
| 209 | Ryokans | ryokan |
| 210 | Farm Stays | farm stay, farmstay |
| 212 | Resort Villages | holiday park |
| 213 | Villas | villa |
| 214 | Campgrounds | campsite, camping |
| 215 | Boats | boat |
| 216 | Guesthouses | guest house |
| 218 | Inns | inn |
| 219 | Condo Hotels | aparthotel, apart-hotel |
| 220 | Vacation Homes | holiday home, vacation rental |
| 221 | Lodges | lodge |
| 222 | Homestays | homestay |
| 223 | Country Houses | country house |
| 224 | Luxury tents | glamping |
| 225 | Capsule Hotels | capsule hotel |
| 226 | Love Hotels | love hotel |
| 227 | Riads | riad |
| 228 | Chalets | chalet |
Output reference
Each record is a search-response object: id, currency,
checkin, checkout, deep_link_url, url, price, availability, plus the
free summary fields (name, accommodationType, starRating, reviewScore,
reviewsCount, address, city, district, countryCode, latitude,
longitude, freeCancellation, isPreferred…) and, when switched on, rooms,
products, reviews, details.
price — base (net), book / total (what you pay for the stay),
extra_charges.included / excluded (summed) and extra_charges.details[], one
entry per tax or fee: charge (CITYTAX, VAT, SERVICECHARGE, TOURISMFEE,
CLEANINGFEE, …), localised name, mode (percentage, per_night,
per_person_per_night, per_stay), percentage or unit_amount,
total_amount, currency, inclusion. On the search path total is Booking's
display price before the listed charges (total + extra_charges.excluded = the
gross rate; entries carry Booking's numeric chargeTypeId, no localised name);
on the hotel_ids path total is the rate as Booking displays it for the run's
point of sale (taxes included from an EU IP, excluded through a US proxy — see
the note in use case 2) and priced_block says which rate it came from.
total + extra_charges.excluded is always the all-in amount.
rooms[] — one entry per room type, always the full catalogue: id, name,
maxOccupancy, fitsParty, productCount, minPrice, minPriceFitting,
bedroomCount, bathroomCount, privateBathroom, beds[]
({type, typeId, count, name, label, size, configuration} with type one of
twin, double, queen, king, sofa_bed, bunk_bed), bedCount,
hasSofaBed, raw bedConfigurations, surfaceM2, photos, childrenPolicy
(maxChildrenFree, maxChildrenFreeAge), extraBedAvailable, extraBedPrice,
babyCotAvailable. Bed and bedroom data is taken from that room type only.
products[] — one entry per bookable rate: id,
room (join to rooms[].id), roomName, fitsParty, fitStatus, occupancy
(adults, children, childrenAges, requestedAdults,
requestedChildrenAges), maxOccupancy, bedroomCount, bathroomCount,
number_of_adults, children, number_available_at_this_price, deal,
policies (cancellation, meal plan, payment), price with itemised
extra_charges.included[] / excluded[].
Searching an area instead of a destination
Set swLat / swLon / neLat / neLon to sweep a rectangle. Use it when the
ground you want has no destination of its own — Booking's "New York" city
destination holds ~520 properties, while a box over the same map also reaches
Jersey City, Hoboken, Brooklyn and North Bergen.
It costs much more per property than a destination search. The area is
covered by point searches, and each one is answered with the properties nearest
its centre — including everything just outside your rectangle, which you pay
nothing for but which still consumes that search's result ceiling. A 21×28 km
box over New York took 30 searches to return ~1,000 properties; the same number
from a destination takes a handful. Keep boxes tight and set maxItems.
What it costs, measured. Same box and dates, properties actually inside the rectangle:
| area | size | searches | properties |
|---|---|---|---|
| Midtown Manhattan | 2×2 km | 1 | 169 |
| New York metro | 21×28 km | 14 | ~996 |
| Lithuania | 380×283 km | 27 | 4,624 (capped by maxItems) |
A small box can be finished in a single search; a country takes tens. The number of searches follows how far each one reaches, not how big the box is.
The limitation worth knowing before you rely on this. In a dense city centre
a search reaches only as far as the ~1,000-result ceiling allows — about 2 km in
Manhattan — so a large dense box can never be proved covered, and splitting it
further barely helps: going from 14 searches to 113 on the New York box moved
the count from 996 to 1,004, under 1%. For a dense city, a destination search
(search: "New York") with deepSearch is both cheaper and more complete; an
area sweep is the right tool when the ground you want has no destination, or
spans several.
What the run tells you about coverage. A destination search can say "5,822 of 5,844". An area search cannot — Booking reports no total for a coordinate query. Instead each cell reports how far its search actually reached against how far it needed to:
cell 7/128 (40.681,-73.881, depth 2): 6 new, reached 11.3 km of 4.4 needed
Reaching further than the cell's own corner means every property inside that cell was within range, so the cell is completely covered. When that holds for every cell, the run says so. When it does not, the run says that too, and names the reason — either the cell budget ran out, or the area stopped yielding because in a dense centre a search reaches only as far as the result ceiling allows, and no amount of further splitting gets past it.
Downloadable files: Excel and map exports
Two optional files, both off by default and both free — they reshape the data you already paid for and add no charge events. Switch either on and find it in the run's Storage → Key-value store tab when the run finishes.
Excel workbook (exportExcel) — an .xlsx with one sheet per section, so
nested data arrives as rows you can pivot instead of JSON crammed into a cell:
| Sheet | One row per | Created when |
|---|---|---|
| Properties | property — name, stars, review score, address, coordinates, price, availability, links | always |
| Rates | bookable rate — room, meal plan, cancellation terms, price, taxes | includeRooms |
| Rooms | room type — occupancy, beds, bathrooms, size, lowest price | includeRooms |
| Reviews | guest review — author, score, date, title, pros, cons | includeReviews |
Child sheets carry property_id, so a VLOOKUP (or a pivot) joins them back to
Properties. The header row is frozen and filtered.
Map file (exportKml) — a .kml with one placemark per property, ready to
open in Google Earth, Google My Maps or QGIS. Each pin's balloon carries the
total price, review score, address and a link straight to the property — and a
photo too when the run has includeDetails on, since the photo URL only comes
back with the property details.
Pins are grouped into folders by city, and kmlColorBy shades them by price
(this run's own quartiles — cheapest green, dearest red) or by review score
(fixed bands: 9+ green, 8–9 amber, 7–8 orange, below 7 red). Properties without
coordinates are skipped and the count is logged.
{"search": "Vilnius","checkin": "2026-11-10","checkout": "2026-11-12","includeRooms": true,"exportExcel": true,"exportKml": true,"kmlColorBy": "review_score"}
Pricing – pay only for the data you get
This scraper uses pay-per-event billing. You're charged only for results actually delivered — never for failed requests or unknown ids.
| You pay | Per | Equivalent |
|---|---|---|
| $0.001 | hotel search result | $1.00 / 1,000 |
| $0.001 | property details record | $1.00 / 1,000 |
| $0.0001 | room option | $0.10 / 1,000 |
| $0.0001 | guest review | $0.10 / 1,000 |
There is no per-run start fee — every charge above is for an item actually delivered. A plain search result costs a tenth of a cent; rooms, reviews and details add their tiny per-item charge only when you ask for them, so a lightweight price check stays extremely cheap and a full property profile is still a fraction of a cent. Unknown hotel ids and failed requests are not charged.
Apify platform usage (compute units, proxy, data transfer) is billed on top of the per-event prices, as shown on your run's usage tab.
Coming 8 October 2026
Two optional surfaces that are currently returned free start being charged, at the rates below. The four prices above do not change, and nothing you are already running gets more expensive unless you opt into these:
| You pay | Per | Equivalent | Opt in with |
|---|---|---|---|
| $0.0005 | nearby-places record | $0.50 / 1,000 | includeSurroundings |
| $0.0005 | review-scores record | $0.50 / 1,000 | includeReviewScores |
Frequently asked questions
Is there a Booking.com API, and do I need partner approval to use it?
Booking.com's official Demand API is partner-gated — you need a contract and an
affiliate ID. This actor needs neither: it reads Booking.com's public mobile app
API (mobile-apps.booking.com) and returns structured JSON, so you can get
hotel prices without an API key.
How do I scrape Booking.com hotel prices?
Give the actor a destination and dates and it returns every property that can host
the stay, each with its live total price, currency and booking link. Add
includeRooms for the per-room rate table and includeExtraCharges for the
itemised taxes and fees.
How do I get room rates and availability for a specific hotel?
Pass the property's numeric id in hotel_ids with your dates and set
includeRooms. You get every bookable rate — occupancy, bed layout, board,
cancellation policy, rooms left — and, when there is no price, an availability
status saying why.
Can I search hotels near a set of coordinates?
Yes. Set latitude, longitude and radius to search by GPS radius, or pass
neLat/neLon/swLat/swLon for a bounding box. Useful for "hotels within 2 km
of this venue" rather than "hotels in this city".
Which Booking.com scraper should I use for rate shopping or revenue management? One that returns rates per room rather than one price per hotel, because a blended nightly total cannot be compared across boards, cancellation policies or occupancy. This actor returns the full per-room rate table with taxes itemised, which is the level rate-shopping actually needs. See the comparison above.
Do I need a Booking.com account or API key? No. Just configure the input and run it.
Does it price children correctly?
Yes — pass the ages in childrenAges (or guests.children) and every request
carries them; see Children / family stays. Without
ages Booking prices the party as adults only.
Can I get prices in my own currency and language?
Yes — set currency and language to whatever you need.
How many reviews can I collect?
Reviews are paginated, so you can pull well beyond the first page — set
maxReviews to the number you want per property.
Can I scrape a specific hotel?
Yes — pass its Booking id in hotel_ids to fetch that property directly. This
must be the numeric internal id, not the URL slug or property name. To find
it: open the hotel's Booking.com page, use your browser's View source
(or right-click → View Page Source), and search for hotelId — the number
next to it is the id to use. An unknown id yields a record with
availability.status: "not_found" instead of silently vanishing.
Can I just put a hotel's name in search instead of finding its id?
You can, and it often works — the actor also tries to resolve a full hotel
name (e.g. one copied from a listing site) to the right property, with checks
in place to avoid confidently returning the wrong one. But name matching
isn't guaranteed to hit, and on ambiguous or unusual names the run may fail
with "Could not resolve destination" instead. Passing the numeric id in
hotel_ids is the reliable way to target one specific hotel.
Why is a hotel missing from my search results?
Booking's search only returns properties that can host the requested stay. To
learn why a specific property is missing (sold out, minimum stay, closed),
query it through hotel_ids and read availability.
Does it return phone numbers or email addresses? No. Booking.com hides direct property contact details until after a booking, so they aren't available from public data.
What formats can I export? Results are stored in a dataset and can be downloaded as JSON, CSV, Excel or HTML, or accessed via the API and integrations.
Is this an official Booking.com product? Does it use the Demand API?
No to both. It's an independent scraper that reads Booking.com's public mobile app
API (mobile-apps.booking.com); it does not call the partner-gated Demand API and
needs no affiliate ID, API key or partner approval.
Travel & booking toolkit
Part of the Travel & booking toolkit — search and pricing data across accommodation, transport, and travel-planning sites worldwide:
- Agoda API Scraper — Agoda search results, pricing and property details via GraphQL.
- Airbnb API Scraper — Airbnb listings, details, and reviews via GraphQL API.
- Hostelworld API Scraper — Hostelworld hostels & properties with full listing + property detail.
- FlixBus API Scraper — FlixBus trips between cities — times, stations, duration, prices.
- Changi Airport Timetable Scraper — Arrival and departure flight timetables from Changi Airport (SIN).
- eSIMDB Travel eSIM Scraper — Travel eSIM data plans from esimdb.com by country/region.
Did you find this useful?
Rate this actor on Apify! Your feedback helps other users find it and helps us keep improving it.
Legal & responsible use
Use this scraper to collect publicly available information only, in line with Booking.com's Terms of Service and applicable laws (including data-protection rules). Avoid collecting personal data without a lawful basis, and scrape at a reasonable rate. You are responsible for how you use the data you extract.