# Ctrip (携程 / `ctrip.com`) — Hotel Scraping Field-tested 2026-04-29 against `hotels.ctrip.com` PC web. Domestic hotels. --- ## TL;DR **Prices are visible without login** — but only if you reach the list page through a "natural" navigation flow that produces a complete URL parameter schema. Direct GETs to a simplified URL get redirected to login. - Browser session required (the page shell is 144 KB, hotels are loaded by XHR after hydration). `http_get` cannot retrieve hotel data. - Once on a valid list page, prices render as `¥ ¥ 起` pairs. No `¥?` placeholders and no `请登录` interstitial. - Detail URL `https://hotels.ctrip.com/hotel/.html?checkin=...` works pre-login and shows full room-rate breakdown. - Compared to ly.com (which hides every price behind login) ctrip is far more scrape-friendly *if you respect the URL schema*. --- ## URL patterns ``` List page (canonical, anonymous-friendly): https://hotels.ctrip.com/hotels/list ?flexType=1 &cityId= # 2 = 上海, 1 = 北京, etc. &provinceId=0 &districtId=0 &countryId=1 # 1 = 中国 domestic &checkin=YYYY-MM-DD &checkout=YYYY-MM-DD Hotel detail (canonical): https://hotels.ctrip.com/hotel/.html?checkin=...&checkout=... → server rewrites to /hotels/detail/?... — both work, same data Login page (when reached unintentionally): https://passport.ctrip.com/user/login?backurl= ``` **Critical:** the *simplified* form `https://hotels.ctrip.com/hotels/list?city=2&checkin=...&checkout=...` (note: `city`, not `cityId`, and missing `provinceId/districtId/countryId/flexType`) **redirects to login.** This is ctrip's signature anti-scrape gate — it distinguishes a "real" client (built the URL through the homepage form) from a scripted client (typed the URL by hand). --- ## How to land on the list page reliably ### Path A — build the canonical URL (preferred when you know cityId) ```python from browser_harness.helpers import new_tab, wait_for_load import time url = ( "https://hotels.ctrip.com/hotels/list" "?flexType=1&cityId=2&provinceId=0&districtId=0&countryId=1" "&checkin=2026-04-29&checkout=2026-04-30" ) new_tab(url) wait_for_load(timeout=20) time.sleep(6) # XHR hotel-list fetch ``` ### Path B — simulate the homepage flow (when you only have a city name) If you only have a city name, drive the home-page form. The 搜索 button is a `
`, not `