# TripAdvisor Hotels & Reviews Scraper | $3.50 / 1k (`pro100chok/tripadvisor-all-in-one`) Actor

Scrape TripAdvisor hotels, restaurants, things to do, and reviews in one Actor. Get prices, star ratings, GPS,
amenities, hours, photos, awards, and full review threads. Input by URL, search keyword, or city name. $3.50 / 1k
places, $0.50 / 1k reviews.

- **URL**: https://apify.com/pro100chok/tripadvisor-all-in-one.md
- **Developed by:** [Raven](https://apify.com/pro100chok) (community)
- **Categories:** Travel, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 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/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 Scraper — Hotels, Restaurants, Attractions and Reviews in One Actor

Scrape TripAdvisor hotels, restaurants, things to do, and customer reviews — all from a single Actor. Three input modes: paste any TripAdvisor URL, type a free-text keyword, or pass a city name. Get pricing, star ratings, GPS coordinates, amenities, opening hours, photos, awards, and full review threads.

### Pricing

Pay per result. No subscription, no minimum.

| Event | Price | Per 1,000 |
|-------|-------|-----------|
| **Result** (one place — hotel, restaurant or attraction) | $0.0035 | **$3.50** |
| **Review** (one TripAdvisor review, embedded in its parent place) | $0.0005 | **$0.50** |

You only pay for what lands in the dataset. Listing pagination, typeahead, retries, and DataDome rotations are absorbed by the Actor — never charged to you. Set `maxItems` and `maxReviewsPerPoi` to cap the run, plus `Maximum cost per run` (default $20) as a hard budget.

### Key Features

- **Three input modes** — paste TripAdvisor URLs, type free-text search terms, or list cities by name (or numeric geo ID). Each mode has its own dedicated input field.
- **All four place types** — hotels, restaurants, things to do, and a single review parser that handles all of them
- **Reviews embedded inline** — each place record carries a `reviews: [...]` array, so one row in the dataset = one place with everything about it
- **City listing crawler** — paginates `Hotels-g{id}-…html`, `Restaurants-g{id}-…html`, `Attractions-g{id}-Activities-…html` to discover all POIs in a destination
- **Typeahead resolver** — turn `"Paris"`, `"Dubai"`, `"New York City"` into the right TripAdvisor geo ID at runtime via TripAdvisor's official autocomplete GraphQL
- **DataDome bypass** — TLS fingerprint impersonation (`tls_client` Chrome 133, no headers overridden) auto-rotates the proxy session on every 403 / captcha hit, up to 5 retries per request, each with a fresh IP
- **Parallel scraping** — up to 10 concurrent worker pool (configurable), each with its own IP and cookie jar; a dedicated thread pool keeps `tls_client`'s sync API from queueing on Python's tiny default executor
- **Two-layout review parser** — TripAdvisor uses different DOM for hotels vs attractions; the Actor detects both (`data-test-target="HR_CC_CARD"` and legacy `data-automation="reviewCard"`) automatically
- **Hard budget cap** — `Maximum cost per run` stops the run cleanly the moment your $X budget is hit, exit code 0, no partial double-charge
- **Apify Residential US proxy** — hardcoded; users never see proxy settings or IP rotation logic

### What Data You Get

Every dataset row is a single place record (hotel, restaurant or attraction). When `Include reviews` is on, reviews come embedded inside that record as an array.

#### Hotel record

| Field | Description |
|-------|-------------|
| `__type` | `"hotel"` |
| `locationId` | TripAdvisor numeric POI id |
| `parentGeoId` | Numeric city id |
| `url` | Canonical TripAdvisor URL |
| `name` | Hotel name |
| `description` | "About this hotel" text |
| `starRating` | Official hotel class (1.0–5.0 stars) |
| `priceRange` | TripAdvisor price band (`$$`) |
| `priceFrom` | Lowest deal price across booking partners |
| `finalPrice` | Headline price shown in the booking module |
| `dealsCount` | How many booking partners have a deal |
| `awards` | Travelers' Choice / Best of the Best / etc. |
| `phone`, `officialWebsite` | Contact details |
| `rating`, `reviewCount`, `ranking` | Aggregate rating, total reviews, "#3 of 1,882 hotels" |
| `address`, `city`, `postalCode`, `country`, `region` | Full address |
| `latitude`, `longitude` | GPS coordinates |
| `amenities` | Flat list of all amenities |
| `amenityGroups` | Same amenities split by `property` / `room_amenities` / `room_types` |
| `languagesSpoken` | When TripAdvisor lists them |
| `images` | Up to 30 photo URLs |
| `breadcrumbs` | Full geo hierarchy (Europe > France > Ile-de-France > Paris > …) |

#### Restaurant record

| Field | Description |
|-------|-------------|
| `__type` | `"restaurant"` |
| `locationId`, `parentGeoId`, `url`, `name` | Identity |
| `description` | About this restaurant |
| `phone`, `image` | Contact + cover photo |
| `rating`, `reviewCount`, `ranking` | Aggregate rating, total reviews, "#24 of 14,022 Restaurants" |
| `priceLevel` | `$`, `$$`, `$$ - $$$`, etc. |
| `cuisines` | `["Japanese", "Sushi", "Asian"]` |
| `mealTypes` | `["Lunch", "Dinner", "Brunch"]` |
| `specialDiets` | `["Vegetarian friendly", "Gluten Free", "Vegan options"]` |
| `features` | `["Reservations", "Outdoor Seating", "Takeout", "Delivery"]` |
| `awards` | Travelers' Choice / Michelin / etc. |
| `openingHours` | Hours per day of week |
| `latitude`, `longitude` | GPS coordinates |
| `city`, `country`, `region` | Geo |
| `images` | Up to 30 photo URLs |
| `breadcrumbs` | Full geo hierarchy |

#### Attraction record

| Field | Description |
|-------|-------------|
| `__type` | `"attraction"` |
| `locationId`, `parentGeoId`, `url`, `name` | Identity |
| `description` | About this attraction |
| `phone`, `officialWebsite`, `image` | Contact + cover photo |
| `rating`, `reviewCount`, `ranking`, `bestRating` | Ratings + "#11 of 4,244 things to do" |
| `openingHours` | e.g. `"Mo-Su 09:30-23:00"` |
| `duration` | Suggested visit length, e.g. `"1-2 hours"` |
| `ticketPriceFrom` | Cheapest ticket / tour price (`"$54"`) |
| `categories` | List of attraction categories (Architectural Buildings, Monuments, etc.) |
| `awards` | Travelers' Choice / Best of the Best / etc. |
| `address`, `city`, `postalCode`, `country` | Full address |
| `latitude`, `longitude` | GPS coordinates |
| `images` | Up to 30 photo URLs |
| `breadcrumbs` | Full geo hierarchy |

#### Embedded review (when `Include reviews = true`)

Reviews live inside their parent place record under `reviews: [...]`. Each review carries:

| Field | Description |
|-------|-------------|
| `reviewId` | TripAdvisor review id |
| `url` | Permalink to the single-review page |
| `title` | Review title |
| `rating` | 1.0–5.0 (parsed from "X of 5 bubbles") |
| `text` | Full review body |
| `language` | BCP-47 language code (when tagged) |
| `travelDate` | When the user stayed/visited (e.g. `"April 2026"`) |
| `tripType` | `"Traveled with family"` / `"Couples"` / `"Solo"` / etc. |
| `writtenDate` | When the review was posted |
| `helpfulVotes` | Helpful-vote count |
| `reviewer` | `{name, profileUrl, contributions, location}` |
| `ownerResponse` | Owner reply if present |

Plus `reviewsScraped: N` on the parent place — handy when you set `maxReviewsPerPoi` and want to know how many actually came back.

### Use Cases

- **Hotel competitive analysis** — pull every hotel in a city with prices, ratings, amenities, ranking, and photos for benchmarking against your own property
- **Restaurant market research** — scrape restaurants by cuisine and price band; compare ratings, awards, and customer sentiment from review text
- **Tourism analytics** — top attractions per city with visit duration, ticket prices, and rating breakdowns for tour operators and travel agencies
- **Review sentiment mining** — bulk-extract review text, ratings, dates, and trip types for sentiment analysis, brand monitoring, and reputation management
- **Pricing intelligence** — track `priceFrom` and `dealsCount` across hotels to spot pricing trends and OTA partner availability
- **OTA / aggregator data feed** — power your own travel site or app with TripAdvisor's place data: GPS, amenities, hours, photos
- **Hospitality SEO research** — what cuisines / categories rank top in a city, which Travelers' Choice winners exist, what features customers ask about
- **Lead generation for travel suppliers** — extract hotel and restaurant contact info (phone, website, email when listed) for outreach
- **Travel content creation** — auto-generate destination guides with curated lists of top-rated places, photos, and review quotes

### How It Works

1. **Pick an Input Mode** at the top of the form — `Start URLs`, `Search terms`, or `Cities`
2. **Fill the matching field** — paste TripAdvisor URLs, type keywords like `"Eiffel Tower"`, or list cities like `"Paris"`, `"Dubai"`, `"187147"`
3. **Pick a Category** — `All` / `Hotels` / `Restaurants` / `Attractions` (ignored when you pass a direct detail URL)
4. **Toggle `Include reviews`** — embeds reviews inside each place record (charged separately)
5. **Set caps** — `Max items total` (hard cap on dataset rows), `Max reviews per POI`, `Max POIs per listing`, `Maximum cost per run`
6. **Run** — actor pulls TripAdvisor pages through Apify Residential US proxy, parses JSON-LD + DOM, pushes flat rows to the dataset
7. **Download** — JSON, CSV, or Excel from the Apify dataset; the table view is preconfigured to show name, rating, price, ranking, city

### Input Parameters

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `mode` | string | `locations` | `startUrls`, `searchTerms`, or `locations` |
| `startUrls` | URL list | — | TripAdvisor pages: `Hotel_Review-`, `Restaurant_Review-`, `Attraction_Review-`, `Hotels-`, `Restaurants-`, `Attractions-` |
| `searchTerms` | string list | — | Free-text keywords (resolved via TripAdvisor typeahead) |
| `locations` | string list | — | City names (`"Paris"`, `"New York City"`) or numeric geo IDs (`"187147"`) |
| `category` | enum | `all` | `all`, `hotels`, `restaurants`, `attractions` |
| `includeReviews` | boolean | `false` (UI prefill: `true`) | Fetch reviews and embed them inside each place record |
| `maxReviewsPerPoi` | integer | `10` | Cap on reviews per place. Each review = $0.50 / 1,000 |
| `maxPois` | integer | `50` | Cap on POIs per listing in `searchTerms` / `locations` modes |
| `maxItems` | integer | `10` | Hard cap on total dataset rows. `0` = unlimited |
| `locale` | string | `en-US` | BCP-47 — used for typeahead and `Accept-Language` |
| `maxRetries` | integer | `5` | Retries per request before giving up; each retry uses a new IP |
| `maxConcurrency` | integer | `10` | Parallel workers (each with its own IP) |

#### Example: scrape Paris and Dubai with 10 hotels each + 5 reviews per hotel

```json
{
  "mode": "locations",
  "locations": ["Paris", "Dubai"],
  "category": "hotels",
  "includeReviews": true,
  "maxReviewsPerPoi": 5,
  "maxPois": 10,
  "maxItems": 0
}
````

#### Example: pull a specific hotel with 50 reviews

```json
{
  "mode": "startUrls",
  "startUrls": [
    { "url": "https://www.tripadvisor.com/Hotel_Review-g187147-d229968-Reviews-Hotel_Astra_Opera_Astotel-Paris_Ile_de_France.html" }
  ],
  "includeReviews": true,
  "maxReviewsPerPoi": 50
}
```

#### Example: keyword search across types

```json
{
  "mode": "searchTerms",
  "searchTerms": ["Eiffel Tower", "Le Bernardin"],
  "category": "all",
  "includeReviews": false
}
```

### Output Example

#### Hotel with embedded reviews

```json
{
  "__type": "hotel",
  "locationId": 250927,
  "parentGeoId": 187147,
  "url": "https://www.tripadvisor.com/Hotel_Review-g187147-d250927-Reviews-Hotel_Europe_Saint_Severin-Paris_Ile_de_France.html",
  "name": "Hotel Europe Saint Severin",
  "description": "Friendly and comfortable property located in the heart of the Latin quarter…",
  "starRating": 3.0,
  "priceRange": "$$ (Based on Average Nightly Rates for a Standard Room from our Partners)",
  "priceFrom": "$160",
  "finalPrice": "$221",
  "dealsCount": 11,
  "awards": ["Travelers' Choice"],
  "rating": 4.5,
  "reviewCount": 3256,
  "ranking": "#383 of 1,882 hotels",
  "address": "38-40 Rue Saint Severin",
  "city": "Paris",
  "postalCode": "75005",
  "country": "FR",
  "latitude": 48.852753,
  "longitude": 2.344314,
  "amenityGroups": {
    "property": ["Free WiFi", "24-hour front desk", "Concierge", "..."],
    "room_amenities": ["Air conditioning", "Bathrobes", "..."],
    "room_types": ["Non-smoking rooms", "Family rooms"]
  },
  "images": ["https://dynamic-media-cdn.tripadvisor.com/..."],
  "reviews": [
    {
      "reviewId": 1057616466,
      "title": "Perfect hotel for a family",
      "rating": 5.0,
      "text": "I can only recommend this hotel! We stayed here as a family of three…",
      "travelDate": "April 2026",
      "tripType": "Traveled with family",
      "writtenDate": "Apr 26",
      "helpfulVotes": 1,
      "reviewer": {
        "name": "Erdal A",
        "profileUrl": "https://www.tripadvisor.com/Profile/erdala957",
        "contributions": null,
        "location": null
      }
    }
  ],
  "reviewsScraped": 5
}
```

#### Restaurant

```json
{
  "__type": "restaurant",
  "locationId": 425227,
  "parentGeoId": 60827,
  "name": "Geido Restaurant",
  "description": null,
  "rating": 4.4,
  "reviewCount": 287,
  "ranking": "#42 of 5,341 Restaurants in Brooklyn",
  "priceLevel": "$$ - $$$",
  "cuisines": ["Japanese", "Sushi", "Asian"],
  "specialDiets": ["Vegetarian friendly"],
  "features": ["Delivery"],
  "awards": ["Travelers' Choice"],
  "openingHours": {
    "Sunday": ["12:00-22:00"],
    "Monday": ["12:00-22:00"]
  },
  "latitude": 40.677,
  "longitude": -73.969
}
```

#### Attraction

```json
{
  "__type": "attraction",
  "locationId": 188151,
  "parentGeoId": 187147,
  "name": "Eiffel Tower",
  "rating": 4.6,
  "reviewCount": 143855,
  "ranking": "#11 of 4,244 things to do",
  "openingHours": "Mo-Su 09:30-23:00",
  "duration": "1-2 hours",
  "ticketPriceFrom": "$54",
  "categories": ["Architectural Buildings in Paris", "Monuments & Statues in Paris", "..."],
  "awards": ["Travelers' Choice", "Best of the Best"],
  "officialWebsite": "https://www.toureiffel.paris/",
  "phone": "+33 892 70 12 39",
  "latitude": 48.858353,
  "longitude": 2.294464
}
```

### Proxy Requirements

**Apify Residential US proxy is hardcoded** — you never configure it. TripAdvisor uses DataDome bot management; only residential IPs from the right pool consistently pass. No SOCKS5, no datacenter — Apify Residential is required.

The Actor rotates the proxy session (= new IP) on every 403 / captcha / connection error, up to 5 times per request. With 10 parallel workers, each runs on its own IP — even bursty fan-outs to 50 hotels at once stay under DataDome's per-IP rate.

### Limitations

- **Reviews behind DataDome lite-mode** — on some Apify residential IPs TripAdvisor returns a stripped detail page (JSON-LD intact, but review markup omitted). The Actor falls back to the dedicated `-or10-` review-pagination URL automatically. If both fail, the review array is empty for that place — the place itself is still pushed
- **Listing depth** — city listings paginate at 30 POIs per page; default cap is 50 POIs per listing (set `maxPois` higher to scrape more, up to 5,000)
- **Reviews per POI cap** — server-side TripAdvisor allows hundreds of pages; default cap is 10 reviews to keep runs cheap, set `maxReviewsPerPoi` higher (up to 50,000)
- **Persisted GraphQL queries rotate** — TripAdvisor's typeahead uses a persisted query id (`58aa2507ecd677af` at the time of writing). When TripAdvisor deploys, this id changes and `searchTerms` / `locations` modes (the ones that go through typeahead) start failing. `Start URLs` mode keeps working unaffected. Re-deploy of the Actor will pick up the new id
- **Two-layout review markup** — TripAdvisor uses different DOM for hotels vs attractions reviews. The Actor detects and parses both. If TripAdvisor adds a third layout, expect a few hours of zero-review runs before a hotfix
- **Geo coverage** — TripAdvisor's data is global; this Actor specifically scrapes the `tripadvisor.com` domain (English / US locale by default). Non-English locales work via the `locale` parameter

### FAQ

**What kinds of TripAdvisor data does this Actor scrape?**
Hotels, restaurants, things to do (attractions), and customer reviews. Reviews come embedded inside each place record.

**How are reviews formatted?**
Reviews live inside their parent place under `reviews: [...]`. Each review has `reviewId`, `title`, `rating`, `text`, `travelDate`, `tripType`, `helpfulVotes`, `reviewer`, and more. Set `Include reviews = true` to fetch them.

**How do I scrape every hotel in a city?**
Use the `Cities` mode, type `"Paris"` (or paste the geo ID `"187147"`), set `category = hotels`, `maxPois = 5000`, and `maxItems = 0` for unlimited.

**Can I scrape a specific hotel page?**
Yes — switch to `Start URLs` and paste the `Hotel_Review-` URL. Same for restaurants (`Restaurant_Review-`) and attractions (`Attraction_Review-`).

**How do I cap the cost per run?**
The default `Maximum cost per run` is **$20**. Lower it in the Run options panel, or set `maxItems` to hard-cap dataset rows.

**Why are some review fields `null`?**
TripAdvisor doesn't always show every field per review (e.g. reviewer location, contributions count, owner response). When the page doesn't surface it, the field is `null`.

**Why does my run return zero reviews on some hotels?**
DataDome occasionally serves a stripped HTML to Apify residential IPs that omits review-card markup. The Actor falls back to a fresh fetch of the `-or10-` review-pagination URL — usually that returns full content. If both fail, the place is still pushed; only `reviews` ends up empty. Retrying the run typically gets the reviews on a fresh proxy session.

**How fast is it?**
With `maxConcurrency = 10`, four hotel detail fetches complete in ~1.7 seconds locally. On Apify Residential, expect ~3–8 seconds per place depending on review depth.

**Can I export to CSV / Excel?**
Yes. Apify dataset supports JSON, CSV, Excel, XML, RSS, HTML. Embedded `reviews: [...]` arrays flatten in CSV via dot-notation; if you need one-row-per-review for spreadsheet analysis, run with `includeReviews = false` then a second run on the same `startUrls` with `includeReviews = true` and post-process.

**Does the price include the proxy cost?**
Yes. The $3.50 / 1,000 results and $0.50 / 1,000 reviews are all-in. You don't pay for proxy bandwidth, retries, or DataDome rotations.

### Having issues? Help me fix them faster

If you experience any problems, please share your run data with me so I can debug and improve the Actor:

1. Go to [Apify Security Settings](https://console.apify.com/settings/security)
2. Find **"Share run data with developers"**
3. In the **"Manage list of Actors"** section, check this Actor (or **All Actors**)
4. Save

This data is used **only for debugging** and helps me resolve issues much faster. Thank you!

### Support

Questions, bug reports, or feature requests: **afrcanec@gmail.com**

### 🏷️ Tags

TripAdvisor Scraper, TripAdvisor API, TripAdvisor Hotels Scraper, TripAdvisor Restaurants Scraper, TripAdvisor Attractions Scraper, TripAdvisor Reviews Scraper, TripAdvisor Data Extractor, Hotel Reviews Scraper, Restaurant Reviews Scraper, Hotel Price Scraper, Hotels Data Mining, Travel Data Scraper, Hospitality Data, Tourism Scraper, City Listings Scraper, Hotel Ratings Extractor, Restaurant Ratings, Things To Do Scraper, Tourist Attractions API, Hotel Amenities Scraper, Hotel Booking Data, Travel Reviews Mining, Sentiment Analysis Travel, Hotel Competitor Analysis, Restaurant Competitor Analysis, OTA Data Scraping, Hotel Star Rating Scraper, Travelers Choice Awards Tracker, Hotel Photo Scraper, How to Scrape TripAdvisor, Extract TripAdvisor Reviews, Travel Market Research, Hospitality Market Research, Tourism Analytics, Hotel Aggregator, Review Aggregator, Restaurant Discovery, Tourist Reviews Database, Travel Industry Data, Vacation Rentals Scraper, Hotel Pricing API, Customer Review Mining

# Actor input Schema

## `mode` (type: `string`):

How to discover what to scrape. 'startUrls' takes any TripAdvisor page URL. 'searchTerms' walks every typeahead match for the keyword (city + named POIs). 'locations' walks city listings only — accepts city names or numeric TripAdvisor geo IDs.

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

TripAdvisor URLs to scrape. Supported: /Hotel\_Review-, /Restaurant\_Review-, /Attraction\_Review-, /Hotels-, /Restaurants-, /Attractions-. Used only when mode = 'startUrls'.

## `searchTerms` (type: `array`):

Free-text keywords (e.g. 'Paris', 'Hotels in Rome'). Resolved via TripAdvisor typeahead. Used only when mode = 'searchTerms'.

## `locations` (type: `array`):

City names or numeric TripAdvisor geo IDs. Names are resolved via TripAdvisor typeahead at runtime (the first geographic match wins). Used only when mode = 'locations'. Examples: Paris, Dubai, New York City, 187791.

## `category` (type: `string`):

What to fetch when expanding a city or keyword. Ignored for direct detail-page start URLs.

## `includeReviews` (type: `boolean`):

If true, fetch reviews for every POI scraped (charged separately as the 'reviews' event at $0.50 / 1,000).

## `maxReviewsPerPoi` (type: `integer`):

Cap on reviews per place. Active only when 'Include reviews' is on. Each review is charged at $0.50 / 1,000.

## `maxPois` (type: `integer`):

Cap on POIs pulled from each city listing in 'searchTerms' / 'locations' modes. Each place record is charged at $3.50 / 1,000.

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

Hard cap on total dataset rows (each row = one place record with reviews embedded). 0 = unlimited.

## `locale` (type: `string`):

BCP-47 language tag used for typeahead and the Accept-Language header (e.g. en-US, fr-FR, de-DE).

## `maxRetries` (type: `integer`):

How many times to retry a failed request (per page) before giving up. Each retry rotates the proxy session to a new IP.

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

How many TripAdvisor pages to fetch in parallel. Each worker uses its own IP via session rotation.

## Actor input object example

```json
{
  "mode": "locations",
  "startUrls": [
    {
      "url": "https://www.tripadvisor.com/Hotel_Review-g187147-d229968-Reviews-Hotel_Astra_Opera_Astotel-Paris_Ile_de_France.html"
    },
    {
      "url": "https://www.tripadvisor.com/Attraction_Review-g187147-d188151-Reviews-Eiffel_Tower-Paris_Ile_de_France.html"
    }
  ],
  "searchTerms": [
    "Paris",
    "Dubai"
  ],
  "locations": [
    "Paris",
    "Dubai"
  ],
  "category": "all",
  "includeReviews": true,
  "maxReviewsPerPoi": 10,
  "maxPois": 50,
  "maxItems": 10,
  "locale": "en-US",
  "maxRetries": 5,
  "maxConcurrency": 10
}
```

# Actor output Schema

## `dataset` (type: `string`):

All scraped places with optional embedded reviews. Use the per-type views (Hotels / Restaurants / Attractions) to slice by category.

# 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 = {
    "mode": "locations",
    "startUrls": [
        {
            "url": "https://www.tripadvisor.com/Hotel_Review-g187147-d229968-Reviews-Hotel_Astra_Opera_Astotel-Paris_Ile_de_France.html"
        },
        {
            "url": "https://www.tripadvisor.com/Attraction_Review-g187147-d188151-Reviews-Eiffel_Tower-Paris_Ile_de_France.html"
        }
    ],
    "searchTerms": [
        "Paris",
        "Dubai"
    ],
    "locations": [
        "Paris",
        "Dubai"
    ],
    "category": "all",
    "includeReviews": true,
    "maxReviewsPerPoi": 10,
    "maxPois": 50,
    "maxItems": 10,
    "locale": "en-US",
    "maxRetries": 5,
    "maxConcurrency": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("pro100chok/tripadvisor-all-in-one").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 = {
    "mode": "locations",
    "startUrls": [
        { "url": "https://www.tripadvisor.com/Hotel_Review-g187147-d229968-Reviews-Hotel_Astra_Opera_Astotel-Paris_Ile_de_France.html" },
        { "url": "https://www.tripadvisor.com/Attraction_Review-g187147-d188151-Reviews-Eiffel_Tower-Paris_Ile_de_France.html" },
    ],
    "searchTerms": [
        "Paris",
        "Dubai",
    ],
    "locations": [
        "Paris",
        "Dubai",
    ],
    "category": "all",
    "includeReviews": True,
    "maxReviewsPerPoi": 10,
    "maxPois": 50,
    "maxItems": 10,
    "locale": "en-US",
    "maxRetries": 5,
    "maxConcurrency": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("pro100chok/tripadvisor-all-in-one").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 '{
  "mode": "locations",
  "startUrls": [
    {
      "url": "https://www.tripadvisor.com/Hotel_Review-g187147-d229968-Reviews-Hotel_Astra_Opera_Astotel-Paris_Ile_de_France.html"
    },
    {
      "url": "https://www.tripadvisor.com/Attraction_Review-g187147-d188151-Reviews-Eiffel_Tower-Paris_Ile_de_France.html"
    }
  ],
  "searchTerms": [
    "Paris",
    "Dubai"
  ],
  "locations": [
    "Paris",
    "Dubai"
  ],
  "category": "all",
  "includeReviews": true,
  "maxReviewsPerPoi": 10,
  "maxPois": 50,
  "maxItems": 10,
  "locale": "en-US",
  "maxRetries": 5,
  "maxConcurrency": 10
}' |
apify call pro100chok/tripadvisor-all-in-one --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "TripAdvisor Hotels & Reviews Scraper | $3.50 / 1k",
        "description": "Scrape TripAdvisor hotels, restaurants, things to do, and reviews in one Actor. Get prices, star ratings, GPS,\n  amenities, hours, photos, awards, and full review threads. Input by URL, search keyword, or city name. $3.50 / 1k\n  places, $0.50 / 1k reviews.",
        "version": "1.0",
        "x-build-id": "2dsxaWM9aGT8bzlD1"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/pro100chok~tripadvisor-all-in-one/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-pro100chok-tripadvisor-all-in-one",
                "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/pro100chok~tripadvisor-all-in-one/runs": {
            "post": {
                "operationId": "runs-sync-pro100chok-tripadvisor-all-in-one",
                "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/pro100chok~tripadvisor-all-in-one/run-sync": {
            "post": {
                "operationId": "run-sync-pro100chok-tripadvisor-all-in-one",
                "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": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "Input mode",
                        "enum": [
                            "startUrls",
                            "searchTerms",
                            "locations"
                        ],
                        "type": "string",
                        "description": "How to discover what to scrape. 'startUrls' takes any TripAdvisor page URL. 'searchTerms' walks every typeahead match for the keyword (city + named POIs). 'locations' walks city listings only — accepts city names or numeric TripAdvisor geo IDs.",
                        "default": "locations"
                    },
                    "startUrls": {
                        "title": "Start URLs",
                        "type": "array",
                        "description": "TripAdvisor URLs to scrape. Supported: /Hotel_Review-, /Restaurant_Review-, /Attraction_Review-, /Hotels-, /Restaurants-, /Attractions-. Used only when mode = 'startUrls'.",
                        "items": {
                            "type": "object",
                            "required": [
                                "url"
                            ],
                            "properties": {
                                "url": {
                                    "type": "string",
                                    "title": "URL of a web page",
                                    "format": "uri"
                                }
                            }
                        }
                    },
                    "searchTerms": {
                        "title": "Search terms",
                        "type": "array",
                        "description": "Free-text keywords (e.g. 'Paris', 'Hotels in Rome'). Resolved via TripAdvisor typeahead. Used only when mode = 'searchTerms'.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "locations": {
                        "title": "Cities",
                        "type": "array",
                        "description": "City names or numeric TripAdvisor geo IDs. Names are resolved via TripAdvisor typeahead at runtime (the first geographic match wins). Used only when mode = 'locations'. Examples: Paris, Dubai, New York City, 187791.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "category": {
                        "title": "Category",
                        "enum": [
                            "all",
                            "hotels",
                            "restaurants",
                            "attractions"
                        ],
                        "type": "string",
                        "description": "What to fetch when expanding a city or keyword. Ignored for direct detail-page start URLs.",
                        "default": "all"
                    },
                    "includeReviews": {
                        "title": "Include reviews",
                        "type": "boolean",
                        "description": "If true, fetch reviews for every POI scraped (charged separately as the 'reviews' event at $0.50 / 1,000).",
                        "default": false
                    },
                    "maxReviewsPerPoi": {
                        "title": "Max reviews per POI",
                        "minimum": 0,
                        "maximum": 50000,
                        "type": "integer",
                        "description": "Cap on reviews per place. Active only when 'Include reviews' is on. Each review is charged at $0.50 / 1,000.",
                        "default": 10
                    },
                    "maxPois": {
                        "title": "Max POIs per listing",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Cap on POIs pulled from each city listing in 'searchTerms' / 'locations' modes. Each place record is charged at $3.50 / 1,000.",
                        "default": 50
                    },
                    "maxItems": {
                        "title": "Max total items",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Hard cap on total dataset rows (each row = one place record with reviews embedded). 0 = unlimited.",
                        "default": 10
                    },
                    "locale": {
                        "title": "Locale",
                        "type": "string",
                        "description": "BCP-47 language tag used for typeahead and the Accept-Language header (e.g. en-US, fr-FR, de-DE).",
                        "default": "en-US"
                    },
                    "maxRetries": {
                        "title": "Max retries",
                        "minimum": 1,
                        "maximum": 15,
                        "type": "integer",
                        "description": "How many times to retry a failed request (per page) before giving up. Each retry rotates the proxy session to a new IP.",
                        "default": 5
                    },
                    "maxConcurrency": {
                        "title": "Max concurrency",
                        "minimum": 1,
                        "maximum": 30,
                        "type": "integer",
                        "description": "How many TripAdvisor pages to fetch in parallel. Each worker uses its own IP via session rotation.",
                        "default": 10
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
