# Tripadvisor Reviews Scraper — Most Comprehensive (`scrapersdelight/tripadvisor-reviews-scraper`) Actor

From $0.30 per 1,000 reviews — 16x cheaper than $5/1k incumbents. Scrape TripAdvisor hotel, restaurant & attraction reviews: full text, ratings, sub-ratings, dates, trip type, owner responses, photos. New-review monitor with Slack/email/webhook alerts. No login or API key.

- **URL**: https://apify.com/scrapersdelight/tripadvisor-reviews-scraper.md
- **Developed by:** [Scrapers Delight](https://apify.com/scrapersdelight) (community)
- **Categories:** AI, E-commerce, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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 — Most Comprehensive

**Scrape TripAdvisor reviews for any hotel, restaurant, or attraction — full review text, bubble rating, sub-ratings (Value / Service / Food / Atmosphere / Rooms…), date of stay, trip type, helpful votes, photos, language & translation flag, and the complete owner/management response — at $0.30 per 1,000 reviews. Then schedule it as a new-review monitor that pings Slack, email, or a webhook the moment a fresh review lands.**

### Why this one? (honest comparison)

| | **This actor** | Leading TripAdvisor reviews scraper |
|---|---|---|
| **Price per 1,000 reviews** | **$0.30** (pay-per-event) | $5.00 (pay per result) |
| Full review text | ✅ | ✅ |
| Sub-ratings (Value/Service/Rooms…) | ✅ | ❌ |
| Owner / management response (+date, responder role) | ✅ | ✅ (text only) |
| Date of stay/visit + trip type | ✅ | ✅ |
| Helpful votes | ✅ | ❌ |
| Review photos | ✅ | ✅ |
| Language + machine-translation flag | ✅ | ✅ |
| Date-range filter with **early-stop** (stops paginating, stops billing) | ✅ | partial |
| Keyword / rating-band filters | ✅ | ❌ |
| **New-review monitor** + Slack/email/webhook alerts | ✅ | ❌ |
| GDPR `stripPersonalData` toggle (default ON) | ✅ | ❌ |
| Raw source object kept per review | ✅ | ❌ |
| Failure handling | per-page retry with fresh proxy session; one bad page never kills the run | — |

*Competitor capabilities/prices as listed on their store pages, June 2026 — verify current state there.*

---

### What does Tripadvisor Reviews Scraper do?

It extracts **every review of any TripAdvisor place** — hotels (`Hotel_Review-…` URLs), restaurants (`Restaurant_Review-…`), attractions (`Attraction_Review-…`) — and returns clean, structured rows you can export to **JSON, CSV, Excel, or pull via API**:

- ⭐ **Rating & sub-ratings** — overall bubble rating plus per-category scores (Value, Service, Food, Atmosphere, Rooms, Cleanliness, Sleep Quality, Location…).
- 📝 **Full review text + title** — not truncated, HTML-clean.
- 📅 **All three dates** — published date, written date, and the actual **date of stay/visit**.
- 🧳 **Trip type** — FAMILY / COUPLES / SOLO / BUSINESS / FRIENDS.
- 💬 **Owner & management responses** — full response text, response date, and the responder's role (e.g. "Guest Services / Front Office").
- 👍 **Helpful votes**, 📷 **review photos** (full-size CDN URLs), 🌐 **language + translated-or-not flag**.
- 🏨 **Place context on every row** — place name, ID, type, overall rating, total review count.
- 🗃️ **`raw` sub-object** — the complete source record, so a TripAdvisor field we didn't flatten is still yours.
- 🔔 **Monitor mode** — run it on a schedule and get **only the reviews that are new since last run**, with Slack/email/webhook alerts.

### Who is it for?

- 🏨 **Hotel & restaurant operators** tracking their own (and competitors') reputation — sub-ratings show *what* slipped, owner-response fields show who's answering.
- 📊 **Hospitality analysts & revenue managers** building review datasets across portfolios.
- 🤖 **AI/NLP teams** that need full-text review corpora with ratings and dates for sentiment models.
- 🛎️ **Agencies** running reputation dashboards — monitor mode + webhooks pipes new reviews straight into your stack.
- 🔎 **Travelers & researchers** pulling complaint patterns (`minRating:1, maxRating:2`) before booking.

### How to use it (step by step)

1. Click **Try for free**.
2. Paste one or more TripAdvisor place URLs (the page you'd send a friend — hotel, restaurant, or attraction).
3. (Optional) set `maxReviewsPerPlace` (default 50; `0` = every review), date range, keyword, rating band, language.
4. Click **Start**, open the **Dataset** tab, export.
5. (Optional) turn on `monitorMode`, attach an Apify **Schedule**, add a Slack/webhook/email channel — get pinged on every new review.

#### Quick start

```json
{
    "startUrls": ["https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_Hotel-New_York_City_New_York.html"],
    "maxReviewsPerPlace": 50
}
````

#### Pull every review since a date (early-stops = you stop paying)

```json
{
    "startUrls": ["https://www.tripadvisor.com/Restaurant_Review-g31979-d477015-Reviews-R_Landry_s_New_Orleans_Cafe-Van_Buren_Arkansas.html"],
    "maxReviewsPerPlace": 0,
    "dateFrom": "2026-01-01"
}
```

#### Reputation monitor (the recurring play)

```json
{
    "startUrls": ["https://www.tripadvisor.com/Hotel_Review-g45963-d91703-Reviews-Bellagio-Las_Vegas_Nevada.html"],
    "monitorMode": true,
    "slackWebhookUrl": "https://hooks.slack.com/services/…"
}
```

### Output example (truncated)

```json
{
    "review_id": "935650210",
    "review_url": "https://www.tripadvisor.com/ShowUserReviews-g31979-d477015-r935650210-R_Landry_s_New_Orleans_Cafe-Van_Buren_Arkansas.html",
    "place_id": "477015",
    "place_name": "R. Landry's New Orleans Cafe",
    "place_type": "EATERY",
    "place_rating": 4.5,
    "place_review_count": 146,
    "title": "Top Notch Cajun Cuisine!",
    "text": "My husband and I got the cajun trio tonight. We didn't realize it was a drive through establishment…",
    "rating": 5,
    "subratings": { "Value": 4, "Service": 5, "Food": 5, "Atmosphere": 2 },
    "published_date": "2024-01-27",
    "stay_date": "2024-01-31",
    "trip_type": "FAMILY",
    "helpful_votes": 0,
    "language": "en",
    "is_translated": false,
    "owner_response": {
        "text": "Every member of our team is smiling reading this…",
        "published_date": "2026-06-10",
        "responder": "Hotel Manager",
        "responder_role": "Guest Services / Front Office"
    },
    "photos": ["https://dynamic-media-cdn.tripadvisor.com/media/photo-o/26/d8/29/ce/caption.jpg?w=1200&h=-1&s=1"],
    "reviewer_hometown": "Van Buren, Arkansas",
    "reviewer_contributions": 685
}
```

With `stripPersonalData: false` you additionally get `reviewer_name`, `reviewer_username`, `reviewer_profile_url`, `reviewer_avatar`.

### Input

| Field | What it does |
|-------|--------------|
| `startUrls` | TripAdvisor place URLs (hotel / restaurant / attraction) |
| `maxReviewsPerPlace` | cap per place (default 50; `0` = all) |
| `stripPersonalData` | **default `true`** — drop reviewer name/username/profile/avatar |
| `dateFrom` / `dateTo` | publish-date window; `dateFrom` early-stops pagination |
| `keyword` | only reviews containing this text |
| `language` | only reviews in this language code (client-side filter) |
| `minRating` / `maxRating` | bubble-rating band (e.g. 1–2 = complaints only) |
| `sortOutput` | `newest` · `oldest` · `highest` · `lowest` |
| `monitorMode`, `alertOnNewReview` | recurring new-review watcher |
| `webhookUrl`, `slackWebhookUrl`, `emailRecipients` | alert channels |
| `proxyConfiguration` | keep **RESIDENTIAL** (default) — TripAdvisor runs DataDome |

### How much does it cost?

Pay-per-event — you pay for what you pull, no subscription:

| Event | What it covers | Price |
|-------|----------------|-------|
| `lot-scraped` | each review returned | **$0.0003** |
| `monitor-run-completed` | each scheduled watch run | $0.02 |
| `new-lot-detected` | each new review found by the monitor | $0.002 |
| `alert-delivered` | each Slack/email/webhook push | $0.005 |

That's **$0.30 per 1,000 reviews** — the same 1,000 reviews cost **$5.00** on the leading per-result competitor. A daily monitor on one hotel costs ~$0.60/month plus a fraction of a cent per new review. *(Plus standard Apify platform usage; final prices are set on the actor's pricing page.)*

### Is it legal? (read this)

- Review text, ratings, and owner responses are **publicly visible without any login**. This actor only reads public pages — no login, no API key, no paywall circumvention.
- **Reviewer identities are personal data.** That's why `stripPersonalData` defaults to **ON**, removing names, usernames, profile links and avatars. Only disable it if you have a lawful basis (GDPR/CCPA) to process reviewer identities, and expect to honor deletion requests.
- Scraping may conflict with **TripAdvisor's Terms of Service**. Republishing TripAdvisor content commercially is restricted by their terms. You are responsible for your use of the data — for most users that means internal analysis, not republication.

### FAQ

**Which TripAdvisor pages does it support?**
Hotels (`Hotel_Review-…`), restaurants (`Restaurant_Review-…`), attractions (`Attraction_Review-…`), and vacation rentals. Paste the normal page URL; redirects to the canonical page are followed automatically.

**Do I need a TripAdvisor account or API key?**
No. The data is read from the public page itself.

**How many reviews can I get per place?**
All of them — set `maxReviewsPerPlace: 0`. Hotels/attractions paginate 10 per page, restaurants 15; the actor walks the pages until your cap, your date floor, or the end.

**Does it return owner/management responses?**
Yes — full text, response date, responder display name and role, on every review that has one.

**Does it return sub-ratings like Value, Service, Rooms?**
Yes, as a `subratings` object whenever the reviewer filled them in.

**Can I get only negative reviews?**
Yes — `minRating: 1, maxRating: 2` returns only 1–2-bubble reviews.

**Can I get only new reviews on a schedule?**
Yes — `monitorMode: true` + an Apify Schedule. State is kept in a named key-value store, so each run emits only reviews it hasn't seen before, and can alert Slack/email/webhook per review.

**What about non-English reviews and translations?**
Each review carries `language`, `original_language`, and `is_translated`. TripAdvisor's US pages serve mostly English; use the `language` filter to keep a single language.

**Why residential proxies?**
TripAdvisor is protected by DataDome. The actor's browser-fingerprint HTTP client plus residential rotation gets through reliably; datacenter IPs get blocked much more often. Failed pages are retried with a fresh session and never kill the run.

**How fast is it?**
About 1–2 seconds per page of 10–15 reviews — 1,000 reviews in a few minutes.

**Is the reviewer's name included?**
Only if you set `stripPersonalData: false` (see the legal section). By default the output is anonymized but keeps hometown and contribution count for weighting.

**Can I export to Excel / CSV / my backend?**
Yes — Dataset tab exports JSON/CSV/Excel/HTML/RSS, or use the Apify API / webhooks to pipe rows anywhere.

**A field I need isn't flattened — am I stuck?**
No. Every row carries the complete `raw` source object from TripAdvisor's own data layer.

### You might also like

- 🛏️ Hotel price & availability scrapers
- 🍽️ Restaurant directory & menu scrapers
- ⭐ Google Maps / Yelp review scrapers

### Feedback

Found a missing field or want a new filter? Open an issue on the actor — fast fixes and feature requests welcome.

# Actor input Schema

## `startUrls` (type: `array`):

One or more TripAdvisor place URLs — hotels (Hotel\_Review-…), restaurants (Restaurant\_Review-…), or attractions (Attraction\_Review-…). Any tripadvisor.com page URL of the place works; the actor follows redirects to the canonical page.

## `maxReviewsPerPlace` (type: `integer`):

Hard cap on reviews scraped per place (cost/safety guard). Defaults to 50 for a fast first run — set 0 to pull EVERY review of the place.

## `stripPersonalData` (type: `boolean`):

ON by default: drops reviewer display name, username, profile URL, and avatar from the output (coarse hometown + contribution count are kept). Turn OFF only if you have a lawful basis to process reviewer identities.

## `keyword` (type: `string`):

Only keep reviews whose title or text contains this keyword (case-insensitive, applied client-side while paginating).

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

Only keep reviews in this language code (e.g. 'en', 'de', 'es'). Applied client-side — TripAdvisor's server pages list English first, so non-English yields may be lower.

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

Only reviews published on/after this date. Reviews come newest-first, so the actor STOPS paginating once a whole page is older than this — big cost saver for incremental pulls.

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

Only reviews published on/before this date.

## `minRating` (type: `integer`):

Only reviews with at least this bubble rating. 0 = no floor. E.g. 1 + maxRating 2 isolates complaints.

## `maxRating` (type: `integer`):

Only reviews with at most this bubble rating. 5 = no cap.

## `sortOutput` (type: `string`):

Ordering of the final dataset (collection itself always walks the site's newest-first pages).

## `monitorMode` (type: `boolean`):

Recurring watcher: diff against the prior run's seen reviews (per place) and output/alert ONLY new reviews. Pair with an Apify Schedule (e.g. daily) for review-reputation alerting.

## `alertOnNewReview` (type: `boolean`):

In monitor mode, deliver an alert for each new review via the channels below.

## `webhookUrl` (type: `string`):

POST endpoint for new-review alert payloads (Make / Zapier / n8n / custom). One JSON body per alert.

## `slackWebhookUrl` (type: `string`):

Slack incoming-webhook URL for formatted new-review cards (rating, title, excerpt, link).

## `emailRecipients` (type: `array`):

Email addresses for the new-review digest (sent via apify/send-mail).

## `proxyConfiguration` (type: `object`):

TripAdvisor sits behind DataDome — keep RESIDENTIAL proxies (the default). Datacenter IPs get blocked far more often.

## `diagnose` (type: `boolean`):

Dev only. Fetches page 1 of the first place, dumps the decoded review JSON to the key-value store (DEBUG\_REVIEW\_LIST) and logs the parsed first record, then exits.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_Hotel-New_York_City_New_York.html"
  ],
  "maxReviewsPerPlace": 50,
  "stripPersonalData": true,
  "minRating": 0,
  "maxRating": 5,
  "sortOutput": "newest",
  "monitorMode": false,
  "alertOnNewReview": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "diagnose": false
}
```

# Actor output Schema

## `items` (type: `string`):

The dataset of scraped TripAdvisor reviews (one review per row).

# 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 = {
    "startUrls": [
        "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_Hotel-New_York_City_New_York.html"
    ],
    "maxReviewsPerPlace": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapersdelight/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 = {
    "startUrls": ["https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_Hotel-New_York_City_New_York.html"],
    "maxReviewsPerPlace": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("scrapersdelight/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 '{
  "startUrls": [
    "https://www.tripadvisor.com/Hotel_Review-g60763-d93589-Reviews-The_Michelangelo_Hotel-New_York_City_New_York.html"
  ],
  "maxReviewsPerPlace": 50
}' |
apify call scrapersdelight/tripadvisor-reviews-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Tripadvisor Reviews Scraper — Most Comprehensive",
        "description": "From $0.30 per 1,000 reviews — 16x cheaper than $5/1k incumbents. Scrape TripAdvisor hotel, restaurant & attraction reviews: full text, ratings, sub-ratings, dates, trip type, owner responses, photos. New-review monitor with Slack/email/webhook alerts. No login or API key.",
        "version": "0.1",
        "x-build-id": "fMFTO6wdmfAftmNJ4"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/scrapersdelight~tripadvisor-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-scrapersdelight-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/scrapersdelight~tripadvisor-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-scrapersdelight-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/scrapersdelight~tripadvisor-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-scrapersdelight-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",
                "required": [
                    "startUrls"
                ],
                "properties": {
                    "startUrls": {
                        "title": "TripAdvisor place URLs",
                        "type": "array",
                        "description": "One or more TripAdvisor place URLs — hotels (Hotel_Review-…), restaurants (Restaurant_Review-…), or attractions (Attraction_Review-…). Any tripadvisor.com page URL of the place works; the actor follows redirects to the canonical page.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxReviewsPerPlace": {
                        "title": "Max reviews per place",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Hard cap on reviews scraped per place (cost/safety guard). Defaults to 50 for a fast first run — set 0 to pull EVERY review of the place.",
                        "default": 50
                    },
                    "stripPersonalData": {
                        "title": "Strip reviewer personal data (GDPR-friendly)",
                        "type": "boolean",
                        "description": "ON by default: drops reviewer display name, username, profile URL, and avatar from the output (coarse hometown + contribution count are kept). Turn OFF only if you have a lawful basis to process reviewer identities.",
                        "default": true
                    },
                    "keyword": {
                        "title": "Keyword filter",
                        "type": "string",
                        "description": "Only keep reviews whose title or text contains this keyword (case-insensitive, applied client-side while paginating)."
                    },
                    "language": {
                        "title": "Language filter",
                        "type": "string",
                        "description": "Only keep reviews in this language code (e.g. 'en', 'de', 'es'). Applied client-side — TripAdvisor's server pages list English first, so non-English yields may be lower."
                    },
                    "dateFrom": {
                        "title": "Date from (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Only reviews published on/after this date. Reviews come newest-first, so the actor STOPS paginating once a whole page is older than this — big cost saver for incremental pulls."
                    },
                    "dateTo": {
                        "title": "Date to (YYYY-MM-DD)",
                        "type": "string",
                        "description": "Only reviews published on/before this date."
                    },
                    "minRating": {
                        "title": "Min rating (1-5)",
                        "minimum": 0,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Only reviews with at least this bubble rating. 0 = no floor. E.g. 1 + maxRating 2 isolates complaints.",
                        "default": 0
                    },
                    "maxRating": {
                        "title": "Max rating (1-5)",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Only reviews with at most this bubble rating. 5 = no cap.",
                        "default": 5
                    },
                    "sortOutput": {
                        "title": "Sort output by",
                        "enum": [
                            "newest",
                            "oldest",
                            "highest",
                            "lowest"
                        ],
                        "type": "string",
                        "description": "Ordering of the final dataset (collection itself always walks the site's newest-first pages).",
                        "default": "newest"
                    },
                    "monitorMode": {
                        "title": "Monitor mode (new-review watcher)",
                        "type": "boolean",
                        "description": "Recurring watcher: diff against the prior run's seen reviews (per place) and output/alert ONLY new reviews. Pair with an Apify Schedule (e.g. daily) for review-reputation alerting.",
                        "default": false
                    },
                    "alertOnNewReview": {
                        "title": "Alert on new reviews",
                        "type": "boolean",
                        "description": "In monitor mode, deliver an alert for each new review via the channels below.",
                        "default": true
                    },
                    "webhookUrl": {
                        "title": "Webhook URL",
                        "type": "string",
                        "description": "POST endpoint for new-review alert payloads (Make / Zapier / n8n / custom). One JSON body per alert."
                    },
                    "slackWebhookUrl": {
                        "title": "Slack webhook URL",
                        "type": "string",
                        "description": "Slack incoming-webhook URL for formatted new-review cards (rating, title, excerpt, link)."
                    },
                    "emailRecipients": {
                        "title": "Email recipients",
                        "type": "array",
                        "description": "Email addresses for the new-review digest (sent via apify/send-mail).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "TripAdvisor sits behind DataDome — keep RESIDENTIAL proxies (the default). Datacenter IPs get blocked far more often.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    },
                    "diagnose": {
                        "title": "Diagnostic mode (dev)",
                        "type": "boolean",
                        "description": "Dev only. Fetches page 1 of the first place, dumps the decoded review JSON to the key-value store (DEBUG_REVIEW_LIST) and logs the parsed first record, then exits.",
                        "default": false
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
