Paste a Booking.com search or city name — get professional host contacts: emails, phones, company names, VAT number. Export-ready dataset, one row per host. No login needed.
hotel_stars — star rating from Phase 1 GraphQL (basicPropertyData.starRating.value). Zero cost — data already present in search results.
hotel_review_score and hotel_review_count — review score and count from Phase 1 GraphQL (basicPropertyData.reviews.totalScore / reviewsCount).
hotel_price_per_night and hotel_price_currency — per-night price computed from priceDisplayInfoIrene. Populated only when the search URL includes dates. In multiSearch mode, dates are always present so price is always available.
Changed
multiSearch passes: 18 → 25. New variation strategy based on observed marginal gains per pass:
Near-term offset sweep at 1 night (+7d, +14d, +21d, +30d, +45d) — catches date-sensitive inventory not visible at a single offset.
Short multi-night stays (+7d·2n, +14d·2n, +21d·3n, +21d·7n) — catches properties with minimum stay requirements.
Mode auto-detection — mode field removed from Console UI. Actor now infers mode from which fields are filled: searchUrls → Search URL mode, cityNames → City name mode. mode remains accepted as an optional override in JSON input for backward compatibility.
multiSearch bug fix — multiSearch was silently ignored when mode was not explicitly set in JSON input. The Console UI never sets mode, so multiSearch never activated from the UI. Fixed by applying multiSearch logic in all searchUrls code paths.
Input form simplified — Removed mode selector, hotelUrls field, and maxHotels field from Console UI. All remain usable via JSON input.
hotel_city fallback — When Booking.com returns a malformed city string (e.g. full address in the city field, contains comma or >40 chars), the actor now falls back to the legal contact city from trader info.
Removed
hotel_postal_code — removed from output. Rarely populated; added noise to exports.
hotel_contact_country — removed from output. Two-letter country code has no practical use in outreach workflows.
Fixed
Warning during multiSearch passes — "X of Y properties collected. Enable multiSearch…" warning was incorrectly firing during multiSearch passes (where partial collection per pass is expected by design). Now suppressed when multiSearch: true.
Warning with small maxHotels — Same warning incorrectly fired when maxHotels intentionally capped results. Now suppressed when the cap is the reason for partial collection.
hotel_price_per_night always 0 — Booking.com's averagePricePerNight field returns 0 (not null) even when a valid stay price is available. Fix: treat 0 as absent and compute per-night from amountPerStay / nights instead.
[2.0] - 2026-04-13
Complete rewrite. The Actor now runs 100% via HTTP GraphQL — no browser, no Chrome, no residential proxy required.
Added
HTTP GraphQL Phase 1 — Hotel URLs collected via Booking.com's internal /dml/graphql search endpoint. No browser navigation needed; no destId required (searchString is sufficient).
HTTP GraphQL Phase 2 — Trader contact info (email, phone, company, address, SIRET) fetched via the hotelPageByPageName GraphQL query with inline fragment ... on HotelPageType. No page rendering, no Apollo cache scraping.
**src/phase1-http-extractor.js** — Phase 1 rewrite: pure HTTP, concurrent city searches.
**src/hotel-graphql-client.js** — Thin HTTP client for hotelPageByPageName with normalizePhone + sanitizeWebsite applied at extraction time.
**httpGraphqlFetch()** exported from src/graphql-client.js — reusable HTTP fetch without a browser page.
**normalizePhone()** and **sanitizeWebsite()** — migrated to src/utils.js and unit-tested.
Proxy optional — The /dml/graphql endpoint is not behind the AWS WAF that blocks HTML page rendering. Proxy can still be added for large-scale runs or geo-routing.
Changed
Docker image — apify/actor-node-puppeteer-chrome:22 → apify/actor-node:22. Image drops from ~1.5 GB to ~200 MB.
**src/dom-fallback.js** — DOM extraction fallback removed (GraphQL is reliable without browser).
**scripts/** and **docs/** — Investigation artifacts removed from the repository.
Dead tests (03-apollo-extractor, 06-graphql-extractor, 07-phase2-fetch-live, 08-email-filter, 10-apollo-keys, 16-contact-extractor) replaced with tests for current modules.
[1.0] - 2026-03-03
Initial release. Puppeteer-based scraper.
Added
GraphQL extraction via page.evaluate (browser context) + DOM fallback.
Pro hosts filter, host deduplication (onlyUniqueProHost).
Modes: Country, City name, Search URL, Hotel URL(s).