# TripAdvisor Reviews Scraper 💰$0.45/1k | Hotels Restaurants (`memo23/tripadvisor-scraper`) Actor

TripAdvisor Reviews Scraper at $0.45/1k — 4x cheaper than the leader. Pull hotel, restaurant & attraction reviews with place metadata (rating, address, geo, histogram) in every row. Filter by rating, language & date; add reviewer profiles. Search-query or URL input. JSON/CSV out.

- **URL**: https://apify.com/memo23/tripadvisor-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Travel, Automation, Agents
- **Stats:** 63 total users, 9 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.45 / 1,000 results

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

<p align="center">
  <img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/tripadvisor-logo.png" alt="TripAdvisor Reviews Scraper" width="140" height="140" />
</p>

## TripAdvisor Reviews Scraper — Hotels, Restaurants & Attractions

**Scrape TripAdvisor reviews at $0.45 per 1,000 results — about 4x cheaper than the market leader, and one actor instead of a two-step funnel.**
Paste any hotel, restaurant, or attraction URL (or just a city name) and get clean, structured review rows — each already enriched with the place's full metadata (rating, address, geo, ranking, rating histogram). Filter by star rating, language, and date; optionally add reviewer profiles and contact emails. JSON, CSV, or Excel out.

<p align="center">
  <img src="https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/tripadvisor-card.png" alt="TripAdvisor Reviews Scraper card" width="720" />
</p>

### Why Use This Scraper?

- ✅ **Cheapest serious option — $0.45/1,000 results.** The category leader charges around $1.90/1,000 at its entry tier. Same review data, a fraction of the bill.
- ✅ **One actor, not two.** Reviews **and** place snapshots come from the same run — no separate "find places" actor feeding a separate "reviews" actor.
- ✅ **Hotels, restaurants, and attractions** — all three place types, all through one input.
- ✅ **Review + place metadata in every row.** Each review already carries `placeInfo` (rating, address, lat/lng, ranking, histogram). No follow-up enrichment step.
- ✅ **Server-side filters** for star rating, language, per-place limit, plus an absolute or relative date cutoff.
- ✅ **Search-query → geo expansion.** Type `"Chicago"` and let the actor discover hotels, restaurants, and attractions for that location.
- ✅ **Optional reviewer profiles and contact-email enrichment.**
- ✅ **Flat, nested, or place-only output** for whatever your pipeline expects.

### Overview

The TripAdvisor Reviews Scraper is built for reputation teams, market analysts, researchers, and agencies who need structured review data from TripAdvisor without stitching together multiple tools.

By default the output is **review-shaped**: one dataset row per review, each carrying a compact `placeInfo` block for the parent hotel/restaurant/attraction. That means even if you start from a *listing* URL (a city's restaurants hub) or a *search query*, the run still resolves down to a stream of review rows — not separate "listing" rows.

Two other shapes are available when you need them:

- **Place-only snapshots** (`scrapeReviews: false`) — one rich row per place (ranking, amenities, category scores, nearby venues) and no reviews. Fast and low-cost for competitor monitoring.
- **Nested** (`outputShape: "nested"`) — one row per place with a `reviews[]` array inside.

### Supported Inputs

#### URL types

| URL type | Pattern | Example |
|---|---|---|
| Hotel place | `Hotel_Review-g{geo}-d{id}-Reviews-{slug}.html` | `https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html` |
| Restaurant place | `Restaurant_Review-g{geo}-d{id}-Reviews-{slug}.html` | `https://www.tripadvisor.com/Restaurant_Review-g60763-d25324283-Reviews-Allora_Fifth_Ave-New_York_City_New_York.html` |
| Attraction place | `Attraction_Review-g{geo}-d{id}-Reviews-{slug}.html` | `https://www.tripadvisor.com/Attraction_Review-g60763-d105123-Reviews-Statue_of_Liberty-New_York_City_New_York.html` |
| Restaurants GEO hub | `Restaurants-g{geo}-…{City}.html` | `https://www.tripadvisor.com/Restaurants-g35805-Chicago_Illinois.html` |
| Hotels GEO hub | `Hotels-g{geo}-…-Hotels.html` | `https://www.tripadvisor.com/Hotels-g60763-New_York_City_New_York-Hotels.html` |
| Attractions GEO hub | `Attractions-g{geo}-Activities-…html` | `https://www.tripadvisor.com/Attractions-g60763-Activities-New_York_City_New_York.html` |
| Restaurant finder | `FindRestaurants?geo=…&establishmentTypes=…` | `https://www.tripadvisor.com/FindRestaurants?geo=188673&establishmentTypes=10591&broadened=false` |

Listing/hub URLs expand (paginated, up to ~300 venues each) into individual place URLs, then each is scraped like a standalone place. `maxItems` applies **per resolved place**.

#### Copy-pasteable startUrls

```json
{
  "startUrls": [
    { "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html" },
    { "url": "https://www.tripadvisor.com/Restaurant_Review-g60763-d25324283-Reviews-Allora_Fifth_Ave-New_York_City_New_York.html" },
    { "url": "https://www.tripadvisor.com/Restaurants-g35805-Chicago_Illinois.html" }
  ]
}
```

#### Search / keyword mode

```json
{
  "searchQuery": "Chicago",
  "includeHotels": true,
  "includeRestaurants": true,
  "includeThingsToDo": true,
  "maxItems": 20
}
```

#### Unsupported inputs

- ❌ `tripadvisor.co.uk` / `tripadvisor.*` country mirrors — use `www.tripadvisor.com`.
- ❌ Vacation rentals, tours/experiences, and flights products.
- ❌ Hotel booking price offers / room rates.
- ❌ Non-TripAdvisor hosts and login-gated content.

### Use Cases

| Audience | Use case |
|---|---|
| **Hotel & restaurant ops** | Daily review monitoring and owner-response SLA tracking |
| **Reputation managers** | Multi-property dashboards with rating-histogram drift over time |
| **Market analysts** | Competitive benchmarks across cities or chains using `placeInfo.rating` + `numberOfReviews` |
| **Content / NLP teams** | Multilingual review corpora for sentiment and topic models, filtered by language and rating |
| **Researchers** | One-shot dataset exports for BI, lake, or warehouse ingestion |
| **Agencies** | Client-ready TripAdvisor datasets without writing or maintaining a scraper |

### How It Works

![How TripAdvisor Reviews Scraper works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-tripadvisor.png)

1. **Input** — provide one or more TripAdvisor URLs, or a free-text `searchQuery` (a city name).
2. **Resolve** — a `searchQuery` becomes a geoId, then expands into hotels, restaurants, and attractions per the `include*` toggles. Listing/hub URLs expand into place URLs. Plain place URLs are used directly.
3. **Fetch place** — load each place page (mobile-friendly HTML) and extract `placeInfo` from JSON-LD + meta (rating, review count, address, geo, ranking).
4. **Page reviews** — pull reviews from TripAdvisor GraphQL in concurrent batches, with `reviewRatings`, `reviewsLanguages`, and `maxItems` pushed into the request; `lastReviewDate` is applied per page with early-exit.
5. **Optional enrichment** — attach reviewer profiles (`scrapeReviewerInfo`) and contact emails (`enrichEmails`).
6. **Output** — emit flat review rows (default), nested place rows, or place-only snapshots. Locations that yield 0 reviews or fail land in a side `tripadvisor-failures` dataset.

### Input Configuration

| Field | Type | Default | Notes |
|---|---|---|---|
| `searchQuery` | string | — | Free-text location (e.g. `"Chicago"`). Resolved to a geoId, then expanded by the `include*` toggles. Use with or instead of `startUrls`. |
| `startUrls` | array of `{ url }` | `[]` | Place URLs and/or listing/hub URLs. Listing URLs expand to venues; place URLs are scraped directly. |
| `maxItems` | integer | `50` | Max reviews **per place / per URL**. `0` = unlimited (paginate every review). |
| `scrapeReviews` | boolean | `true` | `true` → fetch reviews. `false` → emit one place-only snapshot row per place (no reviews). |
| `scrapeReviewerInfo` | boolean | `true` | Populate each review's `user` object (username, hometown, contributions, avatar, profile link). `false` → `user: null`. |
| `includeReviewTags` | boolean | `true` | Include `placeInfo.reviewTags` (theme phrases + counts) when TripAdvisor embeds them. |
| `includeHotels` | boolean | `true` | With `searchQuery`, include hotels for the resolved geo. |
| `includeRestaurants` | boolean | `true` | With `searchQuery`, include restaurants for the resolved geo. |
| `includeThingsToDo` | boolean | `true` | With `searchQuery`, include attractions for the resolved geo. |
| `includeNearby` | boolean | `false` | After each place, add up to 5 nearby venues as place-only snapshot rows (`isNearbyResult: true`). Depth capped at 1. |
| `outputShape` | enum `flat` / `nested` | `flat` | `flat` = one row per review. `nested` = one row per place with `reviews[]`. No effect when `scrapeReviews: false`. |
| `lastReviewDate` | string | — | Skip reviews before this date. Absolute `YYYY-MM-DD` or relative `22 days` / `3 weeks` / `6 months` / `1 year`. |
| `reviewRatings` | array | `["ALL_REVIEW_RATINGS"]` | Filter by star rating: `"1"`–`"5"` or `ALL_REVIEW_RATINGS`. |
| `reviewsLanguages` | array | `["ALL_REVIEW_LANGUAGES"]` | Filter by ISO 639-1 language code, or `ALL_REVIEW_LANGUAGES`. |
| `maxConcurrency` | integer | `100` | Max pages processed concurrently. |
| `minConcurrency` | integer | `1` | Min pages processed concurrently. |
| `maxRequestRetries` | integer | `15` | Retries per failed request before giving up. |
| `proxy` | object | Apify Residential | Proxy configuration. Residential is strongly recommended. |
| `enrichEmails` | boolean | `false` | Find a contact email per place (from its website or by discovery). Adds `contactEmail`, `contactWebsite`, and an `emailEnrichment` object. Billed only when an email is found. |

#### Common scenarios

**1. All reviews for a single hotel, with reviewer info**

```json
{
  "startUrls": [{ "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html" }],
  "maxItems": 0,
  "scrapeReviewerInfo": true
}
```

**2. Recent 5-star English reviews across a city's restaurants**

```json
{
  "startUrls": [{ "url": "https://www.tripadvisor.com/Restaurants-g35805-Chicago_Illinois.html" }],
  "reviewRatings": ["5"],
  "reviewsLanguages": ["en"],
  "lastReviewDate": "6 months",
  "maxItems": 30
}
```

**3. Place-only competitor snapshots (no reviews)**

```json
{
  "searchQuery": "Brooklyn",
  "includeHotels": true,
  "includeRestaurants": true,
  "includeThingsToDo": false,
  "scrapeReviews": false
}
```

### Output Overview

Each dataset item is, by default, one **review** row containing:

- **Core** — `id`, `url`, `title`, `text`, `rating`, `publishedDate`, `travelDate`, `tripType`, `lang`
- **Reviewer** — `user` object (username, hometown, contributions, avatar, profile link) when `scrapeReviewerInfo: true`
- **Owner response** — `ownerResponse` (text + date) when the property replied
- **Extras** — `subratings[]`, `photos[]`, `helpfulVotes`
- **Parent place** — `placeInfo` (name, type, rating, web URL, and more)

When `scrapeReviews: false`, rows are `{ placeDetailOnly: true, placeInfo: {…} }` with a much richer `placeInfo` (ranking, amenities, category scores, nearby venues, histogram).

### Output Samples

#### Flat review row (default)

```jsonc
{
  "id": "1058000050",
  "url": "https://www.tripadvisor.com/ShowUserReviews-g60763-d208453-r1058000050-Hilton_New_York_Times_Square-New_York_City_New_York.html",
  "title": "Was wonderful bravo to Kayla",
  "lang": "en",
  "publishedDate": "2026-04-26",
  "publishedPlatform": "MOBILE",
  "rating": 5,
  "helpfulVotes": 0,
  "text": "Kayla was amazing and gave us great service",
  "travelDate": "2026-04",
  "tripType": "COUPLES",
  "user": {
    "name": "Dubi Shoshan",
    "username": "OnAir02493636276",
    "userLocation": { "name": "Yehud, Israel" },
    "contributions": { "totalContributions": 1 },
    "link": "www.tripadvisor.com/Profile/OnAir02493636276"
  },
  "ownerResponse": null,
  "subratings": [],
  "photos": [],
  "placeInfo": {
    "id": "208453",
    "name": "Hilton New York Times Square",
    "locationString": "New York City New York",
    "type": "HOTEL",
    "webUrl": "https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews.html"
  }
}
```

#### Place-only snapshot (`scrapeReviews: false`)

```jsonc
{
  "placeDetailOnly": true,
  "placeInfo": {
    "type": "HOTEL",
    "name": "LondonHouse Chicago, Curio Collection by Hilton",
    "rating": 4.7,
    "numberOfReviews": 4941,
    "rankingString": "#4 of 215 hotels in Chicago",
    "address": "85 E Wacker Drive, Chicago, IL 60601",
    "latitude": 41.887833,
    "longitude": -87.62543,
    "ratingHistogram": { "count1": 62, "count2": 62, "count3": 150, "count4": 502, "count5": 4166 },
    "categoryReviewScores": [
      { "categoryName": "Cleanliness", "roundedScore": 4.8 },
      { "categoryName": "Location", "roundedScore": 4.9 }
    ],
    "amenities": ["Valet parking", "Free High Speed Internet (WiFi)", "Rooftop bar", "Spa"],
    "id": "9145578",
    "webUrl": "https://www.tripadvisor.com/Hotel_Review-g35805-d9145578-Reviews.html"
  }
}
```

### Key Output Fields

#### Review core

- `id`, `url`, `title`, `text`, `rating`, `lang`, `helpfulVotes`

#### Dates & trip

- `publishedDate`, `publishedPlatform`, `travelDate`, `stayDate`, `tripType`

#### Reviewer (`scrapeReviewerInfo: true`)

- `user.name`, `user.username`, `user.userLocation.name`, `user.contributions.totalContributions`, `user.avatar.image`, `user.link`

#### Owner response & extras

- `ownerResponse.text`, `ownerResponse.publishedDate`, `subratings[]`, `photos[]`

#### Parent place (`placeInfo`)

- `placeInfo.name`, `placeInfo.type` (`HOTEL` / `EATERY` / `ATTRACTION`), `placeInfo.rating`, `placeInfo.webUrl`
- Place-only rows add: `numberOfReviews`, `rankingString`, `address`, `latitude`, `longitude`, `ratingHistogram`, `categoryReviewScores[]`, `amenities[]`, `nearbyLocations[]`

#### Email enrichment (`enrichEmails: true`)

- `contactEmail`, `contactWebsite`, `emailEnrichment`

### How This Compares

| Capability | Category leader (two-actor funnel) | This actor |
|---|---|---|
| Price per 1,000 results | ~$1.90/1k at entry tier | **$0.45/1k** (~4x cheaper) |
| Places + reviews | Separate "find places" actor feeding a separate "reviews" actor | **One actor** does both |
| Hotels / restaurants / attractions | Split across actors | All three, one input |
| Review + place metadata in one row | Usually separate outputs | **Yes** — `placeInfo` on every review |
| Search-query → geo expansion | Varies | **Built in** (`searchQuery`) |
| Rating / language / date filters | Partial | **Yes**, pushed server-side |
| Reviewer profiles | Add-on | Optional (`scrapeReviewerInfo`) |
| Contact-email enrichment | No | Optional (`enrichEmails`, pay-on-hit) |

> Honest scope: this actor does **not** cover vacation rentals, tours/experiences, flights, hotel price offers, or `sortBy`/traveler-type filters. If you need those, it isn't the right tool.

### FAQ

#### Which TripAdvisor URLs are supported?

Hotel, restaurant, and attraction place pages (`…-g{geo}-d{id}-Reviews-…`), plus GEO listing hubs (`Restaurants-g…`, `Hotels-g…`, `Attractions-g…`) and the `FindRestaurants?geo=…` finder. Listing URLs expand to individual venues. Use `www.tripadvisor.com`, not the `tripadvisor.co.*` mirrors.

#### Do I get review rows or place rows?

Review rows by default — one per review, each carrying a compact `placeInfo`. Set `scrapeReviews: false` for one place-only snapshot per place, or `outputShape: "nested"` for one place row with `reviews[]` nested.

#### How does `maxItems` work?

It caps reviews **per place**, applied independently to each URL and each venue discovered from a listing. Use `0` for unlimited.

#### Can I filter by rating, language, or date?

Yes. `reviewRatings` and `reviewsLanguages` are pushed into the TripAdvisor GraphQL request; `lastReviewDate` (absolute or relative) is applied per page with an early exit once a page is fully older than the cutoff.

#### Are reviewer profiles and emails always present?

`user` is populated when `scrapeReviewerInfo: true` (the default). Contact emails require `enrichEmails: true` and only appear when one is actually found — you are never charged for a miss.

#### What isn't supported?

Vacation rentals, tours/experiences, and flights products; hotel booking price offers; `sortBy` and traveler-type filters; and country-mirror domains. This actor focuses on hotel/restaurant/attraction reviews and place snapshots.

#### Can I scrape private or login-gated content?

No. The actor only reads publicly available TripAdvisor pages.

#### What about blocks and rate limits?

The actor uses a hardened anti-bot path (mobile Safari fallback, real-browser fingerprinting for GraphQL, single-shot DataDome detection). Residential proxies are strongly recommended. Blocked or empty locations are recorded in the `tripadvisor-failures` dataset rather than lost.

### Support

Found a bug or need a new feature? Open an issue on the [Issues tab](https://apify.com/memo23/tripadvisor-scraper/issues) or email **muhamed.didovic@gmail.com**.

### Additional Services

Need a custom output shape, a new URL type, extra fields, or scheduled monitoring? I build tailored scrapers and data pipelines — email **muhamed.didovic@gmail.com**.

### Explore More Scrapers

If you found this useful, you might also like:

- [**Capterra Scraper**](https://apify.com/memo23/capterra-scraper) — software listings + reviews
- [**TrustRadius Scraper**](https://apify.com/memo23/trustradius-scraper) — B2B product reviews
- [**Google Maps Reviews**](https://apify.com/memo23) — local business reviews and place data

Full list at [apify.com/memo23](https://apify.com/memo23).

### 🤖 For AI Agents & LLM Apps

Compact reference for AI agents calling this actor via the [Apify MCP server](https://mcp.apify.com) or the Apify API (actor: `memo23/tripadvisor-scraper`).

**Purpose:** Scrape TripAdvisor hotel, restaurant, and attraction reviews (plus place snapshots) from any place/listing URL or a city search query — every review row carries parent-place metadata.

**Minimal input:**

```json
{
  "startUrls": [{ "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html" }],
  "maxItems": 10
}
```

**Output:** one dataset row per review — `id`, `title`, `text`, `rating`, `lang`, `publishedDate`, `travelDate`, `tripType`, `helpfulVotes`, `user {name, username, userLocation, contributions, link}`, `ownerResponse`, `subratings[]`, `photos[]`, `placeInfo {id, name, type, rating, webUrl}`. With `scrapeReviews:false`, rows are `{placeDetailOnly:true, placeInfo{…}}`.

**Behaviors an agent should know:**

- Always set `maxItems` (it caps reviews **per place**); `maxItems:0` means unlimited and can be very large for popular places.
- `startUrls` and `searchQuery` can be combined; `searchQuery` expands via `includeHotels` / `includeRestaurants` / `includeThingsToDo`.
- `outputShape:"nested"` returns one row per place with `reviews[]`; `scrapeReviews:false` returns place-only snapshots.
- Billing: **$0.45 / 1,000 results** (per dataset item) + **$0.0001** per additional-data item + **$0.007** actor start (per GB). `enrichEmails` is billed only when an email is found.
- Not supported: vacation rentals, tours, flights, hotel price offers, `sortBy`/traveler-type filters, and `tripadvisor.co.*` mirrors.

### ⚠️ Disclaimer

This Actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Tripadvisor LLC or any of its subsidiaries. All trademarks mentioned are the property of their respective owners.

The scraper accesses only publicly available TripAdvisor pages — no authenticated endpoints, paid features, or content behind the tripadvisor.com login wall. Users are responsible for ensuring their use complies with TripAdvisor's Terms of Service, applicable data-protection law (GDPR, CCPA, etc.), and any contractual obligations of their own organization.

### SEO Keywords

tripadvisor reviews scraper, tripadvisor scraper, scrape tripadvisor, tripadvisor api, tripadvisor.com scraper, Apify tripadvisor, hotel reviews scraper, restaurant reviews scraper, attraction reviews scraper, tripadvisor hotel data, tripadvisor restaurant data, reviewer profile scraper, review sentiment data, reputation monitoring data, hospitality market research, travel reviews export, tripadvisor json export, tripadvisor csv export, competitive review intelligence, place metadata scraper

# Actor input Schema

## `searchQuery` (type: `string`):

Optional free-text location query, e.g. `"Chicago"`, `"Brooklyn"`, `"London"`. Resolved via TripAdvisor's autocomplete GraphQL into a geoId, then expanded into venues based on the `Include hotels` / `Include restaurants` / `Include things to do` toggles below. Use this **instead of or alongside** `startUrls`. Leave empty to skip text-search and use only the URLs in `startUrls`.

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

Add TripAdvisor URLs to scrape reviews. Supported:

- **Place pages:** `Hotel_Review`, `Restaurant_Review`, `Attraction_Review` URLs (`…/<Type>_Review-g{geoId}-d{locationId}-Reviews-{slug}.html`).
- **GEO restaurant listing:** `Restaurants-g{geo}-…-{City}_{State}.html` — HTML listing + `-oa30-` pagination, expanded to `Restaurant_Review` venues.
- **GEO hotel listing:** `Hotels-g{geo}-…-Hotels.html` — HTML listing + `-oa30-` pagination, expanded to `Hotel_Review` venues.
- **GEO attractions listing:** `Attractions-g{geo}-Activities-…html` — HTML listing + `-oa30-` pagination, expanded to `Attraction_Review` venues. Optional `-cNN-` category subfilter is preserved.
- **Restaurant search:** `FindRestaurants?geo=…&establishmentTypes=…` — listing expansion calls **`api.tripadvisor.com` `AppListRestaurants`** (same as the TA iPhone app), then falls back to www `/data/graphql/ids`, then HTML link harvest if needed. **`maxItems` still caps reviews per scraped `Restaurant_Review` URL** (each listing produces many URLs).

Examples:

- Hotel — `https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html`
- Restaurant — `https://www.tripadvisor.com/Restaurant_Review-g60763-d25324283-Reviews-Allora_Fifth_Ave-New_York_City_New_York.html`
- Chicago restaurants hub — `https://www.tripadvisor.com/Restaurants-g35805-Chicago_Illinois.html`
- New York hotels hub — `https://www.tripadvisor.com/Hotels-g60763-New_York_City_New_York-Hotels.html`
- Find Restaurants — `https://www.tripadvisor.com/FindRestaurants?geo=188673&establishmentTypes=10591&mealTypes=10597&broadened=false`

Mix detail URLs and listing URLs in one run.

## `maxItems` (type: `integer`):

Maximum number of reviews to scrape **per place / per URL**. Applied to each entry in `startUrls` independently. Use 0 for unlimited (the actor will paginate every review the API exposes for that place).

## `scrapeReviewerInfo` (type: `boolean`):

When enabled, populate the `user` object on each review with the reviewer's profile (username, display name, avatar, hometown, profile link, contributions). When disabled, `user` is set to null.

## `scrapeReviews` (type: `boolean`):

When **true** (default), fetch reviews for each `Hotel_Review` / `Restaurant_Review` URL using TripAdvisor GraphQL (paginated), up to **`maxItems` per place**. When **false**, skip review pagination and emit **one dataset row per place** with `{ "placeDetailOnly": true, "placeInfo": … }` extracted from the HTML page (fast, low cost).

## `includeReviewTags` (type: `boolean`):

When **true** (default), include `placeInfo.reviewTags` (theme phrases and counts) when TripAdvisor embeds them on the page. Set **false** to omit tags for smaller payloads.

## `includeNearby` (type: `boolean`):

When `true`, after each main place is scraped the actor expands up to **5** nearby venues from the page's nearby carousel as additional **place-detail-only** snapshot rows tagged with `isNearbyResult: true`. Reviews are NOT fetched for nearby venues. Depth is capped at 1 (no recursive expansion).

## `includeThingsToDo` (type: `boolean`):

When `searchQuery` is set, include `Attraction_Review` venues for the resolved geo. Wired through the `Attractions-g{geo}-Activities-…html` listing expander (paginated, up to ~300 attractions per query).

## `includeRestaurants` (type: `boolean`):

When `searchQuery` is set, include `Restaurant_Review` venues for the resolved geo. Wired through the existing `FindRestaurants?geo=…` expansion (paginated, up to 300 venues per query).

## `includeHotels` (type: `boolean`):

When `searchQuery` is set, include `Hotel_Review` venues for the resolved geo. Wired through the new `Hotels-g{geo}-…-Hotels.html` listing expander (paginated, up to ~300 hotels per query).

## `outputShape` (type: `string`):

Controls how reviews are returned in the dataset.

- **`flat`** (default): one dataset row **per review**, each carrying `placeInfo`. Best for tabular consumers and Apify's UI.
- **`nested`**: one dataset row **per place** of the form `{ ...placeInfo, placeDetailOnly: false, reviews: [...] }`. Best when you want a single object per hotel/restaurant with reviews nested.

No effect when **`scrapeReviews: false`** — that path always emits one `{ placeDetailOnly: true, placeInfo }` row per place.

**Note on billing:** under `PRICE_PER_DATASET_ITEM`, nested mode collapses N reviews into 1 row, so the bill drops by ~Nx. Review your actor pricing before switching the default.

## `lastReviewDate` (type: `string`):

Skip any review published before this date. Pick an absolute date (YYYY-MM-DD) or a relative duration like `22 days`, `2 weeks`, `3 months`, `1 year`.

## `reviewRatings` (type: `array`):

Filter reviews by overall rating. Leave empty to include every rating.

## `reviewsLanguages` (type: `array`):

Filter reviews by language (ISO 639-1 codes). Leave empty to include every language.

## `maxConcurrency` (type: `integer`):

Maximum number of pages that can be processed at the same time.

## `minConcurrency` (type: `integer`):

Minimum number of pages that will be processed at the same time.

## `maxRequestRetries` (type: `integer`):

Number of times each failed request is retried before giving up. Lower values surface persistent failures quickly; higher values absorb transient anti-bot blocks at the cost of long-tail latency.

## `proxy` (type: `object`):

Specifies proxy servers that will be used by the scraper in order to hide its origin.<br><br>For details, see <a href='https://apify.com/apify/web-scraper#proxy-configuration' target='_blank' rel='noopener'>Proxy configuration</a> in README.

## `enrichEmails` (type: `boolean`):

If enabled, finds a contact email for each result from its own website (or by discovering it from the name). Adds contactEmail + contactWebsite columns plus a detailed emailEnrichment object. Billed per contact email found; only charged when an email is returned, never for misses.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html"
    },
    {
      "url": "https://www.tripadvisor.com/Restaurant_Review-g60763-d25324283-Reviews-Allora_Fifth_Ave-New_York_City_New_York.html"
    },
    {
      "url": "https://www.tripadvisor.com/FindRestaurants?geo=188673&establishmentTypes=10591&mealTypes=10597&broadened=false"
    },
    {
      "url": "https://www.tripadvisor.com/Restaurants-g35805-Chicago_Illinois.html"
    }
  ],
  "maxItems": 50,
  "scrapeReviewerInfo": true,
  "scrapeReviews": true,
  "includeReviewTags": true,
  "includeNearby": false,
  "includeThingsToDo": true,
  "includeRestaurants": true,
  "includeHotels": true,
  "outputShape": "flat",
  "reviewRatings": [
    "ALL_REVIEW_RATINGS"
  ],
  "reviewsLanguages": [
    "ALL_REVIEW_LANGUAGES"
  ],
  "maxConcurrency": 100,
  "minConcurrency": 1,
  "maxRequestRetries": 15,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "enrichEmails": false
}
```

# Actor output Schema

## `results` (type: `string`):

Direct link to the run's default dataset items.

## `failures` (type: `string`):

Locations that produced 0 reviews or failed mid-pagination. Empty if the run was perfect.

# 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": [
        {
            "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html"
        },
        {
            "url": "https://www.tripadvisor.com/Restaurant_Review-g60763-d25324283-Reviews-Allora_Fifth_Ave-New_York_City_New_York.html"
        },
        {
            "url": "https://www.tripadvisor.com/FindRestaurants?geo=188673&establishmentTypes=10591&mealTypes=10597&broadened=false"
        },
        {
            "url": "https://www.tripadvisor.com/Restaurants-g35805-Chicago_Illinois.html"
        }
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/tripadvisor-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": [
        { "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html" },
        { "url": "https://www.tripadvisor.com/Restaurant_Review-g60763-d25324283-Reviews-Allora_Fifth_Ave-New_York_City_New_York.html" },
        { "url": "https://www.tripadvisor.com/FindRestaurants?geo=188673&establishmentTypes=10591&mealTypes=10597&broadened=false" },
        { "url": "https://www.tripadvisor.com/Restaurants-g35805-Chicago_Illinois.html" },
    ],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

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

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).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": [
    {
      "url": "https://www.tripadvisor.com/Hotel_Review-g60763-d208453-Reviews-Hilton_New_York_Times_Square-New_York_City_New_York.html"
    },
    {
      "url": "https://www.tripadvisor.com/Restaurant_Review-g60763-d25324283-Reviews-Allora_Fifth_Ave-New_York_City_New_York.html"
    },
    {
      "url": "https://www.tripadvisor.com/FindRestaurants?geo=188673&establishmentTypes=10591&mealTypes=10597&broadened=false"
    },
    {
      "url": "https://www.tripadvisor.com/Restaurants-g35805-Chicago_Illinois.html"
    }
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call memo23/tripadvisor-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/tripadvisor-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/MdCnYilhVu0miZEnq/builds/J5EPoC5Fm8f85iLHy/openapi.json
