Travel
Booking.com Hotel Listings & Reviews Scraper
Structured Booking.com hotel data by destination and dates — price, currency, star rating, review score, room type, coordinates, and guest reviews — with geo-correct pricing you can trust, not a plausible-looking wrong-currency guess.
Free Apify credit covers a first run. No credit card to try.
What this Actor scrapes
For each run, this Actor works in one of two modes:
1. Search mode — pass a destination (plus check-in/check-out dates), and it opens Booking.com's search results for that window, capped at your maxHotelsPerSearch. 2. Direct-URL mode — pass a list of hotelUrls, and it visits each hotel's own detail page directly, independent of a destination search.
What we handle for you
- We clear the JS-execution gate Booking.com puts in front of raw HTTP requests — a hardened browser layer renders the page like a real visitor instead of bouncing off an automated bot-control challenge screen.
- We rotate proxy sessions on every block — a fresh exit IP and session id whenever a challenge or mismatch is detected.
- We verify the currency and locale actually match what you asked for before trusting a price — a wrong-geo page never gets emitted as if it were correct.
- We back off when the target pushes back. Partial successes surface with a clear status message — we never silently return an empty dataset.
- Per-hotel fault isolation — one dead page, timeout, or parse error skips that hotel with a logged warning; it never fails the whole run.
- Pydantic v2 input + output validation — every row is a typed, schema-enforced record; nullable fields are always
null, never silently dropped. - Pay-Per-Event pricing — you're charged per hotel row written to your dataset, plus a small per-review charge only when you opt into reviews.
Use cases
- OTA price intelligence — track how a set of hotels prices a given date range across markets.
- Revenue-management benchmarking — hotel revenue managers pull comparable listings to sanity-check their own pricing and positioning.
- Review-signal analysis — pull guest review scores and text at scale for sentiment or competitive analysis.
- Travel-agtech and itinerary tools — bulk-source structured hotel data (name, coordinates, star rating, price) to power a booking or comparison product.
Input
Paste this into the Apify Console, or send it as the run input over the API. Proxy settings are on by default; you rarely need to touch them.
| Field | Type | Required | What it does |
|---|---|---|---|
destination | string | no | Free-text destination (city/region) for search mode, e.g. "Paris, France". Leave blank if using Hotel URLs instead. |
checkin | string | no | Check-in date (YYYY-MM-DD). Required when Destination is set. |
checkout | string | no | Check-out date (YYYY-MM-DD), must be after Check-in date. |
adults | integer | no | Adults per room. |
rooms | integer | no | Number of rooms. |
maxHotelsPerSearch | integer | no | Cap on hotels returned per search. |
hotelUrls | array | no | Direct hotel-detail mode — one or more booking.com/hotel/...html URLs. Used alongside or instead of Destination. |
scrapeReviews | boolean | no | Also fetch guest reviews per hotel (best-effort). |
maxReviewsPerHotel | integer | no | Cap on reviews per hotel when Scrape reviews is enabled. |
countryCode | string | no | 2-letter ISO country code — proxy geo pin, passed to the proxy session. |
currency | string | no | 3-letter ISO 4217 currency code. |
sortOrder | string | no | Optional Booking.com search sort. |
{
"destination": "Paris, France",
"checkin": "2026-09-10",
"checkout": "2026-09-12",
"adults": 2,
"rooms": 1,
"maxHotelsPerSearch": 20,
"scrapeReviews": false,
"countryCode": "US",
"currency": "USD"
} Output
One row per result, schema-validated before it is written. Export JSON, CSV, Excel or XML from the run, or read it over the API.
hotel_namebooking_urladdresscitycountrylatitudelongitudestar_ratingreview_scorereview_countpricecurrencyroom_typethumbnail_urlreviews
{
"hotel_name": "H\u00f4tel Eiffel Trocad\u00e9ro",
"booking_url": "https://www.booking.com/hotel/fr/eiffel-trocadero.html",
"address": "35 Rue Benjamin Franklin, 75116 Paris",
"city": "Paris",
"country": "France",
"latitude": 48.8635,
"longitude": 2.287,
"star_rating": 4.0,
"review_score": 8.6,
"review_count": 1204,
"price": 189.0,
"currency": "USD",
"room_type": "Superior Double Room",
"thumbnail_url": "https://cf.bstatic.com/xdata/images/hotel/square200/....jpg",
"checkin": "2026-09-10",
"checkout": "2026-09-12",
"reviews": null
} Pricing
| Event | Price | When |
|---|---|---|
| Actor start | $0.20 | Once per run, covers warm-up and proxy session setup. |
| Hotel row | $0.0020 | Per result written to the dataset. |
| Review item | $0.0005 | Per result written to the dataset. |
You pay only for results that land. Cap any run with maxTotalChargeUsd. See pricing & billing for worked examples.
FAQ
Is this legal?
Why is a field `null`?
null when Booking.com doesn't expose that field publicly for a given hotel, or when a currency/locale mismatch caused the Actor to skip trusting that page's price.Do I need my own proxy?
proxyConfiguration is optional if you want to bring your own.Why did I get fewer rows than `maxHotelsPerSearch`?
Ready to run it?
Open the listing on Apify, paste the input above, and watch rows land. If it ever breaks, it is our problem before it is yours.
Related Actors