Ctrip / Trip.com Hotel Scraper - Prices, Ratings & Availability avatar

Ctrip / Trip.com Hotel Scraper - Prices, Ratings & Availability

Pricing

from $30.00 / 1,000 results

Go to Apify Store
Ctrip / Trip.com Hotel Scraper - Prices, Ratings & Availability

Ctrip / Trip.com Hotel Scraper - Prices, Ratings & Availability

Scrape hotel listings from Trip.com (Ctrip): names, nightly prices, ratings, reviews, location, star class, amenities, photos. Supports city, check-in/out dates, guests, and rooms.

Pricing

from $30.00 / 1,000 results

Rating

0.0

(0)

Developer

Thirdwatch

Thirdwatch

Maintained by Community

Actor stats

0

Bookmarked

5

Total users

4

Monthly active users

14 hours ago

Last modified

Categories

Share

Ctrip / Trip.com Hotel Scraper

Scrape hotel listings from Trip.com (the English face of Ctrip): prices, ratings, reviews, location, star class, amenities, room types, and photos for any city and date range.

What you get per hotel

FieldDescription
hotel_nameHotel name
hotel_idTrip.com internal hotel ID
urlDetail page URL
priceLowest nightly rate seen
currencyCurrency code (USD default)
original_priceCrossed-out / pre-discount price when present
ratingUser rating (0-5 scale on Trip.com)
rating_label"Excellent" / "Very good" / etc.
reviews_countTotal user reviews
starsStar class (1-5)
addressStreet / area description
city, districtLocation breakdown
latitude, longitudeMap coordinates
image_urlPrimary photo
amenitiesList of facility names
room_typesSample room types from card
tagsPromotional / property tags
distance_from_centerWhen Trip.com provides it
checkin_date, checkout_date, search_cityEchoed inputs
source"api" (preferred) or "dom" (fallback)

Input

{
"city": "Tokyo",
"cityId": 228,
"checkIn": "2026-06-01",
"checkOut": "2026-06-03",
"guests": 2,
"rooms": 1,
"maxResults": 50
}

cityId is strongly recommended for production. Trip.com's hotel list endpoint requires a numeric city ID — passing only a city name does not drive a search. The actor has a small built-in map of verified IDs (Tokyo 228, Singapore 73, Beijing 1, Shanghai 2, Madrid 357, Granada 717, New Delhi 495) and tries an in-browser autocomplete fallback for everything else, but the autocomplete resolver is not 100% reliable. To grab a cityId by hand, open https://www.trip.com/hotels/list?city=<id> for guesses and check the page title.

How it works

Trip.com renders its hotel list entirely client-side, behind a stealth-defence script (hotel-spider-defence) and a jigsaw CAPTCHA. Pure HTTP requests to the public fetchHotelList SOA endpoint are rejected without the dynamic testab token minted by the in-page JS.

The actor uses Camoufox (stealth Firefox) with Apify Residential proxy, performs a homepage warmup to settle session cookies, and then:

  1. Attaches a page.on("response") listener before navigation, capturing every JSON response on /restapi/soa2/34951/fetchHotelList.
  2. Loads /hotels/list?city=<id>&checkin=&checkout=&adult=&crn= and scrolls to trigger pagination / dynamic refresh XHRs.
  3. Recursively walks each captured JSON for hotel records (matches dicts that look like a hotel: have hotelBasicInfo, or both hotelName and hotelId).
  4. Falls back to anchor-based DOM extraction (a[href*="/hotels/detail/"] walked up to the smallest container with an image + meaningful text) if the API capture comes up short.

This is the same XHR-intercept pattern used by meesho-scraper and tatacliq-scraper in this repo.

Pricing (PPE)

TierPer result
FREE$0.008
BRONZE$0.006
SILVER$0.005
GOLD$0.004

Known limits

  • Pagination is XHR-driven, not URL-driven. We rely on scrolling to fetch additional pages; 50-100 hotels per run is the comfortable ceiling. Larger maxResults may stall.
  • CAPTCHA risk. Trip.com occasionally serves a jigsaw challenge to fresh proxy IPs. The actor retries up to 3 times with new browsers; persistent failures usually mean the proxy IP is currently flagged.
  • Currency. All requests are pinned to USD via the curr URL param. Trip.com may still echo back rates that include local taxes/fees.
  • City ID auto-resolve is best-effort. For ambiguous city names, supply cityId directly.