TripAdvisor Reviews Scraper
Pricing
$0.40 / 1,000 reviews
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
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
19 hours ago
Last modified
Categories
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: truereview rows for the hotel (location93589) that match the filters (4 or 5 stars, couples or families, published in 2026), billed - 1
success: falserow,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. AdateFrombound 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, featureadditional_ratings(for example Rooms, Service, Value), thetrip_type(couples, family, business, solo, friends), thestay_date, and the reviewer'suser_hometownand 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:
| Field | Type | What it is |
|---|---|---|
success | boolean | true 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_id | string | TripAdvisor's unique review id. |
location_id | string | The numeric location id the review belongs to. |
rating | integer | Bubble rating, 1 to 5. |
title | string or null | The review title. |
text | string | The review body. |
published_date | string or null | Publish date, YYYY-MM-DD. |
created_date | string or null | Creation date, YYYY-MM-DD. |
trip_type | string or null | Trip type: couples, family, business, solo, or friends. |
stay_date | string or null | Visit or stay date, YYYY-MM-DD. |
language | string or null | The review's language code. |
helpful_votes | integer | Helpful-vote count. |
url | string or null | Permalink to the review on tripadvisor.com. |
user_name | string or null | Reviewer display name. |
user_id | string or null | Reviewer id. |
user_hometown | string or null | Reviewer's stated hometown. |
user_contributions | integer or null | Number of contributions the reviewer has made. |
owner_response | object or null | The owner/management reply: text, published_date, responder, connection. |
additional_ratings | array | Feature sub-ratings, e.g. [{ "feature": "Rooms", "rating": 4 }]. |
photos | array | Reviewer photo URLs. |
place_name | string or null | The location's name. |
place_url | string or null | The 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.
maxReviewsis 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.
languagefilters to one language at a time (defaulten) and sets the machine-translation target. To cover another language, run the location again with a differentlanguage. - Owner replies appear only when the property replied. Most reviews have no reply;
owner_responseis simplynullon 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
- Open the Actor in the Apify Console.
- Set
url(single) orurls(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. - Set
maxReviewsto cap how many reviews to return per location, and optionallylanguagefor the review language. - Click Start. Each review is one
success: truerecord. Locations that cannot be listed produce onesuccess: falserecord 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.