# TripAdvisor Reviews Scraper (`apihq/tripadvisor-reviews-scraper`) Actor

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.

- **URL**: https://apify.com/apihq/tripadvisor-reviews-scraper.md
- **Developed by:** [apihq dev](https://apify.com/apihq) (community)
- **Categories:** Developer tools, Business, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.40 / 1,000 reviews

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## TripAdvisor Reviews Scraper

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:

```json
{
  "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:

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

A batch, in French:

```json
{
  "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:

```json
{
  "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:

```json
{
  "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:

```json
{
  "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.** `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.

```json
{
  "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.

# Actor input Schema

## `url` (type: `string`):

A single TripAdvisor detail page URL (hotel, restaurant, or attraction) or a bare numeric location id (e.g. '93589'). An unrecognizable value comes back as a success:false record (code VALIDATION\_FAILED), not a rejected run.

## `urls` (type: `array`):

List of TripAdvisor detail URLs or numeric location ids. Merged with url and de-duplicated (a URL and its bare id count as the same location); up to 50 unique locations are processed per run. A location with no reviews comes back as a success:false record, so one bad location never blocks the batch.

## `maxReviews` (type: `integer`):

Maximum target per location, not a guaranteed count. The Actor may return fewer when fewer reviews are available, or when an anti-bot challenge, timeout, or capacity stop ends the walk early (reviews already delivered are kept, the run still succeeds, and only delivered reviews are charged). Very large values are also bounded by the run's time limit: the Actor stops cleanly with a free diagnostic before the run times out.

## `language` (type: `string`):

Two-letter language code (e.g. 'en', 'fr', 'de', or a locale like 'pt-BR'). Filters reviews to that language and sets the machine-translation target. Defaults to 'en'. An unrecognized value falls back to 'en'.

## `ratings` (type: `array`):

Keep only reviews with these bubble ratings (1 to 5). Leave empty for all ratings. If you pass a mix of valid and invalid values, the valid ones are used and the rest ignored; if every value you pass is invalid (e.g. only \[6]), the run stops immediately with one free INVALID\_FILTER row and still succeeds, rather than silently returning unfiltered reviews.

## `travelerTypes` (type: `array`):

Keep only reviews from these traveler types. Leave empty for all types. A mix of valid and invalid values uses the valid ones; if every value is invalid, the run stops with one free INVALID\_FILTER row and still succeeds, rather than returning unfiltered reviews.

## `dateFrom` (type: `string`):

Keep only reviews published on or after this date (YYYY-MM-DD). Leave empty for no lower bound. A non-empty value that is not a valid date, or a range where dateFrom is after dateTo, stops the run with one free INVALID\_FILTER row (and still succeeds), rather than returning reviews outside your window.

## `dateTo` (type: `string`):

Keep only reviews published on or before this date (YYYY-MM-DD). Leave empty for no upper bound. A non-empty value that is not a valid date stops the run with one free INVALID\_FILTER row (and still succeeds), rather than returning reviews outside your window.

## Actor input object example

```json
{
  "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_New_York.html",
  "maxReviews": 100,
  "language": "en"
}
```

# Actor output Schema

## `reviews` (type: `string`):

One record per review. success:true carries the review fields (billed). success:false carries an error code and message and is free: either one bad/empty location, or the single global early-stop diagnostic row that stops the walk when TripAdvisor challenges the request or a timeout/capacity limit is reached.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_New_York.html",
    "maxReviews": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("apihq/tripadvisor-reviews-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_New_York.html",
    "maxReviews": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("apihq/tripadvisor-reviews-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_New_York.html",
  "maxReviews": 100
}' |
apify call apihq/tripadvisor-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=apihq/tripadvisor-reviews-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "TripAdvisor Reviews Scraper",
        "description": "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.",
        "version": "0.1",
        "x-build-id": "KL4b2JvX9qR3fILn5"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/apihq~tripadvisor-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-apihq-tripadvisor-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/apihq~tripadvisor-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-apihq-tripadvisor-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/apihq~tripadvisor-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-apihq-tripadvisor-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "url": {
                        "title": "Location (URL or id)",
                        "type": "string",
                        "description": "A single TripAdvisor detail page URL (hotel, restaurant, or attraction) or a bare numeric location id (e.g. '93589'). An unrecognizable value comes back as a success:false record (code VALIDATION_FAILED), not a rejected run."
                    },
                    "urls": {
                        "title": "Multiple locations",
                        "type": "array",
                        "description": "List of TripAdvisor detail URLs or numeric location ids. Merged with url and de-duplicated (a URL and its bare id count as the same location); up to 50 unique locations are processed per run. A location with no reviews comes back as a success:false record, so one bad location never blocks the batch.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxReviews": {
                        "title": "Max reviews per location",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Maximum target per location, not a guaranteed count. The Actor may return fewer when fewer reviews are available, or when an anti-bot challenge, timeout, or capacity stop ends the walk early (reviews already delivered are kept, the run still succeeds, and only delivered reviews are charged). Very large values are also bounded by the run's time limit: the Actor stops cleanly with a free diagnostic before the run times out."
                    },
                    "language": {
                        "title": "Review language",
                        "type": "string",
                        "description": "Two-letter language code (e.g. 'en', 'fr', 'de', or a locale like 'pt-BR'). Filters reviews to that language and sets the machine-translation target. Defaults to 'en'. An unrecognized value falls back to 'en'.",
                        "default": "en"
                    },
                    "ratings": {
                        "title": "Ratings",
                        "type": "array",
                        "description": "Keep only reviews with these bubble ratings (1 to 5). Leave empty for all ratings. If you pass a mix of valid and invalid values, the valid ones are used and the rest ignored; if every value you pass is invalid (e.g. only [6]), the run stops immediately with one free INVALID_FILTER row and still succeeds, rather than silently returning unfiltered reviews.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "1",
                                "2",
                                "3",
                                "4",
                                "5"
                            ],
                            "enumTitles": [
                                "1 - Terrible",
                                "2 - Poor",
                                "3 - Average",
                                "4 - Very good",
                                "5 - Excellent"
                            ]
                        }
                    },
                    "travelerTypes": {
                        "title": "Traveler types",
                        "type": "array",
                        "description": "Keep only reviews from these traveler types. Leave empty for all types. A mix of valid and invalid values uses the valid ones; if every value is invalid, the run stops with one free INVALID_FILTER row and still succeeds, rather than returning unfiltered reviews.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "Business",
                                "Couples",
                                "Family",
                                "Friends",
                                "Solo"
                            ]
                        }
                    },
                    "dateFrom": {
                        "title": "Reviews from (inclusive)",
                        "type": "string",
                        "description": "Keep only reviews published on or after this date (YYYY-MM-DD). Leave empty for no lower bound. A non-empty value that is not a valid date, or a range where dateFrom is after dateTo, stops the run with one free INVALID_FILTER row (and still succeeds), rather than returning reviews outside your window."
                    },
                    "dateTo": {
                        "title": "Reviews to (inclusive)",
                        "type": "string",
                        "description": "Keep only reviews published on or before this date (YYYY-MM-DD). Leave empty for no upper bound. A non-empty value that is not a valid date stops the run with one free INVALID_FILTER row (and still succeeds), rather than returning reviews outside your window."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
