Booking.com Hotel & Price Scraper
Pricing
from $2.50 / 1,000 results
Booking.com Hotel & Price Scraper
Scrape hotel search results from Booking.com — prices, ratings, reviews, availability, and location. Filter by star rating, price range, and sort order. Supports 10 currencies. Hybrid API + HTML extraction for maximum reliability. Ideal for price monitoring and market research.
Pricing
from $2.50 / 1,000 results
Rating
0.0
(0)
Developer

Tomáš Gregorovič
Actor stats
0
Bookmarked
1
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Scrape hotel search results from Booking.com with structured data including prices, ratings, availability, location, and amenities. Export to JSON, CSV, or Excel.
Features
- Dual extraction engine: API interception (primary) + HTML fallback for maximum reliability
- Fast & Enriched modes: Quick search-only scraping (default) or deep detail page extraction with room options, full amenities, review breakdowns, and photos
- Anti-detection: Browser fingerprint spoofing, user-agent rotation, viewport randomization, stealth scripts
- Proxy support: Built-in residential proxy rotation with Apify Proxy (RESIDENTIAL group recommended)
- Smart pagination: Offset-based with configurable max results (up to 1,000 hotels)
- Advanced filters: Property type, minimum review score, children with ages, star rating, price range
- CAPTCHA detection: Automatically detects and backs off on CAPTCHA pages with retry logic
- Rich data output: 20+ fields per hotel including GPS coordinates, price breakdowns, availability, and optional detail data
- Production error handling: Clear failure reporting via
Actor.fail()with descriptive status messages - Graceful degradation: If a detail page fails (CAPTCHA, timeout), search data is still pushed
Use Cases
- Price monitoring: Track hotel pricing trends over time by scheduling daily or weekly runs. Compare rates across destinations and date ranges to identify pricing patterns.
- Competitive analysis: Benchmark your property against competitors in the same destination. Monitor review scores, pricing strategies, and availability across the market.
- Market research: Analyze hotel supply in a destination — count properties by star rating, average price per night, and review scores to assess market saturation.
- Travel deal alerts: Combine with Apify webhooks to get notified when prices drop below a threshold. Automate deal-finding across multiple destinations.
- Academic research: Collect structured hospitality data for tourism studies, pricing elasticity research, or geographic analysis of accommodation supply.
Fast vs. Enriched Mode
| Fast Mode (default) | Enriched Mode | |
|---|---|---|
| Input | enrichData: false | enrichData: true |
| Speed | ~50–100 hotels/min | ~10–20 hotels/min |
| Data source | Search result cards only | Search cards + detail pages |
| Fields | 14 base fields | 14 base + room options, full amenities, review breakdown, photos, description |
| Cost | Lower (fewer requests) | Higher (1 extra page per hotel) |
| Best for | Price monitoring, market overview | Competitive analysis, full property comparison |
Input Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
destination | string | Yes | — | City, region, or property name |
checkIn | string | Yes | — | Check-in date (YYYY-MM-DD) |
checkOut | string | Yes | — | Check-out date (YYYY-MM-DD) |
adults | integer | No | 2 | Number of adult guests |
rooms | integer | No | 1 | Number of rooms |
children | integer | No | 0 | Number of children (requires childrenAges) |
childrenAges | array | No | [] | Ages of children (0–17), one per child |
currency | string | No | USD | Currency code (USD, EUR, GBP, CZK, etc.) |
language | string | No | en-us | Booking.com language code |
maxResults | integer | No | 100 | Max hotels to return (1–1,000) |
sortBy | string | No | price_low | Sort order: price_low, price_high, rating, review_score |
minPrice | integer | No | — | Min price per night filter |
maxPrice | integer | No | — | Max price per night filter |
starRating | array | No | [] | Filter by star ratings, e.g. [3, 4, 5] |
propertyType | array | No | [] | Filter by type: hotel, apartment, hostel, resort, villa, guesthouse |
minReviewScore | number | No | — | Minimum review score (0–10) |
enrichData | boolean | No | false | Enable detail page scraping for richer data |
detailTimeout | integer | No | 30 | Detail page load timeout in seconds (5–120) |
proxyConfig | object | No | Apify RESIDENTIAL | Proxy configuration |
Example Input (Fast Mode)
{"destination": "Prague, Czech Republic","checkIn": "2026-03-15","checkOut": "2026-03-18","adults": 2,"rooms": 1,"currency": "EUR","maxResults": 50,"sortBy": "price_low","starRating": [3, 4, 5]}
Example Input (Enriched Mode)
{"destination": "Barcelona, Spain","checkIn": "2026-04-10","checkOut": "2026-04-14","adults": 2,"children": 1,"childrenAges": [8],"currency": "EUR","maxResults": 20,"enrichData": true,"propertyType": ["hotel", "resort"],"minReviewScore": 8.0}
Output
Each hotel record contains structured data. The data_source field indicates whether the record was enriched with detail page data.
Fast Mode Output (data_source: "search")
{"hotel_id": "12345","name": "Grand Hotel Prague","url": "https://www.booking.com/hotel/cz/grand-prague.html","price": {"per_night": 142.00,"total": 426.00,"currency": "EUR","original_price": 178.00,"discount_percent": 20.0},"rating": {"score": 8.7,"review_count": 3421,"review_word": "Fabulous"},"location": {"address": "Kralodvorska 4, Prague 1","city": "Prague","country": "Czech Republic","latitude": 50.0875,"longitude": 14.4280,"distance_from_center": "0.3 km from center"},"stars": 5,"property_type": "Hotel","amenities": ["Free WiFi", "Spa", "Restaurant"],"images": ["https://cf.bstatic.com/xdata/images/hotel/max1024x768/123456.jpg"],"availability": {"rooms_left": 3,"free_cancellation": true,"no_prepayment": false,"deal_badge": "Genius discount"},"check_in": "2026-03-15","check_out": "2026-03-18","scraped_at": "2026-02-06T14:30:00Z","data_source": "search","detail": null}
Enriched Mode Output (data_source: "search+detail")
When enrichData is enabled, the detail object is populated with data from the hotel's detail page:
{"hotel_id": "12345","name": "Grand Hotel Prague","url": "https://www.booking.com/hotel/cz/grand-prague.html","data_source": "search+detail","detail": {"description": "Located in the heart of Prague's Old Town, Grand Hotel Prague offers...","all_amenities": ["Free WiFi", "Spa", "Restaurant", "Airport Shuttle", "24-hour Front Desk", "Bar", "Non-smoking Rooms", "Room Service", "Fitness Center"],"room_options": [{"name": "Superior Double Room","max_occupancy": 2,"beds": "1 large double bed","price_per_night": 142.00,"price_total": 426.00,"currency": "EUR","meal_plan": "Breakfast included","free_cancellation": true}],"review_summary": {"overall_score": 8.7,"total_reviews": 3421,"staff": 9.1,"cleanliness": 9.0,"comfort": 8.8,"location": 9.5,"facilities": 8.6,"value_for_money": 8.2,"free_wifi": 9.3},"photo_urls": ["https://cf.bstatic.com/xdata/images/hotel/max1024x768/123456.jpg","https://cf.bstatic.com/xdata/images/hotel/max1024x768/123457.jpg"]}}
Note: The enriched output includes all Fast Mode fields (price, rating, location, etc.) plus the
detailobject. If detail page extraction fails for a hotel, it falls back gracefully withdata_source: "search"anddetail: null.
How It Works
- Input validation: All parameters are validated (date ranges, price filters, star ratings) before crawling begins. Invalid inputs produce clear error messages.
- Search URL construction: Builds Booking.com search URL with all filters and pagination offset.
- Phase A — API Interception: Captures Booking.com's internal GraphQL/REST API responses for structured data extraction.
- Phase B — HTML Fallback: If API interception yields no results, falls back to CSS selector-based extraction from rendered HTML.
- Pagination: Automatically paginates through results (25 per page) until
maxResultsis reached or no more results exist. - CAPTCHA handling: Detects Cloudflare challenges and reCAPTCHA. Backs off for 30 seconds on first detection, aborts after consecutive blocks.
- Error reporting: Uses
Actor.fail()with descriptive messages for zero results, CAPTCHA blocks, and invalid input. Partial results still succeed viaActor.exit().
Integration Examples
Scheduled Runs (Price Monitoring)
Set up a daily schedule in Apify Console to track prices over time:
- Go to your Actor run → Schedules tab
- Create a schedule with cron expression
0 8 * * *(daily at 8:00 AM) - Results accumulate in the default dataset — export via API or download
Webhook Notifications
Trigger actions when a run completes:
- Go to Integrations → Webhooks
- Set event to
ACTOR.RUN.SUCCEEDED - Point to your endpoint (Slack webhook, email API, etc.)
API Access
Retrieve results programmatically after a run:
# Start a runcurl -X POST "https://api.apify.com/v2/acts/YOUR_ACTOR_ID/runs" \-H "Authorization: Bearer YOUR_TOKEN" \-H "Content-Type: application/json" \-d '{"destination": "Paris", "checkIn": "2026-04-01", "checkOut": "2026-04-03"}'# Get dataset itemscurl "https://api.apify.com/v2/datasets/DATASET_ID/items?format=json" \-H "Authorization: Bearer YOUR_TOKEN"
Python Client
from apify_client import ApifyClientclient = ApifyClient("YOUR_TOKEN")run = client.actor("YOUR_ACTOR_ID").call(run_input={"destination": "London","checkIn": "2026-05-01","checkOut": "2026-05-03","maxResults": 200,"currency": "GBP",})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(f"{item['name']}: {item['price']['per_night']} {item['price']['currency']}")
Proxy Recommendations
Booking.com has aggressive anti-bot protection. For best results:
- Use Apify Proxy with RESIDENTIAL group (default configuration)
- The scraper includes stealth measures (fingerprint spoofing, timing randomization) but residential proxies significantly improve success rates
- Expected extraction speed: 50–100 hotels/minute with residential proxies
FAQ
How fast is the scraper? With residential proxies, expect 50–100 hotels per minute. A typical 100-hotel run completes in 1–3 minutes. Larger runs (500–1,000 hotels) take 5–15 minutes depending on pagination and page load times.
What happens if Booking.com blocks the scraper? The scraper detects CAPTCHAs and anti-bot challenges automatically. On first detection, it backs off for 30 seconds and retries. After two consecutive blocks, it aborts with a clear error message. Using residential proxies minimizes blocking.
Why are some fields null?
Not all fields are available for every property. Star ratings (stars) depend on Booking.com's HTML structure which varies across page renders. GPS coordinates require API interception to succeed. The scraper returns null rather than guessing.
Can I scrape specific hotel pages (not search results)?
Yes! Set enrichData: true and the scraper will visit each hotel's detail page to extract room options, full amenities, review breakdowns by category, descriptions, and photo galleries. This is slower but gives you the richest data available.
How much does it cost to run? Costs depend on proxy usage, memory allocation, and run time. Typical estimates:
| Results | Approximate Cost |
|---|---|
| 100 hotels | ~$0.10–0.25 |
| 500 hotels | ~$0.50–1.25 |
| 1,000 hotels | ~$1.00–2.50 |
What currencies are supported?
USD, EUR, GBP, CZK, JPY, CNY, AUD, CAD, CHF, and INR. The currency input parameter controls which currency Booking.com uses for pricing.
Can I filter by property type or review score?
Yes. Use propertyType to filter by hotel, apartment, hostel, resort, villa, or guesthouse. Use minReviewScore to only return properties scoring above your threshold (0–10 scale).
Limitations
- Maximum 1,000 results per search (Booking.com platform limit)
- Maximum stay duration: 30 nights
- CAPTCHA pages trigger backoff and may cause early termination after consecutive blocks
- Results depend on Booking.com's current page structure — the dual extraction engine mitigates breakage risk
- Star rating field may be null on some page renders