Booking.com Hotels Scraper
Pricing
from $0.42 / 1,000 property saveds
Booking.com Hotels Scraper
Scrape Booking.com hotels by place and dates: prices, availability, property details, rooms and guest reviews. Export to JSON, CSV or Excel.
Pricing
from $0.42 / 1,000 property saveds
Rating
0.0
(0)
Developer
Nice Dev
Maintained by CommunityActor stats
0
Bookmarked
7
Total users
3
Monthly active users
10 minutes ago
Last modified
Categories
Share
🏨 What is Booking.com Hotels Scraper?
Booking.com Hotels Scraper extracts hotels, apartments, villas and every other stay from Booking.com: name, price for your dates with taxes, availability, guest rating, address, GPS position and photos for a whole destination, a map point, a list of property names or ids, or any Booking.com search or property link you paste. Switch on the options you need to add the full property profile, every room offer, a day-by-day price calendar, guest reviews, the review summary, nearby places and the host or company contact details. It works as a Booking.com API alternative: run it on a schedule, call it from your code, or plug it into Make, Zapier or n8n.
Type a destination (Paris), pick your dates, guests and currency, click Start, and download the properties in JSON, CSV or Excel. No login, nothing to set up. Several destinations, property names, property ids, map points and links can run together in one run, and a search that holds more than 1,000 properties is read in full automatically.
📋 What data can you extract from Booking.com?
One item per property, 107 fields. The rows marked option are filled only when you tick the matching option; each option is charged on its own, only when ticked (see Pricing).
| Category | What you get |
|---|---|
| 🏨 Property | name, link, type (hotel, apartment, villa…), stars, host type — My Story Hotel Tejo, hotel, 3 stars |
| 💰 Price and taxes | price for the whole stay, price per night, crossed-out price, discounts, taxes to pay on site, currency — 156 EUR |
| 🛎️ Availability and conditions | available or sold out, free cancellation and its last date, rooms left, the room Booking.com recommends, the stay priced |
| ⭐ Ratings | guest score out of 10, its wording, number of reviews, score per category (staff, cleanliness, location…) — 9.1, Superb |
| 📍 Location | address, district, city, country, GPS, distance from the center in km and as Booking.com words it |
| 🖼️ Photos and badges | main photo (every photo with the full profile), deal badges, Preferred Partner, sustainability |
| 🧾 Full property profile (option) | description, amenities by group, house rules, check-in and check-out times, languages, licence numbers, chain, guests' questions and answers, full address with postal code, Genius and Travel Proud badges |
| 🛏️ Room offers (option) | every room and rate: size, beds, meals, price, taxes, cancellation, prepayment, rooms left |
| 📅 Price calendar (option) | day by day: bookable or not, indicative price of a one-night stay, minimum stay |
| 💬 Guest reviews (option) | rating, date, title, positive and negative text, traveler type, country, room, stay dates, the property's reply; number of reviews per language, traveler type and season |
| 🧠 Review summary (option) | Booking.com's own summary of the reviews, scores by topic and by traveler type |
| 🚉 Nearby places (option) | airports, landmarks, restaurants, public transport, beaches — name, category, distance, time on foot and by car |
| 🏢 Host contact (option) | company name, registration number, address, e-mail, phone; the name of a private host |
Every field, with an example, is listed in the Output section below.
A field of an option you did not tick is null, a list too (reviews, roomOffers, calendar, nearbyPlaces, reviewsByLanguage), never missing, so every row has the same columns: test for null before you read a list, except the lists of the full profile (amenities, highlights, meals), which are empty when the profile is not ticked.
✅ Why use Booking.com Hotels Scraper?
- 🌍 Many sources in one run: destinations, map point and radius, property names, property ids and pasted links, each with its own cap if you want one.
- 📈 Past the 1,000 results of a search: a big city is read in full (Rome holds more than 5,000 properties), without any setting.
- 🎯 Filters Booking.com applies itself: price, stars, rating, type, amenities, meals, free cancellation, distance, chains and any other filter of the site, so unwanted properties are never read nor charged.
- 💶 Your dates, guests and currency: prices are for your stay, with taxes and the taxes to pay on site detailed. Flexible dates are supported.
- 🧩 Pay for what you use: the base row is cheap and every heavy block (profile, room offers, calendar, reviews, review summary, nearby places, host contact) is an option, unticked by default.
- 🔔 Monitoring built in: tick Only new properties, schedule the Actor, and each run saves (and charges) only what it has never delivered before.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…), proxy rotation and JSON/CSV/Excel export via the Apify platform.
🚀 How to scrape Booking.com
- Create a free Apify account.
- Open Booking.com Hotels Scraper and type a Destination (a city, region, district, airport or landmark, e.g.
Paris). - Or paste your own Booking.com links into Start URLs (search results pages: their dates, guests, currency and filters are kept; or single property pages), or fill Property names, Property IDs, or a map point with Latitude, Longitude and Radius.
- Pick the stay (Check-in date, Nights, Adults, Currency) and set Max properties (100 by default, 0 = no limit) — and Max properties per search when you run several searches — then click Start.
- Tick the options you want (profile, room offers, calendar, reviews…) and download the dataset in JSON, CSV, Excel or via API.
💰 How much does it cost to scrape Booking.com?
This Actor uses pay per event pricing: a price per property saved plus a small fee per run start. The exact amounts, for every Apify plan, are on the Pricing tab of this page. Platform usage (compute, proxy) is included in the price.
Every option is unticked by default and charged only when ticked, per unit it delivers:
| Option | Charged per |
|---|---|
| Extract full property profile | property whose profile is read |
| Room offers (every room and rate) | room offer saved (a sold-out property has none and costs nothing for this option) |
| Price calendar | day saved |
| Include reviews | review saved |
| Include review summary | property that has a summary |
| Nearby places | property whose places are saved |
| Company / host contact details | contact found |
Filters Booking.com applies itself (price, stars, rating step, type, amenities, meals, free cancellation, distance, chains, raw filters, available only) cost nothing: the other properties are never read. A property dropped by a filter the Actor runs itself (exact rating, minimum reviews, excluded words or ids) costs a small filter fee instead of a full property price, see Pricing. Set the run option maximum cost per run to cap what a run can spend: the Actor stops saving rows when the cap is reached.
⚙️ Input
Search one destination for a stay that starts in 30 days:
{"location": "Paris","checkIn": "30 days","nights": 2,"adults": 2,"currency": "EUR","maxItems": 200}
Several destinations, only 4-star hotels with free cancellation, only the properties not delivered before:
{"locations": ["Rome", "Florence"],"propertyTypes": ["hotel"],"minStars": 4,"freeCancellationOnly": true,"maxItemsPerQuery": 500,"onlyNew": true,"stateKey": "italy-4-stars"}
Your own links and property names (a pasted search keeps its dates, guests and filters):
{"startUrls": [{ "url": "https://www.booking.com/searchresults.html?ss=Lisbon&checkin=2026-12-20&checkout=2026-12-22" },{ "url": "https://www.booking.com/hotel/fr/lutetia.html" }],"hotelNames": ["Lutetia Paris"],"maxItems": 500}
Properties around a map point, nearest first, until the first one beyond the radius:
{"latitude": 48.8584,"longitude": 2.2945,"radiusKm": 2,"adults": 2,"children": 1,"childrenAges": ["5"],"sortBy": "distance_from_search","maxItems": 100}
Three properties by id, with every option on (profile, room offers, calendar, reviews, review summary, nearby places, host contact):
{"hotelIds": ["535429", "59015", "6966158"],"checkIn": "120 days","nights": 2,"adults": 2,"currency": "EUR","language": "en-gb","maxItems": 3,"extractDetails": true,"includeRoomOffers": true,"maxRoomOffersPerHotel": 50,"includeCalendar": true,"calendarDays": 70,"includeNearbyPlaces": true,"includeHostContact": true,"includeReviews": true,"maxReviewsPerHotel": 30,"reviewsSort": "NEWEST_FIRST","includeReviewSummary": true}
| Field | Notes |
|---|---|
location, locations | A city, region, district, airport or landmark, as typed in the Booking.com search box (Paris, Tuscany, Orly Airport). locations adds more destinations: one search each. |
startUrls | Search results pages (https://www.booking.com/searchresults.html?ss=Paris&checkin=2026-12-20) or property pages (https://www.booking.com/hotel/fr/lutetia.html). Dates, guests, currency and site filters are kept. |
hotelNames | Properties named as Booking.com completes them (Lutetia Paris): each name is looked up before the run. Type the name without a first word such as "Hotel" if nothing is found. |
hotelIds | Booking.com numeric property ids (54642), the propertyId of a result. |
latitude, longitude, radiusKm | A map point (48.8584, 2.2945) and a radius in kilometres: both coordinates are needed, or neither. Results nearest first. |
checkIn, checkOut, nights, flexWindow | First night: a date (2026-12-20) or a period from the run date (7 days, 2 weeks, 1 year). Empty = a stay starting 30 days from the run date, and Booking.com takes bookings up to about 495 days ahead (a later date is refused). Check-out empty = check-in plus nights. Flexible dates move the stay by up to 7 days. |
adults, children, childrenAges, rooms | Guests and rooms for the whole stay; rooms not above adults (Booking.com needs an adult per room). One age per child in childrenAges (5), in the same order as on the site. |
currency | Currency of every price (EUR, USD, GBP…). A pasted search keeps its own currency. |
language | Language of the names, descriptions and labels (en-gb, fr, de…) when Booking.com has a translation. A pasted link keeps the language of its address (a language code before html such as fr, or lang=fr); a link with none uses this one. |
sortBy | The 10 orders of the site: popularity (default), price, price_from_high_to_low, class, distance_from_search, bayesian_review_score… Ignored for a map point (always nearest first) and for hotel names, property ids and property links (one property each). |
maxItems, maxItemsPerQuery | Stop after this many properties for the run (0 = no limit) and for each search (0 = no per-search cap). |
extractDetails | Option: the full property profile (description, every photo, amenities, house rules, licence numbers…). |
includeRoomOffers, maxRoomOffersPerHotel | Option: every room offer of each property for your dates, up to the cap per property (50 covers almost every property). |
includeCalendar, calendarDays | Option: day-by-day availability, indicative one-night price and minimum stay, from the check-in date, up to 365 days (nothing beyond about 495 days ahead). |
includeNearbyPlaces | Option: airports, landmarks, restaurants, public transport, beaches around each property. |
includeHostContact | Option: the company or host that runs each property, as Booking.com publishes it (see the FAQ on personal data). |
includeReviews, includeReviewSummary, maxReviewsPerHotel | Option: the guest reviews of each property up to the cap (0 = every review the site serves), and Booking.com's own review summary with the scores by topic. Either one also gives the number of reviews per language, traveler type and season and the topics guests mention, at no extra charge. |
reviewsSort | Order of the reviews: MOST_RELEVANT, NEWEST_FIRST, OLDEST_FIRST, SCORE_DESC, SCORE_ASC. |
reviewsLanguages | Keep only the reviews written in these languages, as two-letter codes (en, fr, de). |
reviewsTravelerType | Keep only one type of traveler: FAMILIES, COUPLES, GROUP_OF_FRIENDS, SOLO_TRAVELLERS, BUSINESS_TRAVELLERS. |
reviewsScore | Keep only one score band of Booking.com: REVIEW_ADJ_SUPERB (9+), REVIEW_ADJ_GOOD, REVIEW_ADJ_AVERAGE_PASSABLE, REVIEW_ADJ_POOR, REVIEW_ADJ_VERY_POOR. |
reviewsTimeOfYear | Keep only the stays of one season: _03_05, _06_08, _09_11, _12_02. |
reviewsSearchText | Keep only the reviews that mention a word or phrase (breakfast). |
reviewsAfter, reviewsBefore | Review date range: 2026-01-01, or a period before now (7 days, 3 months). 7 days on a schedule = the new reviews only. |
reviewsMinRating, reviewsMaxRating | Keep only the reviews scored between these two values (out of 10, 0 = no bound). |
minPrice, maxPrice, minStars, maxStars, minRating, minReviewCount | Price per night in the chosen currency, stars, guest score and review count. 0 = no filter. Price, stars and rating are asked from Booking.com; the exact rating and the review count are checked by the Actor. |
propertyTypes | Keep only these types: hotel, apartment, holiday_home, villa, guesthouse, hostel… |
amenities | Keep only properties that have ALL the ticked amenities (the form lists them by name; 107 is Free Wifi, 2 is Parking). |
mealPlan | Keep only properties with this meal option: breakfast, breakfast_dinner, kitchen. |
freeCancellationOnly, availableOnly | Free cancellation only (off by default); available properties only (on by default: sold-out properties are left out). |
maxDistanceFromCenterKm | Within this distance of the center, in the three steps of the site: 0.8, 1.6 or 3.2 km. |
chains | Keep only these brands, by name (ibis, Mercure) or brand id. |
rawFilters | Any filter of the site that has no field here, as Booking.com writes it in a search link (class=4;review_score=80, ht_id=204;hotelfacility=107; stay_type=2 keeps adults-only properties, 1 pets allowed, 4 LGBTQ+ friendly). Separate filters with a semicolon. |
excludeKeywords | Drop the properties whose name contains one of these words (hostel), case and accents ignored. |
excludePropertyIds | Booking.com property ids to skip even when they match (54642), for example your own hotels. |
onlyNew, stateKey, resetState | Monitoring: only the properties never delivered under this memory key (paris-hotels); resetState forgets the memory. |
| Advanced | proxyConfiguration (Apify proxy by default, included in the price; the residential proxy is not available), maxConcurrency, maxRequestsPerMinute, minRequestIntervalMs, maxRequestRetries, debugLog. |
📦 Output
One real item, from a run for Lisbon (stay of 2 nights, every option on). It is shortened: long texts are cut, lists keep their first entries, and about half of the fields are left out (the host contact among them); every field is listed below.
{"id": 39719,"propertyId": 39719,"name": "My Story Hotel Tejo","url": "https://www.booking.com/hotel/pt/my-story-tejo.html","pageName": "my-story-tejo","countryCode": "pt","propertyType": "hotel","starRating": 3,"starRatingType": "stars","rating": 9.1,"ratingText": "Superb","reviewCount": 4958,"ratingBreakdown": {"staff": 9.4, "services": 9.1, "cleanliness": 9.4, "comfort": 9.4, "valueForMoney": 8.9, "location": 9.8},"price": 156,"currency": "EUR","pricePerNight": 78,"taxesAndFeesExcluded": 0,"priceWithAllTaxes": 156,"isAvailable": true,"freeCancellation": false,"freeCancellationUntil": null,"recommendedRoom": {"name": "Double Room","beds": 1,"bedrooms": 0,"units": 1,"bathrooms": 0,"kitchens": 0,"livingRooms": 0},"stay": {"checkIn": "2026-12-01","checkOut": "2026-12-03","nights": 2,"adults": 2,"children": 0,"childrenAges": [],"rooms": 1},"address": "Rua Condes de Monsanto Nº2","formattedAddress": "Rua Condes de Monsanto Nº2, Santa Maria Maior, 1100-159 Lisbon, Portugal","postalCode": "1100-159","city": "Lisboa","country": "Portugal","latitude": 38.7136009994135,"longitude": -9.13665130734444,"distanceFromCenter": "250 m from centre","distanceFromCenterKm": 0.25,"images": ["https://cf.bstatic.com/xdata/images/hotel/max1024x768/304605677.jpg?k=290a15c841c998cc8817640cb06f58007d96d51ec3689f2c5208cd7812136163&o=","https://cf.bstatic.com/xdata/images/hotel/max1024x768/171205095.jpg?k=eebcfc8eb75c1e7644d38598751a9a01a7f2eef59bf7a9dfdfd1ec83bec61007&o="],"imageCount": 65,"hostType": "professional","description": "Set in the heart of the Baixa, My Story Hotel Tejo is a creative renovation of an historic building. It is in a prime location within Lisbon's histor…","nearbyPlaces": [{"name": "Humberto Delgado Airport","category": "Airports","distanceKm": 5.49,"distanceText": "5 km","walkTime": "1 hr 16 min","walkMinutes": 76,"driveTime": "7 min","driveMinutes": 7,"latitude": 38.7699,"longitude": -9.12951},{"name": "Cascais Municipal Airport","category": "Airports","distanceKm": 18.7,"distanceText": "18 km","walkTime": null,"walkMinutes": null,"driveTime": "16 min","driveMinutes": 16,"latitude": 38.7251052856475,"longitude": -9.35599040992859}],"calendar": [{"date": "2026-12-01", "available": true, "price": 78, "minNights": 1},{"date": "2026-12-02", "available": true, "price": 78, "minNights": 1}],"roomOffers": [{"offerId": "3971902_88531738_2_2_0","roomName": "Double Room","roomSizeSqm": 16,"maxOccupancy": 2,"mealPlan": "BREAKFAST_EXCLUDED","price": 156,"pricePerNight": 78,"priceBeforeDiscount": null,"currency": "EUR","taxesAndFeesIncluded": 23.92,"freeCancellation": false,"cancellationText": "Non-refundable","prepaymentText": "Pay the property before arrival","roomsLeft": 10,"breakfastPrice": 15}],"roomOfferCount": 28,"reviews": [{"reviewId": "9c06019b57488a26","rating": 9,"date": "2026-09-29T08:20:33.000Z","title": "wonderful experience","positive": "Unbelievably friendly staff. Everyone was so nice and helpful. From the moment we arrived…","negative": "Only one small problem was that housekeeping didn't always leave a full set of towels. Bu…","reviewerCountry": "United States","reviewerCountryCode": "us","travelerType": "SOLO_TRAVELLERS","roomType": "Double Room","nights": 4,"checkIn": "2026-09-24","checkOut": "2026-09-28","stayStatus": "stayed","helpfulVotes": 0}],"reviewsIncomplete": false,"reviewsByLanguage": [{"code": "it", "name": "Italian", "count": 595, "flag": "it"},{"code": "en", "name": "English", "count": 1566, "flag": "gb"},{"code": "de", "name": "German", "count": 527, "flag": "de"}],"reviewsByTravelerType": [{"travelerType": "FAMILIES", "name": "Families", "count": 1173},{"travelerType": "COUPLES", "name": "Couples", "count": 2462}],"reviewsBySeason": [{"season": "_03_05", "name": "Mar–May", "count": 1262},{"season": "_06_08", "name": "Jun–Aug", "count": 1432}],"reviewTopics": [{"id": 249, "name": "Location"},{"id": 270, "name": "Room"},{"id": 245, "name": "Breakfast"}],"reviewSummary": {"language": "en","basedOnReviews": 3763,"summary": "- Guests appreciated the <b>central location</b> near major attractions\n- <b>Breakfast</b> was gene…","pros": [],"cons": []},"rank": 2,"searchLocation": "Lisbon","searchUrl": "https://www.booking.com/searchresults.html?ss=Lisbon&checkin=2026-12-01&checkout=2026-12-03&group_adults=2&no_rooms=1&group_children=0&selected_currency=EUR&lang=en-gb&nflt=oos%3D1&page=1","totalResults": 3870,"cityId": -2167973,"scrapedAt": "2026-10-02T00:57:28.417Z"}
You can download the dataset in various formats such as JSON, HTML, CSV or Excel.
All 107 fields
| Fields | What you get |
|---|---|
id, propertyId, name, url, bookingUrl, pageName, countryCode | ids (id is a copy of propertyId), name, property page, the same page with your stay in the link |
propertyType, propertyTypeId, starRating, starRatingType | hotel, 204, 3, stars (tiles = Booking.com's quality rating for homes, circles = rating Booking.com shows as circles, not official stars) |
rating, ratingText, reviewCount, ratingBreakdown, externalRating, externalReviewCount | 9.1, Superb, 4958, score per category, outside review score and its number of reviews when the site shows one |
price, currency, pricePerNight, priceBeforeDiscount, discountPercent, discounts | price of the recommended offer for the whole stay, EUR, per night, crossed-out price, discount |
taxesAndFeesExcluded, taxesAndFees, priceWithAllTaxes | taxes to pay on site (null when Booking.com says charges may apply without an amount), every tax line, price plus those taxes |
priceInHotelCurrency, hotelCurrency, priceNote | the price in the property's own currency when it differs, the note under the price |
isAvailable, isClosed, roomsLeft, freeCancellation, freeCancellationUntil, noPrepayment, mealPlan, recommendedRoom | availability, rooms left, cancellation, prepayment, meals and room of the recommended offer |
stay, datesAdjusted | check-in, check-out, nights, guests, rooms priced; whether flexible dates moved the stay |
address, district, displayLocation, city, region, country, latitude, longitude | where the property is |
distanceFromCenter, distanceFromCenterKm, publicTransport, isCentral, isWithinBestLocationScoreArea | distance as the site words it and in km, nearest public transport, location flags |
mainImage, images, imageCount, badges, sponsored | photos (1024 px), deal badges, whether the result is an ad |
isPreferred, isPreferredPlus, isSustainable, sustainabilityCertifications, isNewlyOpened, isTpiExclusive, hostType | Booking.com badges; professional or private host |
formattedAddress, postalCode, isGenius, isTravelProud | option, full profile: the full address in one line, the postal code read from it (only where the format of the country is known), Genius programme and Travel Proud badges |
description, descriptionHtml, finePrint, highlights | option, full profile: description as text and as HTML, important information, highlights |
amenities, amenityGroups, meals, languagesSpoken | option, full profile: amenities flat and by group, meals served, languages of the staff |
checkInTime, checkOutTime, policies, questionsAnswers, averageResponseTime | option, full profile: times, house rules (children, beds, pets, payment, deposit), guests' questions with the answers (50 at most) |
licenseNumbers, licensePhrases, chain, brands, hostProfile | option, full profile: licence numbers, chain and brands, the host's own presentation |
hostContact | option, host contact: company name, trade register, registration number, address, e-mail, phone, name of a private host |
nearbyPlaces | option, nearby places: name, category, distance in km, time on foot and by car (text and minutes), GPS |
calendar | option, price calendar: date, available, indicative one-night price, minimum stay |
roomOffers, roomOfferCount | option, room offers: every offer (room, beds, meals, price, taxes, cancellation, rooms left) and how many Booking.com gave |
reviews, reviewsIncomplete | option, reviews: the reviews, and whether some could not be read |
ratingScores, scoreDistribution | option, reviews: score per category with the city average, number of reviews per score band |
reviewsByLanguage, reviewsByTravelerType, reviewsBySeason, reviewTopics | option, reviews or review summary: number of reviews per language, per type of traveler and per season, and the topics guests mention (Location, Breakfast…) |
reviewSummary, reviewTopicScores | option, review summary: Booking.com's summary, score per topic and per traveler type |
rank, searchLocation, searchUrl, totalResults, cityId, scrapedAt | position in the search, what the property was found for, the search page, properties of the search, city id, ISO timestamp |
💡 Tips
How to get more results
Set maxItems to 0: a search that holds more than 1,000 properties is cut into map areas automatically and read in full (those properties come without a rank and not in the order you asked). Give each destination its own cap with maxItemsPerQuery so that one big city does not use up the whole budget.
How to reduce costs
The price is per property plus what the options you tick deliver, so the levers are maxItems, maxItemsPerQuery, the filters Booking.com applies itself (a filtered-out property is never read), maxRoomOffersPerHotel, calendarDays and maxReviewsPerHotel, and onlyNew for recurring runs (you never pay twice for the same property). Leave an option unticked when you do not need it.
Several sources in one run
Fill locations, hotelNames, hotelIds, startUrls and / or a map point: the Actor runs one search per destination, name, id, link and map point. A property found by several searches is saved — and charged — once. Without maxItemsPerQuery the first searches can use up the whole maxItems budget.
Monitoring: only the new properties
Tick Only new properties (onlyNew) and schedule the Actor. The first run returns everything; each later run skips the properties already delivered: they are not saved, not charged, and their profile is not fetched. The memory lives in a named key-value store of your account (booking-hotels-scraper-seen, up to 150,000 properties per key) and is only updated with properties that really reached the dataset, so a failed run never hides anything. With Only new properties, a property that your own filters drop (exact rating, minimum reviews, excluded words or ids) is checked (and charged the small filter fee) once; the next runs with the same filters skip it for free. The exception is a property that does not pass a count that only grows yet (the minimum number of reviews): it is checked again on the next run, and charged the small filter fee again while it is still refused, so it is delivered as soon as it passes. Change a filter, or tick Reset the memory, to check them again. Give each schedule its own stateKey (two schedules sharing a key would hide each other's properties), and tick resetState once to start over. Booking.com has no "newest first" order, so a monitoring run still reads the whole search and saves only what it has not delivered before. To follow the new reviews of known properties instead, set reviewsAfter to a short period (7 days) with reviewsSort set to NEWEST_FIRST.
Choose the stay
Prices on Booking.com only exist for a given stay. With Check-in date empty the Actor uses a stay that starts 30 days from the run date, for 1 night, so a saved task never goes stale; use a period such as 60 days to keep the same distance ahead.
🔌 Integrations and API
Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.
🤖 Use with AI agents (MCP)
AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the Apify MCP server, billed to their Apify account like any run. It returns one item per Booking.com property. Actor id: nice_dev/booking-hotels-scraper; MCP server with this Actor only: https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/booking-hotels-scraper.
Smallest input, for a cheap first call:
{"location": "Paris","maxItems": 10}
Key output fields: name, url, starRating, rating, reviewCount, price, currency, isAvailable and address. The options (roomOffers, calendar, reviews…) are null unless ticked.
Cost: see the pricing section above and the Pricing tab. Cap each call with maxItems and, through the API, with the run option maxTotalChargeUsd.
❓ FAQ
Is it legal to scrape Booking.com?
The Actor only reads what Booking.com shows publicly to any anonymous visitor. It logs in to nothing and solves no captcha. Results can contain personal data (a reviewer's first name and country, the name of a private host), which is protected by GDPR: do not store it without a legitimate reason. The host contact option returns business contact details that Booking.com publishes for trader traceability; you stay responsible for how you use them (marketing, GDPR). You are responsible for using the data in compliance with Booking.com's Terms of Use and applicable law. This Actor is not affiliated with Booking.com.
Does it need a login or a proxy?
No login. The proxy is included in the price: leave the default setting (the residential proxy is not available). A request the site turns away is retried at once on a new proxy session, up to 10 times on top of the retries (without a proxy, after a pause of 5 seconds, doubled at each retry up to 150 seconds).
Are the prices the ones I see on Booking.com?
They are the prices Booking.com shows to a visitor who is not logged in, for the stay and the currency you asked for: price is for the whole stay with the taxes Booking.com includes, taxesAndFeesExcluded is what is paid on site on top, and priceWithAllTaxes is the sum. When Booking.com only writes that additional charges may apply, without an amount (often the city tax per person), both are null and priceNote carries its words. In some markets Booking.com shows visitors who are not logged in a price that already takes off a Genius member discount, with a "log in to get this price" note: price is that shown price, and the discount is listed in discounts (its name says Genius), so you can add it back for the price without an account (isGenius, with the full profile option, only says whether the property takes part in the programme). Prices are live: two runs a few minutes apart can differ.
Is the data safe to open in Excel or to show on a web page?
Names, descriptions and review texts are written by third parties, copied as they are. A text can begin with -, +, = or @: Excel and Google Sheets may read such a cell of a CSV file as a formula or as a number. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import the text columns as text. descriptionHtml (full profile option) and the review summary carry the HTML markup Booking.com sends, and the Actor does not sanitize it: strip or escape it before showing it on a web page, and escape every other field like any text written by a stranger.
Known limitations
- Dates: with no check-in date the stay starts 30 days after the run date and lasts 1 night (or the Nights you set). Booking.com gives no price without dates, so there is no "no dates" mode.
- Currency and language: Booking.com converts the prices to the currency you ask for. If a search comes back in another currency, the log says so and
currencytells which one the prices are in. Every amount has the decimals of its currency (whole numbers in JPY or KRW, cents in EUR or USD), as Booking.com shows it. Names, descriptions and labels come in the language you pick when Booking.com has them in it; reviews and guests' questions stay in the language of their author. - Distances come as Booking.com words them in the language asked (miles with
en-usfor instance);distanceFromCenterKmand the distances ofnearbyPlacesare always converted to kilometres. - Calendar prices (option) are indicative: the price of a day is the price of a stay of ONE night that starts that day, for one room and the guests you asked (asking for 2 rooms does not change it), rounded to the unit, and it is the same whatever
nightsis. In Europe it usually equals the bookable price rounded; it can differ, because Booking.com may leave some discounts in (a New York hotel showed 418 against 282.52 bookable). The exact price of your stay isprice. - Room offers (option): the
priceof an offer is for ONE room of that type for the whole stay. With 2 rooms asked each offer still shows the price of one room, whilepriceof the row is the total of all the rooms asked. - Property by link, name or id:
regionis empty, and so arerankandtotalResults. The property appears only if Booking.com lists it for your dates: otherwise the log says it is sold out or not bookable for them. - Names: Booking.com completes a name from its start ("Lutetia Paris", not "Hotel Lutetia Paris"). When no property has exactly that name the closest one is taken and the log says so, with its id.
- Reviews: a property's reviews are saved up to 6 MB per row; past that the row is saved with the reviews read so far and
reviewsIncompleteistrue. WithmaxReviewsPerHotelat0("every review") the maximum cost of the run counts 5,000 reviews per property. Filters Booking.com does not apply itself (review dates, exact rating range) are applied by the Actor: after 1,000 reviews read and dropped for a property it stops reading its reviews and the row saysreviewsIncomplete. With the newest first order andreviewsAfterit stops by itself at the first review that is too old. With many reviews per property the Actor reads fewer properties at a time so the run fits in its memory (the log says so): more memory means more properties at a time. For every review (0) or several thousand reviews per property, give the run more memory (Run options → Memory): when it is too small, the log says so at the start, with the memory to give. - Genius prices are never returned (a logged-in account is needed).
- Filters the site does not know (a wrong
rawFiltersvalue) are ignored by Booking.com without an error: the log warns when a filter you set was not applied, and the results are then NOT filtered by it. - 1,000 results per search is what Booking.com serves; the Actor goes past it for a destination or a link by cutting the map into areas, and the properties found that way come without
rankortotalResults, withoutdistanceFromCenter(Booking.com gives a distance from the centre of a place, not from a map area) and not in the order asked. A city search keeps only the properties of that city (the map areas reach into the towns around it: those are left out, not saved, not charged, and counted in the summary of the log); for a country or a region it keeps those of its country; for a district, a landmark or an airport there is no such rule, so a few properties just beyond its edge can come back. A search by map point (latitude,longitude,radiusKm) is not cut: it gives at most the 1,000 nearest properties. The count of a search moves by a few units between two calls (live availability), and Booking.com repeats a few properties from one page to the next: each property is saved once. onlyNewremembers property ids, not their content: a property whose price changed is not returned again, and a property your filters dropped is not checked again while the filters stay the same, except for the minimum number of reviews (a property under the minimum is checked again on the next run, as its reviews may have grown).- Two runs sharing the same
stateKeyat the same time may both return the same new property.
A run that reaches its timeout stops itself about 45 seconds before it: no new page is asked, what it read is saved and, with onlyNew, remembered, and the run ends Succeeded with "Stopped before the run's timeout". Resurrect it to go on from there, or give the next run a longer timeout (Run options).
A run the platform stops without warning (out of memory)
- Resurrect it: it goes on from where it stood at most a minute before the stop. What it had read since is read again, and the properties already saved are skipped: none is delivered or charged twice, and
maxItemsstill counts them. - With
onlyNew, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the properties it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the properties of its last 2 seconds once more.
Something doesn't work?
The last line of the log counts the properties saved, filtered out and no longer on Booking.com (removed while the run was reading them), and the requests that failed after every retry. Those requests and the removed properties are listed, with the reason, in the FAILED_REQUESTS record of the run's key-value store. The line also counts the hotel names and property links of your input that Booking.com does not have: they are skipped with a warning in the log and the other sources are read. A run that saved nothing and had failed requests fails, and its last message gives the cause.
If Booking.com changes its pages, you are told instead of paying for blank rows. A results page that counts properties but gives none the Actor can read is an error (listed in FAILED_REQUESTS), never a quiet "No properties found". If the first 20 properties read all lack their name or their type, the run saves nothing more, stops and fails, and its last message names the missing field: at most those first properties are charged. A run of fewer properties (a scheduled onlyNew run that finds a few new ones, a small Max properties) is checked at its end, from 5 properties: its properties are already saved, and the run fails with the missing field instead of ending green.
🛟 Support
Open an issue in the Issues tab with a link to your run: the run log and the FAILED_REQUESTS record of the key-value store show exactly which requests failed and why.