Trip.com Hotels, Rooms & Reviews Scraper avatar

Trip.com Hotels, Rooms & Reviews Scraper

Pricing

from $1.00 / 1,000 hotel results

Go to Apify Store
Trip.com Hotels, Rooms & Reviews Scraper

Trip.com Hotels, Rooms & Reviews Scraper

Pull structured hotel listings from trip.com with prices, room types, amenities, policies, nearby places, and full guest reviews with ratings breakdown and an AI review summary. Search by destination or paste trip.com URLs directly.

Pricing

from $1.00 / 1,000 hotel results

Rating

0.0

(0)

Developer

Abot API

Abot API

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

2

Monthly active users

3 days ago

Last modified

Categories

Share

Trip.com Hotels Scraper: Prices, Rooms & Full Guest Reviews

Trip.com Hotels Scraper turns Trip.com hotel listings into structured data: name, star rating, guest review score, price (current, original and with taxes and fees), images, amenities, check in and check out policies, nearby places, room types with per room pricing, and the full guest review feed with a ratings breakdown and an AI generated review summary. Search by destination name, or paste Trip.com hotel links straight from your browser (every link shape works), then export to JSON, CSV or Excel, or read the results through the API.

Why This Scraper?

  • Real destination search. Type "Tokyo" or "New York" - no city ids to hunt for. Trip.com city ids and id|Name strings still work for power users.
  • Every Trip.com link works in URL mode. Hotel list links, hotel detail links, and the SEO links search engines show (like /hotels/tokyo-hotels-list-228/) all resolve - missing dates and guests are filled from your input automatically.
  • Full hotel record in one run. Price (current, original, with taxes and fees), star rating, guest review score, images, amenities, policies, nearby places and a description, all in a single dataset row per hotel.
  • Room level detail and the full guest review feed, not just an average. Rooms nest per hotel with cancellation terms and per room pricing; reviews carry per category ratings, traveler type and useful count, plus an aggregate breakdown and an AI generated summary. Cap the feed with Max reviews (default 20).
  • Filters that don't starve later pages. Minimum star rating and minimum guest review score are applied before any per page item cap, and each destination keeps being resampled until it stops producing hotels you haven't already collected.
  • Incremental mode for schedules. Let the actor remember what it already delivered and push only what is new or changed since the last run, with changeType on every row.
  • Pay per hotel returned. A small extra charge applies to hotels enriched from the detail page, plus one review unit per 10 delivered reviews; no flat monthly fee.

Use Cases

  • Travel agencies and OTAs: benchmark Trip.com's pricing and availability against your own listings for a destination and date range.
  • Rate and demand analysts: track price, discount and occupancy signals across many hotels in a city over time - incremental mode makes the scheduled re-runs cheap to read.
  • Reputation and review teams: pull the full guest review feed and AI summary to spot recurring complaints or praised amenities.
  • Travel content and comparison sites: build destination pages with live pricing, star ratings and photos.
  • Revenue managers: compare your own property's room types and cancellation terms against nearby competitors listed on Trip.com.

Data You Get

Sample shape: values are illustrative placeholders, not from a live record.

FieldExample
hotelId"0000000"
name"Sample Grand Hotel"
detailUrlTrip.com link to the hotel's detail page
starRating4
reviewScore / reviewScoreLabel9.1 / "Great"
reviewCount1200
reviewTags["Easy to get around", "Delicious breakfast"]
address"Sample District, Sample City"
lat / lng35.0000 / 139.0000
priceCurrent / priceOriginal120 / 140
priceTotalWithTaxes134
discountPercent / discountLabel14 / "14% off"
currency"USD"
images / imagefull photo list / the first photo
amenities["Free WiFi", "Fitness center", "Parking"]
policiescheck in, check out and cancellation terms
nearbyPlaces[{"name": "Sample Station", "type": "station", "distance": "400m"}]
rooms / roomCountper room name, meal notes, price and cancellation terms / how many
reviewsindividual guest reviews with a per category rating breakdown
aggregateRatingBreakdown{"overall": 9.1, "location": 9.3, "facility": 8.9, "service": 9.0, "room": 9.0}
aggregateAiSummaryAI generated summary of what guests say
changeType / changedFields / firstSeenAt / lastSeenAtincremental mode only: what changed since the last run
scrapedAt"2026-11-01T00:00:00.000Z"

Every record also carries description, reviewCount_pushed (reviews included in the record), badges, medal, propertyTag, contactPhone, contactEmail, cityId, cityName, aggregateTotalReviewCount and aggregateCommentTags. Three fields are always null: roomImages (no separate room gallery payload was found), confirmInfo (no post booking confirmation payload is exposed pre booking) and each review's reviewOwnerReply (no populated property response example was found on any review). nearbyHotels is always an empty array for the same reason.

How to Use

  1. Pick a mode: search (destination and dates) or url (paste Trip.com links).
  2. For search mode, type one or more destination names ("Tokyo", "New York") and set dates, guests and any star or review filters. For url mode, paste one or more Trip.com hotel links - list links, detail links, or the SEO links copied from a search engine all work.
  3. Leave Fetch hotel detail pages on for amenities, policies, room pricing detail and reviews, or turn it off for just the listing page fields. Set Max reviews (default 20) to cap the review feed per hotel.
  4. Set Max pages and Max listings to control run size and cost, then click Start. For scheduled runs, see Incremental mode below.

Search by destination name:

{
"mode": "search",
"locations": ["Tokyo"],
"checkIn": "2026-11-15",
"checkOut": "2026-11-16",
"adults": 2,
"maxListings": 20,
"fetchDetails": true
}

Mix names and city ids with a star rating filter:

{
"mode": "search",
"locations": ["Tokyo", "359|Bangkok", "73"],
"checkIn": "2026-12-01",
"checkOut": "2026-12-04",
"minStarRating": 4,
"maxListings": 40
}

Paste Trip.com links - every shape works:

{
"mode": "url",
"urls": [
"https://www.trip.com/hotels/tokyo-hotels-list-228/",
"https://www.trip.com/hotels/list?city=228&cityName=Tokyo&checkIn=2026-11-15&checkOut=2026-11-16",
"https://www.trip.com/hotels/tokyo-hotel-detail-1234567/sample-hotel-name/"
],
"fetchDetails": true
}

A pasted detail link returns the detail page fields; listing fields such as price, star rating, review score and images stay empty because they come from the list page.

Scrape a single hotel’s full detail and reviews:

{
"mode": "url",
"urls": ["https://www.trip.com/hotels/detail/?hotelId=0000000&checkIn=2026-11-15&checkOut=2026-11-16"]
}

Run it from your code

Python:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("abotapi/trip-com-scraper").call(run_input={"mode": "search", "locations": ["Tokyo"], "maxListings": 20})
for hotel in client.dataset(run["defaultDatasetId"]).iterate_items():
print(hotel["name"], hotel["priceCurrent"], hotel["currency"])

JavaScript:

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });
const run = await client.actor('abotapi/trip-com-scraper').call({ mode: 'search', locations: ['Tokyo'], maxListings: 20 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.

Search mode: destination names

Type the destination the way you would say it - "Tokyo", "New York", "Seoul", "Ho Chi Minh City". Names are matched against a built-in index of Trip.com's own destinations (the same slugs and ids Trip.com uses in its links), so common spellings, aliases like "NYC", and capitalization all resolve with zero extra requests. Trip.com city ids are accepted too: a bare 228 or 228|Tokyo.

If a smaller town is not in the index, the run log tells you exactly what to do: switch to URL mode and paste any Trip.com hotel link for that place - links copied from a search engine (like /hotels/<town>-hotels-list-<id>/) carry the city id and work directly.

Link you pasteWhat the actor does
/hotels/list?city=228&... (hotel list search)Scraped as-is; missing dates, guests or currency filled from your input; legacy spellings (checkin, adults) normalized.
/hotels/tokyo-hotels-list-228/ (SEO city link, with or without a zone suffix)Converted to the canonical list link for city 228 with your dates and guests.
/hotels/tokyo-asakusa/hotels-c228m15019878/ (landmark, railway, brand or zone page)Converted to the city list for city 228 (the landmark filter itself is not available to a plain fetch).
/hotels/detail/?hotelId=123 (hotel detail)Scraped as-is; missing dates and guests filled from your input.
/hotels/tokyo-hotel-detail-123/sample-hotel/ (SEO detail link, including /review.html and /photo.html variants)Converted to the canonical detail link for hotel 123.
Anything else (homepage, city directories, flights, other hosts)Skipped with a warning in the log - never misread as a hotel page.

Multi-URL is supported. Each list link collects repeated result samples, as described below. The us. / hk. / other market hosts are all accepted.

How Max pages and Max listings shape a run

Trip.com's hotel list page does not expose a real page number to a plain fetch: each additional page instead re-queries the destination and returns a resampled slice of its full hotel pool (thousands of hotels for a city like Tokyo), with partial overlap between fetches. The actor keeps a hotel-id dedup set for the whole run and only counts genuinely new hotels toward your target. The actor stops a destination after several consecutive resamples bring back nothing new, since one empty resample alone has been observed to still be followed by a fresh one. maxListings is a run-wide total, split evenly across your destinations and list links.

That dedup set is shared across every destination and every pasted URL in the run, and it is keyed by hotel id only, not by dates or guests. This has three effects when two entries in one run cover the same city (the same city listed twice, two link variants of it, or, in URL mode, the same city with different dates or guest counts):

  • The second entry only returns hotels the first one didn't. It can stop after a handful of hotels, well short of its share of maxListings, and in URL mode a second date range will not return a second price for hotels already collected under the first.
  • If the first entry has already collected everything that city offers, the second entry never finds a new hotel, so the "nothing new" stop never triggers: it keeps re-fetching until Max pages is reached, or until the run times out if Max pages is empty.
  • Hotels a page brings back but that are cut by the maxListings cap before being saved are still marked as collected, so no later entry in the same run returns them, including a pasted hotel detail link for one of those hotels, which is skipped.

Workaround: list each city only once and raise maxListings or maxPages instead of adding a duplicate entry. To compare prices for the same city across different dates, use one run per date range. If you must repeat a city in one run, set Max pages.

Incremental mode: scheduled runs that only return what changed

Turn Incremental mode on and the actor remembers the hotels it delivered for your exact search scope (destinations or URLs, dates, guests, currency, filters and review cap - or name the scope yourself with State key). On each scheduled run every hotel is classified against that memory:

  • NEW - first time seen; pushed.
  • UPDATED - seen before, fields changed; pushed with changedFields listing exactly which fields changed.
  • UNCHANGED - seen before, nothing changed; not pushed (unless Also push unchanged rows is on).
  • EXPIRED - in the previous run but no longer returned by this search; pushed as a tombstone row with the last known values - but only when the search ran to completion (a run cut short by Max listings, Max pages or connection trouble never declares hotels gone).

Every pushed row carries changeType, changedFields, firstSeenAt and lastSeenAt, and the dataset's Changes output tab shows just the change columns. Two knobs: ignoreFieldsForChanges lists dataset fields that never count as a change (they stay in the output, they just don't flip a row to UPDATED), and emitExpired: false skips tombstone rows. If a run fails mid-way, point Resume from run ID at it and the next run continues its dedup set instead of re-scraping.

Send results into your apps (MCP connectors)

Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.

What gets written to the connector: a condensed, human readable summary of each record, not the full JSON. Each hotel becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.

  1. Authorize a connector once under Apify -> Settings -> Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
  3. For Notion, also set notionParentPageUrl to the page where items should be created.

The connection is mediated by Apify's MCP proxy, so this actor never sees your third party credentials. Leave the field empty to skip.

Input Parameters

ParameterTypeDefaultDescription
modestringsearchsearch (destination and dates) or url (paste Trip.com links).
locationsarray["Tokyo"]Search mode. One destination per line: a city name ("Tokyo"), a Trip.com city id ("228"), or "228|Tokyo".
checkInstring14 days from todayCheck in date, YYYY-MM-DD. Also the default for pasted list links missing dates.
checkOutstringone night after check inCheck out date, YYYY-MM-DD.
adultsinteger2Adults per room.
childreninteger0Children per room.
roomsinteger1Number of rooms.
currencystringUSDCurrency for prices.
minStarRatinginteger0Keep only hotels rated at or above this many stars, 0 = no filter. Also applied to pasted list links.
minReviewScoreinteger0Keep only hotels scoring at or above this out of 10, 0 = no filter. Also applied to pasted list links.
urlsarraysample list URLURL mode. One or more Trip.com hotel links, any shape (see the table above).
fetchDetailsbooleantrueAlso fetch each hotel's detail page for amenities, policies, nearby places, description and reviews.
maxReviewsinteger20Cap the guest reviews attached to each hotel. 0 skips reviews.
maxPagesinteger(none, walk every page)Max list pages to walk per destination or URL.
maxListingsinteger20Stop after this many hotels total. 0 = no cap.
resumeFromRunIdstring(none)Continue an interrupted run: its hotels join this run's dedup set.
incrementalModebooleanfalseRemember delivered hotels per search scope and push only NEW/UPDATED rows (plus EXPIRED tombstones), stamped with change metadata.
stateKeystring(auto)Name for the incremental baseline. Empty = keyed automatically on the search scope.
emitUnchangedbooleanfalseWith incremental mode, also push rows that did not change.
emitExpiredbooleantrueWith incremental mode, push EXPIRED tombstone rows for hotels the search no longer returns.
ignoreFieldsForChangesarray(none)Dataset fields that never count as a change in incremental mode.
proxyobjectApify ProxyConnection settings.
mcpConnectorsarray(none)Optional: send a summary of each hotel to apps you authorized under Integrations.
notionParentPageUrlstring(none)Notion connector only: page under which records are created.
maxNotifyListingsinteger50Cap on items written to each connector per run.

Output Example

Sample shape, values are illustrative placeholders, not from a live listing.

{
"hotelId": "0000000",
"name": "Sample Grand Hotel",
"starRating": 4,
"reviewScore": 9.1,
"reviewScoreLabel": "Great",
"reviewCount": 1200,
"reviewTags": ["Easy to get around", "Delicious breakfast"],
"address": "Sample District, Sample City",
"lat": 35.0000,
"lng": 139.0000,
"priceCurrent": 120,
"priceOriginal": 140,
"priceTotalWithTaxes": 134,
"discountPercent": 14,
"discountLabel": "14% off",
"currency": "USD",
"images": ["https://example.com/photo1.jpg"],
"image": "https://example.com/photo1.jpg",
"badges": ["Free Cancellation"],
"medal": null,
"propertyTag": "Hotel",
"detailUrl": "https://www.trip.com/hotels/detail/?hotelId=0000000&checkIn=2026-11-15&checkOut=2026-11-16&adult=2&children=0&curr=USD",
"amenities": ["Free WiFi", "Fitness center", "Parking"],
"policies": { "checkin": "After 15:00", "checkout": "Before 11:00", "cancellation": "Free cancellation" },
"nearbyPlaces": [{ "name": "Sample Station", "type": "station", "distance": "400m" }],
"contactPhone": "+1-000-0000000",
"contactEmail": "stay@samplegrandhotel.com",
"rooms": [
{ "roomId": "0", "roomName": "Superior Queen Room", "roomPrice": { "current": 120, "original": 140, "currency": "USD", "taxesAndFeesTotal": 14 } }
],
"roomCount": 1,
"reviews": [
{ "reviewId": "0", "reviewerNickname": "Jane Doe", "reviewRatingOverall": 9, "reviewContent": "Great location and clean room." }
],
"reviewCount_pushed": 20,
"aggregateTotalReviewCount": 1200,
"aggregateRatingBreakdown": { "overall": 9.1, "location": 9.3, "facility": 8.9, "service": 9.0, "room": 9.0 },
"aggregateCommentTags": ["Clean and tidy", "Great location"],
"aggregateAiSummary": "Facilities: guests liked the range of amenities. Guest Suggestion: some guests wanted a quicker check-in process.",
"cityId": 228,
"cityName": "Tokyo",
"scrapedAt": "2026-11-01T00:00:00.000Z"
}

Sample shape: with incremental mode on, rows also carry changeType (NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED), changedFields, firstSeenAt and lastSeenAt.

Plan Requirement

The default proxy setting works out of the box on any paid Apify plan, and the actor automatically retries on a different connection whenever one is refused, so a flaky exit doesn't fail the run. If your Apify account has no proxy access at all, a warning is logged and the run continues on whatever connection is available rather than crashing outright. For large or frequent runs, the residential proxy group gives more headroom; pick it under Connection.

FAQ

How much does it cost?

You're charged once when a run starts, per hotel returned, and a small amount for each hotel enriched from the detail page (rooms, policies, reviews). Both use the existing detail-enrichment event: one unit per enriched hotel plus one additional unit per started block of 10 delivered reviews per hotel (20 reviews adds 2 review units). The Pricing tab shows the current rates. Use Max listings and Max reviews to cap the cost of any run.

This actor collects only publicly available hotel listing data. You are responsible for how you use it: follow Trip.com's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Prices and availability change constantly and are shown for reference, not as a booking guarantee.

Can I schedule this to only get new or changed hotels?

Yes - turn on Incremental mode. The actor remembers what it delivered for your search scope and each scheduled run pushes only new and changed hotels (plus EXPIRED tombstones for hotels that disappeared), each row stamped with changeType and changedFields. Without it, each run is an independent search returning the full current result set.

Why did I get fewer hotels than I expected from one destination?

Trip.com's hotel list page doesn't expose real page numbers to a plain fetch, so each page is a resampled slice of the destination's hotel pool and depth comes from repeated fetching, not from advancing a page counter. A run also stops a destination once several resamples in a row bring back nothing new, and Max listings is split evenly across all your destinations and links. If the same city appears twice in one run (listed twice, two link variants, or the same city with different dates or guests in URL mode), both entries share one dedup set keyed by hotel id: the second only returns hotels the first didn't, can stop after a few hotels, and stops after consecutive samples bring back no new hotels. List each city once and raise Max listings or Max pages instead, and use one run per date range to compare dates.

Why was my destination name not found?

Destination names resolve against a built-in index of Trip.com's own destinations - the major cities everywhere plus every destination Trip.com publishes in its directory. A small town may be missing: use the nearest bigger city, or switch to URL mode and paste any Trip.com hotel link for the town (links copied from a search engine carry its city id and work directly). The run log says exactly this whenever a name can't be resolved.

Why did I get an empty dataset instead of an error?

This actor never fails a run just because a request was refused: every page fetch is retried automatically on a different connection, and if a destination or URL still can't be read after retries, that one entry is skipped with a warning in the log while the rest of the run continues. If every destination in the run comes back empty, you'll see an empty dataset with warning lines explaining what to check (the destination name, the date range, or trying URL mode with a link copied from your browser) instead of a failed run. With incremental mode on, an empty dataset with an informational log line can also mean every hotel was already known and unchanged - use Also push unchanged rows if you want the full set every run.

Can I use it with AI agents or MCP?

Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.

πŸ”— Want more travel data?

Pair this actor with these related scrapers from the same team:

🏨 Expedia Hotels Scraper
From $1/1K. Scrape Expedia.com hotel listings and reviews for any destination. Extract...
🏨 Booking.com Hotels, Prices and Reviews Scraper
Scrape booking.com hotels, apartments, villas and hostels. Search any destination with...
🏨 Wego Scraper
Scrape Wego hotels by city or search URL. Get rates, providers, booking links...
🏨 Traveloka Hotel Scraper
Scrape Traveloka hotels across Singapore, Malaysia, Indonesia, Thailand, Vietnam and the...
🏨 Hostelworld Scraper
Scrape Hostelworld hostels, hotels, guesthouses, B&Bs, apartments and campsites by city...
🏨 LoopNet Scraper
Scrape LoopNet commercial listings across the US, including office, retail, industrial...

πŸ‘‰ Browse all abotapi scrapers

πŸ’¬ Support

  • 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
  • πŸ› οΈ Need another site, extra fields or a private build? Email contact@abotapi.com.
  • ⭐ Enjoying it? A quick review on the actor page helps other users find it.