# TripAdvisor Scraper (`s-r/tripadvisor-scraper`) Actor

- **URL**: https://apify.com/s-r/tripadvisor-scraper.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:**
- **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/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

## TripAdvisor Scraper

Give it a TripAdvisor restaurants or hotels list URL and get the places back as rows: rating, review count, price band, phone number, full address, coordinates and cuisine tags.

No browser, no CAPTCHA solver, no cookies.

### What you get

- **Rating and review count on every row**, which together are the only honest read of a place: a 4,8 from eleven reviews and a 4,4 from fifteen hundred are not the same signal
- **Coordinates on every row**, so results drop into a map or a spatial join with no geocoding step
- **Phone number and full postal address**, split into street, city, region and postal code
- **Cuisine tags and price band** on restaurants
- **`address_source` on every row**, saying whether TripAdvisor split the address itself or whether the city had to be taken out of the street line
- **Restaurants and hotels** from the same actor, both paginated

### How this reaches the site

TripAdvisor refuses almost every automated request, which is why most scrapers for it either need a browser or stop working.

It answers 200 with about 2 MB to **`OAI-SearchBot`**, OpenAI's search crawler.

Those last two are worth putting side by side. Both are OpenAI crawlers; one is refused and one is served. Whatever rule TripAdvisor is applying, it is not "block the AI bots", and no amount of reasoning would have found the working one. It had to be enumerated.

What that buys you: no browser, no solver, so runs are fast and cheap. What it costs you: a single-identity route can close. If it does, this actor reports `forbidden` and explains it rather than returning an empty result.

### Input

| Field | Type | Required | Default | What it does |
|---|---|---|---|---|
| `url` | string | yes | a Boston restaurants URL | A TripAdvisor restaurants or hotels list URL |
| `limit` | integer | no | `60` | Places to return, 1 to 600. A page carries 30 |
| `retries` | integer | no | `3` | Retry attempts per page |

Pick the city on TripAdvisor and paste the URL from your browser. The actor handles pagination itself.

### Output

```json
{
  "position": 1,
  "location_id": "3567563",
  "name": "Carmelina's",
  "type": "Restaurant",
  "url": "https://www.tripadvisor.com/Restaurant_Review-g60745-d3567563-Reviews-Carmelina_s-Boston_Massachusetts.html",
  "rating": 4.5,
  "reviews_count": 807,
  "price_range": "$$ - $$$",
  "cuisines": [
    "Italian",
    "Pizza"
  ],
  "telephone": "+1 617-742-0020",
  "street": "307 Hanover St",
  "city": "Boston",
  "region": "MA",
  "postal_code": "02113-1810",
  "country": "United States",
  "address_source": "derived_from_street",
  "latitude": 42.36387,
  "longitude": -71.05464
}
```

### Use cases

**Building a local-business dataset for a city.** One run gives you every restaurant or hotel TripAdvisor lists, with rating, review volume, price band, phone and coordinates. That is a usable lead list or market map without touching a business-directory API.

**Competitive positioning for a venue.** Pull the city, sort by `reviews_count`, and you can see where a place sits against the ones that actually get traffic rather than against the ones with the highest score.

**Market gap analysis.** Group restaurants by `cuisines` and `price_range` per neighbourhood using the coordinates. Where a band is thin is where a concept has room.

**Hotel rate-band research.** The hotels surface returns the same structure, so a city's supply can be split by band and rating before any rate-shopping work starts.

**Enriching an existing venue list.** Match on name and coordinates and you gain rating, review count and phone for records that had only an address.

### Limits and gotchas

- **Attractions are not supported.** That surface ships an empty schema.org list and keeps its data elsewhere, so the parser returns nothing for it. The actor refuses attraction URLs with that explanation rather than returning an empty run.
- **Restaurants and hotels format their address differently.** Hotels split it properly. Restaurants leave the city and region fields empty and put everything in the street line, so those are split out and `address_source` says `derived_from_street`. It worked on 29 of 30 in testing; the one miss had no comma to split on.
- **`price_range` is a band, not an amount.** Restaurants show `$$ - $$$`, hotels show euro symbols even from a US exit. It is TripAdvisor's own notation and is returned exactly as published rather than converted into a number it does not represent.
- **30 places per page**, paginated on an offset in the URL. The actor rewrites that itself, so paste the plain first-page URL.
- **`description` is usually empty** on list pages. TripAdvisor keeps the text on the place's own page.
- **US exit.** Other TripAdvisor domains are not covered.

### FAQ

**Does this need a browser?**
No. It is a plain HTTP request, which is why it is fast.

**Can I scrape reviews with it?**
No, this reads list pages: which places exist and how they are rated. Individual reviews live on each place's own page.

**Why are attractions refused?**
Because that page carries no structured place list. Returning zero rows without saying why would look like a broken run.

**Why is the hotel price band in euros?**
Because that is what TripAdvisor publishes there. It is a band rather than a price, so the symbol carries no information.

**How many places can I get?**
Up to 600, which is 20 pages.

### Related Actors

- [Google Maps Scraper](https://apify.com/s-r/free-google-maps-scraper) — the same kind of local record from Google
- [Trustpilot Reviews](https://apify.com/s-r/trustpilot-reviews) — review data for businesses
- [Booking Scraper](https://apify.com/s-r/free-google-maps-reviews-scraper) — accommodation listings

# Actor input Schema

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

A TripAdvisor restaurants or hotels list URL for the city you want. Pick the city on the site and paste the URL from your browser. Attractions are not supported.

## `limit` (type: `integer`):

How many places to return, 1 to 600. A page carries 30.

## `retries` (type: `integer`):

Retry attempts per page, each with a rotated TLS fingerprint.

## Actor input object example

```json
{
  "url": "https://www.tripadvisor.com/Restaurants-g60745-Boston_Massachusetts.html",
  "limit": 60,
  "retries": 3
}
```

# Actor output Schema

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

One row per restaurant or hotel.

## `summary` (type: `string`):

Places returned, rating, coordinate, phone and price-band coverage, and how many addresses had to be derived.

## `errors` (type: `string`):

Per-page failures with a code and a redacted message.

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "url": "https://www.tripadvisor.com/Restaurants-g60745-Boston_Massachusetts.html",
    "limit": 60,
    "retries": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/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 = {
    "url": "https://www.tripadvisor.com/Restaurants-g60745-Boston_Massachusetts.html",
    "limit": 60,
    "retries": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("s-r/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 '{
  "url": "https://www.tripadvisor.com/Restaurants-g60745-Boston_Massachusetts.html",
  "limit": 60,
  "retries": 3
}' |
apify call s-r/tripadvisor-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/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/OJkpNOKQrzFkqpbQj/builds/vjYN8aug4UE7YDuzD/openapi.json
