Tripadvisor Hotel Scraper
Pricing
from $0.80 / 1,000 results
Tripadvisor Hotel Scraper
Extract hotel data from TripAdvisor anonymously — no login needed. Search hotels by name, city or URL; pull real per-provider OTA rates (Booking.com, Expedia, Agoda & more) side by side; or get a city's total hotel count and listing. Reads TripAdvisor's own embedded data, not guessed-at page text.
Pricing
from $0.80 / 1,000 results
Rating
0.0
(0)
Developer
MrDoe
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
What does TripAdvisor Hotel Scraper do?
TripAdvisor Hotel Scraper extracts hotel data from TripAdvisor - anonymously, no login, no TripAdvisor account. Three operations live in one Actor:
- Hotel Search - look up one or many hotels by name, by city, or by a direct TripAdvisor hotel URL/ID.
- Room & OTA Rate Details - the same lookup, plus every real per-provider rate TripAdvisor exposes for that hotel (Booking.com, Expedia, Hotels.com, Agoda, Priceline, Vio.com, and more - whatever OTA partners TripAdvisor has aggregated for that hotel at fetch time).
- Location Hotel Count & List - given just a city, how many hotels TripAdvisor lists there and a capped, paginated list of them.
Why use this Actor?
- Compare hotels - batch several hotel names/URLs in one run (
hotelQueries) to line up hotel X against hotel Y in one dataset. - Rate-shop across OTAs -
roomRatesreturns every provider's price for a hotel side by side (Booking.com vs. Expedia vs. Agoda...), including which one TripAdvisor flags as its lowest price. - Market sizing -
locationtells you how many properties TripAdvisor lists for a city and hands you a sample.
How to use it
- Pick an Operation: Hotel Search, Room & OTA Rate Details, or Location Hotel Count & List.
- Fill the matching field:
- Hotel Search / Room & OTA Rate Details →
hotelQuery(a hotel name, a city name, a full TripAdvisorHotel_Review-...URL, or a bare numeric hotel ID) orhotelQueriesfor a batch. - Location Hotel Count & List →
location(a city name or numeric geo ID) orlocationsfor a batch.
- Hotel Search / Room & OTA Rate Details →
- Set
maxItems. - Click Start.
Batch fields (hotelQueries/locations) win over their singular counterparts when filled; duplicates and blanks are dropped automatically.
Input
| Field | Type | Description |
|---|---|---|
operation | string (required) | One of: search, roomRates, location. |
hotelQuery / hotelQueries | string / array | A hotel name, city name, TripAdvisor Hotel_Review URL, or numeric hotel ID. Used by search/roomRates. |
location / locations | string / array | A city name or raw TripAdvisor numeric geo ID. Used by location. |
maxItems | integer | Caps the number of hotel-summary rows produced per run. Default 10. No hard upper limit beyond what you set. |
proxyConfiguration | object | Required, residential. TripAdvisor is DataDome-protected and blocks datacenter IPs outright. |
Resolving a hotel: URL/ID vs. free text
A TripAdvisor hotel URL (e.g. https://www.tripadvisor.com/Hotel_Review-g60763-d224214-Reviews-The_Bryant_Park_Hotel-New_York_City_New_York.html) or a bare numeric hotel ID (the d number, e.g. 224214) resolves directly and reliably to one hotel - TripAdvisor itself redirects a placeholder-slug URL built from just the geo+hotel IDs to the real canonical page, so no slug lookup is needed.
Free text (a hotel name and/or a city) is resolved through the same curated city list used by the location operation (see below), then optionally narrowed to a hotel-name match within that city's listing. This is not a global hotel-name search across all of TripAdvisor - it only works for hotels in a supported city (TripAdvisor's own search page is a client-side-rendered shell with no working anonymous free-text/typeahead endpoint found during development). For a hotel in an unsupported city, use the direct TripAdvisor URL/ID instead.
Supported city names (location text resolution)
Live-verified 2026-08-28 (10/10 checked against real TripAdvisor pages): Amsterdam, Bangkok, Barcelona, Berlin, Boston, Chicago, Dubai, Hong Kong, Istanbul, Las Vegas, London, Los Angeles, Miami, New York City, Orlando, Paris, Rome, San Francisco, Seoul, Singapore, Sydney, Tokyo, Toronto, Washington DC.
For any other city, pass its raw numeric TripAdvisor geo ID instead (visit tripadvisor.com, search the city, and copy the number after Hotels-g in the resulting URL) - location/hotelQuery both accept a bare numeric ID directly.
Output
One flat row per item, distinguished by kind:
hotelSummary- one per hotel (all three operations).rate- one per OTA-provider offer,roomRatesonly (a hotel with 12 connected providers produces 12raterows).locationSummary- one per city query,locationonly, carries the total hotel count.
Every row has _operation and status (success, unavailable, or error).
Hotel summary row:
{"_operation": "search","status": "success","kind": "hotelSummary","geoId": "60763","hotelId": "224214","hotelName": "The Bryant Park Hotel","address": "40 West 40th Street, New York City, New York, 10018-2602","city": "New York City","country": "US","phone": "1 (212) 869-0100","latitude": 40.752895,"longitude": -73.983696,"rating": 4.8,"reviewCount": 5560,"priceFrom": 368,"priceMax": 1201,"url": "https://www.tripadvisor.com/Hotel_Review-g60763-d224214-Reviews-The_Bryant_Park_Hotel-New_York_City_New_York.html"}
Rate row (roomRates, one per OTA provider):
{"_operation": "roomRates","status": "success","kind": "rate","hotelId": "224214","hotelName": "The Bryant Park Hotel","offerCount": 12,"provider": "Booking.com","price": 570,"currency": "USD","strikeThroughPrice": null,"isLowestPrice": false,"offerStatus": "AVAILABLE","freeCancellation": true}
Location summary row (location):
{"_operation": "location","status": "success","kind": "locationSummary","query": "New York City","geoId": "60763","hotelCount": 1038,"hotelsListed": 10}
How it works
TripAdvisor is protected by DataDome: a bare anonymous GET, a plain got-scraping request through a residential proxy, and headed/headless Chromium via plain Playwright were all live-tested 2026-08-28 and every one came back the same DataDome challenge shell (geo.captcha-delivery.com, "Please enable JS and disable any ad blocker"). Camoufox (a fingerprint-patched Firefox build) with its humanize option enabled, plus a homepage warm-up navigation before the target page in the same browser session, is the only tier that got through at all during development - see Limitations for the honest, observed reliability of that bypass (it is inconsistent, not solved).
Once a page loads, hotel data is pulled from TripAdvisor's own embedded structures rather than guessed at from visible text:
- Hotel summary (
search/roomRates/location): the detail page'sLodgingBusinessJSON-LD block (name, address, phone, coordinates, aggregate rating) plus apriceRangefigure pulled from the same hydration payload as the OTA offers. - OTA rate offers (
roomRates): TripAdvisor embeds its real-time rate-comparison data (the "top offers" row plus the longer "all deals" list) as a URL-percent-encoded, backslash-escaped JSON blob inside a<script src="data:text/javascript,...">hydration payload on every hotel detail page. This Actor locates and decodes just that one script's content (not the whole page, to avoid unrelated%characters elsewhere breaking the decode) and parses the real provider/price/cancellation-policy data out of it. - Listing cards (
searchfree-text/location): TripAdvisor's listing-page CSS classes are content-hashed and change on every deploy, so cards are located by the one stable marker TripAdvisor does keep (data-automation="hotel-card-title") and parsed with small regexes within each card's chunk, rather than fragile class-name selectors. Pagination beyond the first ~6-30 hotels uses TripAdvisor's ownoa<N>offset URL segment (verified live:Hotels-g60763-oa30-...30x-redirects to the real page-2 URL).
Limitations
- DataDome bypass reliability varies over a session's lifetime - read this before relying on this Actor for production data. During development, Camoufox (
humanize+ a homepage warm-up) passed DataDome cleanly across 4 separate fresh browser sessions and 15+ further page loads reused within them. Later in the same development window it then failed 16 fresh-session attempts in a row (across two different residential-proxy providers). One real bug was found and fixed during that investigation (an accidental Chrome-UA override that broke Camoufox's own Firefox fingerprint consistency), plus a second bug where the wrong hotel's link could get matched from deep inside a card's markup (also fixed - see the extraction bugs below). After both fixes, four separate platform runs against Apify's own Residential proxy group all succeeded cleanly (location,roomRates, a multi-hotelsearchbatch, and a final confirmation run), each returning real hotel/rate data with no retries needed. Net assessment: the bypass works, and worked repeatedly and cleanly in final verification - but DataDome's response to this technique is not perfectly stable over time, so occasional runs may still land onstatus: "error"rows if every retry attempt hits a blocked session. This Actor automatically detects a blocked/challenged fetch and retries with a brand-new browser session (a fresh proxy exit IP), up to 3 attempts per page; if every retry is exhausted, that lookup lands as astatus: "error"row rather than failing the whole run. - Two real extraction bugs were caught and fixed via live platform data (not just local fixtures) during development: (1) a listing card's hotel name/ID could rarely be pulled from an unrelated
Hotel_Reviewlink elsewhere in the same card's markup rather than its own - fixed by narrowing the link search to the anchor immediately following the card's title marker; (2) some TripAdvisor sort orders (e.g. "Best Value") prefix a card's title with its own rank ("1. Hotel Name") - stripped as noise. Both are covered by regression tests intest/main.test.js. hotelCount(the total-properties figure in alocationSummaryrow) is not always present. It's parsed from a specific "N properties in <City>" sentence TripAdvisor renders on page 1 of a listing; on at least one live run (London) that sentence wasn't present in the fetched markup andhotelCountcame backnull, whilehotelsListed(the actual capped list this Actor returns) was still correct. TreathotelCountas best-effort.- Free-text hotel-name search is city-scoped, not global. No working TripAdvisor hotel-name-autocomplete/search endpoint could be reached anonymously (TripAdvisor's own
/Searchpage is a client-rendered shell, and its internal/TypeAheadJsonendpoint 403s outside a full browser challenge). Free text resolves via the curated city list, then narrows within that city's listing. Use a direct hotel URL/ID for a reliable single-hotel lookup outside the curated cities. - City-name resolution covers a curated list of 24 major cities, live-verified against real TripAdvisor pages, not an exhaustive directory. Anything else needs the raw numeric geo ID from a TripAdvisor URL.
- OTA rate offers depend on what TripAdvisor itself has aggregated for that hotel/date range at fetch time. TripAdvisor does not expose a check-in/check-out date input on this anonymous path (no session/cart state), so offers reflect TripAdvisor's own default near-term date window, not a date range you choose. A hotel with no connected OTA partners for that window returns a
status: "unavailable"raterow instead of provider prices. - A city listing page reliably renders ~6 main-list hotel cards per fetch (plus TripAdvisor's own separate "top picks" carousel, not extracted here to keep the data shape consistent); more are reached via TripAdvisor's own page-offset pagination (
oa<N>), which this Actor uses automatically up tomaxItems. - Prices reflect TripAdvisor's own currency/pricing at fetch time and are not guaranteed to match what you'd see at checkout on the OTA's own site.
Pricing
This Actor uses pay-per-event pricing - one small run-start charge, then a per-row charge for each hotel-summary row and each OTA-rate row. See the Pricing tab for current rates. Failed/unavailable lookups land as status: "error"/"unavailable" rows and are never charged.
FAQ
Do I need a TripAdvisor account or API key? No - it runs entirely against TripAdvisor's public, logged-out web pages.
Why did I get 0 OTA rate offers for a hotel? TripAdvisor had no connected/available provider rates for that hotel at fetch time (see Limitations) - the hotel summary row is still returned.
Can I pick my own check-in/check-out dates for rates? Not anonymously - see Limitations. TripAdvisor's rate-comparison data on this path reflects its own default date window.
Disclaimer
This Actor is an independent tool, not affiliated with or endorsed by TripAdvisor. It only accesses data TripAdvisor serves publicly to anonymous visitors. Use it in compliance with TripAdvisor's terms of use and applicable law in your jurisdiction. Found a bug or have a feature request? Use the Issues tab on this Actor's page.