TripAdvisor Reviews Scraper avatar

TripAdvisor Reviews Scraper

Pricing

$0.40 / 1,000 reviews

Go to Apify Store
TripAdvisor Reviews Scraper

TripAdvisor Reviews Scraper

Scrape TripAdvisor reviews to JSON from hotel, restaurant, or attraction URLs or location IDs. No TripAdvisor account or API key. Get rating, text, trip type, photos, sub-ratings, and owner replies. Filter by rating, traveler type, and date. Empty locations cost $0. $0.40 per 1,000 reviews.

Pricing

$0.40 / 1,000 reviews

Rating

0.0

(0)

Developer

apihq dev

apihq dev

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

19 hours ago

Last modified

Share

Export TripAdvisor reviews as clean JSON from a hotel, restaurant, or attraction URL or a numeric location id. No TripAdvisor account or API key. Get one row per review with the rating, title, text, trip type, visit date, reviewer hometown, photos, feature sub-ratings, and the owner's reply. Filter by rating, traveler type, and date, and pay only for reviews delivered at $0.40 per 1,000.

The contract is simple: a location with no reviews never fails your run, and you only pay for reviews delivered. Scrape a batch of places and get one record per review. There is no per-run start fee, so a location that returns nothing costs $0.

See one run

Input:

{
"urls": [
"https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_New_York.html",
"not-a-tripadvisor-location"
],
"maxReviews": 3,
"language": "en",
"ratings": ["4", "5"],
"travelerTypes": ["Couples", "Family"],
"dateFrom": "2026-01-01",
"dateTo": "2026-12-31"
}

What comes back:

  • Up to 3 success: true review rows for the hotel (location 93589) that match the filters (4 or 5 stars, couples or families, published in 2026), billed
  • 1 success: false row, code: VALIDATION_FAILED, for the unrecognizable value, not billed
  • Run status: SUCCEEDED (one bad location never fails the batch)
  • Charged: up to 3 reviews = $0.0012 ($0.40 per 1,000)

Every filter is optional; leave them out to return all reviews for each location.

A single url works too, and a bare numeric location id works anywhere a URL does. Good input returns billed rows, a bad location returns a free error row in the same dataset, and the run still succeeds so one bad entry never costs you a batch.

Why this Actor

  • Filter before you pay. Narrow each location by star ratings (1 to 5), travelerTypes (Business, Couples, Family, Friends, Solo), and a published-date window (dateFrom / dateTo), so you pull and pay for only the reviews you want. A dateFrom bound also stops each location once its reviews are older than your window, so recent-review jobs finish sooner.
  • Owner and management replies included. Each review carries the property's public reply (owner_response) with its text, date, responder name, and role.
  • Review photos, sub-ratings, and trip context. Every row can carry reviewer photos, feature additional_ratings (for example Rooms, Service, Value), the trip_type (couples, family, business, solo, friends), the stay_date, and the reviewer's user_hometown and contribution count.
  • You pay only for reviews. Billing fires on an explicit per-review event, not on dataset writes, so a location that returns nothing sits in your dataset for free. There is no per-run start fee, so an empty run costs zero.
  • URL or id, no account. Point it at a tripadvisor.com detail URL or a bare location id. It reads public reviews, so there is nothing to log into and no key to provision.

Best for

Data and AI workflows that turn place reviews into text: sentiment and reputation analysis, competitor and property monitoring, hospitality research, and building review datasets for LLM pipelines. The failure-free billing matters most when the extraction runs unattended inside a larger pipeline, where one bad location should never take down the batch. It works fine for one-off manual pulls too.

Input example

A single location:

{
"url": "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_New_York.html",
"maxReviews": 500
}

A batch, in French:

{
"urls": [
"https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-x.html",
"https://www.tripadvisor.fr/Restaurant_Review-g187147-d12345-Reviews-y.html",
"93589"
],
"maxReviews": 1000,
"language": "fr"
}

Filtered to recent 5-star and 4-star reviews from couples and families:

{
"url": "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-x.html",
"maxReviews": 500,
"language": "en",
"ratings": ["4", "5"],
"travelerTypes": ["Couples", "Family"],
"dateFrom": "2026-01-01",
"dateTo": "2026-12-31"
}

url and urls are merged and de-duplicated (a numeric id and its tripadvisor.com URL count as the same location). Up to 50 unique locations run per job. language applies to every location in the run.

The optional filters narrow what is returned, and apply to every location: ratings (any of 1 to 5), travelerTypes (Business, Couples, Family, Friends, Solo), and a published-date window with dateFrom and dateTo (inclusive, YYYY-MM-DD). Leave a filter empty (an empty list, or a blank date) to apply no constraint for that dimension.

Filter values are handled to protect your bill. Within a list, valid entries are kept and unusable entries are ignored with a log note (so [4, 5, 9] filters to 4 and 5). But if a filter you set has no valid value at all (for example ratings: [6], an unparsable date, or a dateFrom after dateTo), the run does not silently fall back to returning everything: it stops before making any request, writes one free success: false row with code INVALID_FILTER, and finishes SUCCEEDED, so you are never charged for reviews outside the filter you intended. When a location does have reviews but none match a valid filter, you get one free success: false row with code NO_MATCHING_REVIEWS.

Reviews are returned newest first. A dateFrom bound stops each location once its reviews are older than the requested window, instead of paging through older reviews it would only discard, so recent-review jobs finish sooner. (The bill is the same either way: you pay per delivered matching review, and non-matching reviews are never charged.)

maxReviews is a maximum target per location, not a guaranteed count. If fewer reviews are available, the location finishes normally with no diagnostic row. If an anti-bot challenge, timeout, or service-capacity condition stops extraction early, the reviews already delivered are preserved, one free success: false diagnostic row is added, and the run finishes SUCCEEDED. You are charged only for reviews delivered. The Reliability section below shows the full contract.

Output example

One record per review. The location id is copied onto every row so each row stands alone:

{
"success": true,
"review_id": "1068526713",
"location_id": "93589",
"rating": 5,
"title": "Great suite & staff",
"text": "We stayed in a Grand Suite for our wedding trip.",
"published_date": "2026-07-15",
"created_date": "2026-07-15",
"trip_type": "COUPLES",
"stay_date": "2026-07-31",
"language": "en",
"helpful_votes": 1,
"url": "https://www.tripadvisor.com/ShowUserReviews-g60763-d93589-r1068526713-x.html",
"user_name": "koala",
"user_id": "C9A937BB",
"user_hometown": "United Kingdom",
"user_contributions": 6,
"owner_response": {
"text": "What a special occasion!",
"published_date": "2026-07-16",
"responder": "Hotel Manager",
"connection": "Guest Services / Front Office"
},
"additional_ratings": [
{ "feature": "Value", "rating": 5 },
{ "feature": "Rooms", "rating": 4 }
],
"photos": ["https://cdn.tripadvisor.com/photo-o/33/caption.jpg?w=1024&h=1024&s=1"],
"place_name": "The Michelangelo New York",
"place_url": "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-x.html"
}

A value that is not a recognized TripAdvisor location lands in the same dataset and is not charged:

{
"success": false,
"location_input": "not-a-tripadvisor-location",
"code": "VALIDATION_FAILED",
"error": "not a valid TripAdvisor URL or location id: not-a-tripadvisor-location",
"request_id": "req_911f37d2e55644ff9d9e4a3f",
"status_code": 400
}

Split hits from misses on the success field. Quote request_id in any support issue and we can trace the exact request.

What you get

Every review is one record with success: true:

FieldTypeWhat it is
successbooleantrue for a review (billed). false for a diagnostic row (never billed): a single bad or empty location, or a row marking that the walk stopped early.
review_idstringTripAdvisor's unique review id.
location_idstringThe numeric location id the review belongs to.
ratingintegerBubble rating, 1 to 5.
titlestring or nullThe review title.
textstringThe review body.
published_datestring or nullPublish date, YYYY-MM-DD.
created_datestring or nullCreation date, YYYY-MM-DD.
trip_typestring or nullTrip type: couples, family, business, solo, or friends.
stay_datestring or nullVisit or stay date, YYYY-MM-DD.
languagestring or nullThe review's language code.
helpful_votesintegerHelpful-vote count.
urlstring or nullPermalink to the review on tripadvisor.com.
user_namestring or nullReviewer display name.
user_idstring or nullReviewer id.
user_hometownstring or nullReviewer's stated hometown.
user_contributionsinteger or nullNumber of contributions the reviewer has made.
owner_responseobject or nullThe owner/management reply: text, published_date, responder, connection.
additional_ratingsarrayFeature sub-ratings, e.g. [{ "feature": "Rooms", "rating": 4 }].
photosarrayReviewer photo URLs.
place_namestring or nullThe location's name.
place_urlstring or nullThe location's TripAdvisor page URL.

Every success: false row is free and carries a machine-readable code and a human-readable error. Rows raised by the backing service (NO_REVIEWS, NO_MATCHING_REVIEWS, VALIDATION_FAILED, TRIPADVISOR_CHALLENGED, NO_FRESH_IP, TRIPADVISOR_UPSTREAM, POOL_STOPPED, MINT_BLOCKED, MINT_QUEUE_FULL, DEADLINE_EXCEEDED) also carry the service request_id, the HTTP status_code, and the location_input/location_id. Rows raised by the Actor itself carry no request_id or status_code: PAGINATION_STALLED, ACTOR_DEADLINE_NEAR, and NO_MATCHING_REVIEWS (when it is the Actor, not the service, that finds zero matches after walking a location) carry location_input/location_id; the NO_INPUT and INVALID_FILTER rows (a run with no usable location, or a filter with no valid value) carry only code and error. NO_MATCHING_REVIEWS therefore appears in both forms: service-generated (with request metadata) when the very first page is empty under a filter, or Actor-generated (without it) when a location has reviews but none match after the walk.

Per-location codes (NO_REVIEWS, NO_MATCHING_REVIEWS, VALIDATION_FAILED, PAGINATION_STALLED) mark one bad, empty, filter-unmatched, or exhausted location while the rest of the batch continues. Run-level codes (TRIPADVISOR_CHALLENGED, NO_FRESH_IP, TRIPADVISOR_UPSTREAM, POOL_STOPPED, MINT_BLOCKED, MINT_QUEUE_FULL, DEADLINE_EXCEEDED, ACTOR_DEADLINE_NEAR) stop the run after the reviews already delivered. INVALID_FILTER stops the whole run before any request (a supplied filter had no valid value), and NO_INPUT means no usable location was given. The Reliability section explains what to do with each.

Pricing

Pay-per-review. One charge per review delivered, fired only after a review row lands in your dataset. The exact per-1,000 rate is shown on this Actor's pricing card above.

  • A run that hits only empty or unrecognizable locations costs $0.
  • There is no per-run start fee, so an empty run is genuinely free.

Platform compute is included in the per-review price, so there is no separate usage charge. Cap the maximum spend of a single run from Apify's Run Limits panel; the Actor honors the cap and stops cleanly mid-location when the budget runs out.

What this Actor does not do

Honest scope, so you know before you run it:

  • No guaranteed review count. maxReviews is a target, not a promise. TripAdvisor is behind an anti-bot layer, so a very deep walk can be stopped by a challenge or capacity limit. When that happens the Actor keeps what it delivered, adds one free diagnostic row, and finishes SUCCEEDED. It does not claim a fixed maximum depth.
  • Reviews are per language. language filters to one language at a time (default en) and sets the machine-translation target. To cover another language, run the location again with a different language.
  • Owner replies appear only when the property replied. Most reviews have no reply; owner_response is simply null on those rows, not an error.
  • Public reviews only. It returns what a signed-out visitor sees on the TripAdvisor listing.

How to use this Actor

  1. Open the Actor in the Apify Console.
  2. Set url (single) or urls (a list). Each accepts a TripAdvisor detail URL (hotel, restaurant, or attraction) or a bare numeric location id. Up to 50 unique locations run per job.
  3. Set maxReviews to cap how many reviews to return per location, and optionally language for the review language.
  4. Click Start. Each review is one success: true record. Locations that cannot be listed produce one success: false record and do not stop the run. Only reviews are charged.

The Actor is also callable from the Apify API and every official integration (Make, Zapier, n8n, Slack, webhooks). The API tab in the Console has ready-to-paste JavaScript, Python, and curl snippets.

Reliability

A bad location never fails the batch. A non-tripadvisor URL, an unrecognizable value, or a location with no reviews becomes a success: false record with a specific code. The run keeps going and finishes successfully.

You never pay for a miss. Billing fires on an explicit per-review charge event, not on dataset writes, so success: false records are free. There is no per-run start fee either.

Partial results stay usable. maxReviews is a maximum target, not a guaranteed count. If TripAdvisor challenges the request, or the extraction reaches a timeout or a service-capacity limit, the Actor stops the remaining walk instead of adding to the pressure. Reviews already delivered stay in the dataset, followed by one free success: false diagnostic row, and the run finishes SUCCEEDED. You are charged only for the reviews delivered.

{
"success": false,
"location_id": "93589",
"location_input": "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-x.html",
"code": "TRIPADVISOR_CHALLENGED",
"error": "Extraction stopped early: TripAdvisor challenged the request. Reviews already delivered are preserved; remaining locations were not processed to avoid worsening the upstream condition.",
"request_id": "req_5f21c0e9a1b2483d",
"status_code": 403
}

If this row follows 120 review rows from a maxReviews: 500 request, you get 120 delivered and billed reviews, one free diagnostic row, and the rest not processed. In a batch, the locations after the stop are skipped for the same reason. The run-level early-stop codes are TRIPADVISOR_CHALLENGED, NO_FRESH_IP, TRIPADVISOR_UPSTREAM, POOL_STOPPED, MINT_BLOCKED, MINT_QUEUE_FULL, DEADLINE_EXCEEDED, and ACTOR_DEADLINE_NEAR (the run approached its time limit). A single location can also stop early with PAGINATION_STALLED (several consecutive pages returned only reviews already delivered), and the batch continues.

FAQ

Do I need a TripAdvisor account or API key?

No. The Actor reads public TripAdvisor reviews directly from a location URL or id.

How do I point it at a location?

Use a TripAdvisor detail URL (https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-x.html) or the bare numeric location id (93589). Both resolve to the same location. An unrecognizable value comes back as a success: false record with code: VALIDATION_FAILED, not a rejected run.

Can I filter TripAdvisor reviews by rating, traveler type, or date?

Yes. Combine star ratings (any of 1 to 5), travelerTypes (Business, Couples, Family, Friends, Solo), and an inclusive published-date range (dateFrom / dateTo, YYYY-MM-DD). Only matching review rows are delivered and billed. Every filter is optional; leave it out to include everything for that dimension.

How many reviews can I get per location?

Up to your maxReviews, subject to what TripAdvisor serves and to upstream conditions. maxReviews is a target, not a guarantee: a location with fewer reviews, or an anti-bot challenge, timeout, or capacity stop, can return fewer. The next question covers what an early stop looks like.

What if the Actor stops before maxReviews?

You keep everything delivered so far. If TripAdvisor challenges the request or the run reaches a timeout or a service-capacity limit, the Actor stops the remaining walk rather than adding to the pressure. The reviews already delivered stay in the dataset and are billed, one free success: false diagnostic row records why it stopped (for example code: TRIPADVISOR_CHALLENGED), and the run still finishes SUCCEEDED. In a batch, the locations after the stop are skipped. You are never charged for the diagnostic row or for reviews that were not delivered.

Can I get reviews in other languages?

Yes. Set language (for example fr, de, pt-BR). It filters reviews to that language and sets the machine-translation target. One run covers one language; run the location again per language for wider coverage.

What if a location has no reviews?

It comes back as a success: false record with code: NO_REVIEWS. You are not charged.

Can I use this Actor from my own code?

Yes. Use the Apify API or one of the official SDKs (Node.js: apify-client, Python: apify-client). The Console shows ready-to-paste code samples on the API tab.

How does billing know a location returned nothing?

Billing fires on an explicit per-review charge event, not on dataset writes. The Actor only fires it when a review is delivered, so success: false records sit in your dataset for free. You get every result in one place and still branch on success and code, with a request_id for support correlation.

Found a bug or want a feature?

Open an issue on this Actor's Issues tab and include the request_id from any error record you saw. We respond within one business day.