# Expedia Reviews Scraper ✈️ Hotel Ratings, Text & Sentiment (`factden/expedia-hotel-reviews-scraper`) Actor

Scrape Expedia hotel reviews at scale - guest ratings, full review text, sub-ratings, stay dates, traveler type, language & owner responses, plus LLM-ready markdown. Also accepts Hotels.com, Travelocity, Orbitz, Wotif, CheapTickets & ebookers URLs. Filter by date/rating; export JSON/CSV.

- **URL**: https://apify.com/factden/expedia-hotel-reviews-scraper.md
- **Developed by:** [Factden](https://apify.com/factden) (community)
- **Categories:** Travel, Automation, AI
- **Stats:** 8 total users, 6 monthly users, 100.0% runs succeeded, 4 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.002 / review

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Expedia Reviews Scraper

**Scrape Expedia hotel reviews at scale** - guest **ratings**, full **review text**, category **sub-ratings**,
**stay dates**, **traveler type**, **language**, and **hotel owner responses** - plus a per-review
**LLM-ready markdown** block. Paste one or more [Expedia](https://www.expedia.com) hotel URLs and export clean
**JSON, CSV, Excel, or via API**. No login, no Expedia API key.

> **One actor, all seven Expedia Group sites** - **Expedia, Hotels.com, Travelocity, Orbitz, Wotif,
> CheapTickets & ebookers.** Paste any of their hotel URLs and get the **same fields, same output schema**.
> A single actor replaces seven separate scrapers.

Runs on the Apify platform, so you get **scheduling**, a **REST API**, **webhooks & integrations**, **proxy
rotation**, and **run monitoring** out of the box - plus **incremental / since-date** runs so you only pull
what's new.

![Expedia hotel reviews - one row per review](https://raw.githubusercontent.com/factden/apify-actor-assets/main/expedia-hotel-reviews-scraper/02-reviews-overview.png)

### Supported sites - all 7 Expedia Group brands in one actor

This actor covers **every Expedia Group hotel brand** from one input. They share Expedia's backend, so the same
property resolves across brands and the **output schema is identical** no matter which brand URL you paste:

| Brand | Example hotel URL to paste |
|---|---|
| **Expedia** | `https://www.expedia.com/Las-Vegas-Hotels-Bellagio.h140596.Hotel-Information` |
| **Hotels.com** | `https://www.hotels.com/ho119566/` |
| **Travelocity** | `https://www.travelocity.com/...h140596.Hotel-Information` |
| **Orbitz** | `https://www.orbitz.com/...h140596.Hotel-Information` |
| **Wotif** | `https://www.wotif.com/...h140596.Hotel-Information` |
| **CheapTickets** | `https://www.cheaptickets.com/...h140596.Hotel-Information` |
| **ebookers** | `https://www.ebookers.com/...h140596.Hotel-Information` |

Hotels.com `/ho<id>/` links are **resolved automatically** to the global property. Mix brands freely in one run,
and use the **Review sources** filter to keep only certain brands' reviews (or leave it empty for the
cross-brand union).

### What does Expedia Reviews Scraper do?

It extracts **every public guest review** for any Expedia Group hotel you point it at, and returns a clean,
structured record per review - the overall **/10 rating**, the written **review text**, category
**sub-ratings** (cleanliness, service, room comfort, hotel condition, amenities, eco-friendliness), **stay
dates**, **traveler type**, **language**, **review photos**, and any **hotel owner response**. Alongside the
reviews it returns a **hotel aggregate**: average rating, recency-weighted rating, total review count, the full
1-5 **rating distribution**, and per-language / per-traveler-type counts.

### Why use Expedia Reviews Scraper?

- **Reputation & sentiment analysis** - track guest sentiment for your own or competitor hotels over time; every
  review carries structured sub-ratings and a sentiment-ready text block.
- **Competitor benchmarking** - pull rating distributions, category sub-scores and review volume per property to
  see exactly where a competitor wins or loses.
- **Market research** - analyze traveler types, languages, and what guests praise or complain about across a
  whole market or brand.
- **AI / RAG pipelines** - every review ships with a self-contained `markdownContent` block ready for
  vector-DB ingestion, so you can build a hotel-reviews chatbot or summarizer without any post-processing.
- **Hospitality tooling** - power owner-response tracking, guest-experience dashboards, or review-response SLAs.

### How to use Expedia Reviews Scraper

1. Open a hotel's page on Expedia (or any of the six other brands above) and copy the URL - it contains a
   `.h<number>.` segment, e.g. `.../Las-Vegas-Hotels-Bellagio.h140596.Hotel-Information`.
2. Paste one or more such URLs (any Expedia Group site) or bare property IDs into **Hotel URLs**.
3. (Optional) Set **Max reviews per hotel**, a **date range**, a **rating range**, a **sort order**, or
   **Review sources**.
4. Click **Start**, then download the results as **JSON, CSV, Excel**, or pull them from the **API**.

![Input tab - hotel URLs plus filters & limits](https://raw.githubusercontent.com/factden/apify-actor-assets/main/expedia-hotel-reviews-scraper/01-input-form.png)

### Input

| Field | Description |
|---|---|
| **Hotel URLs or property IDs** (`hotelUrls`) | Hotel-page URLs from any of the 7 brands (each with a `.h<id>.` segment), Hotels.com `/ho<id>/` URLs, **or bare property IDs** (`140596`). One per line. |
| **Max reviews per hotel** (`maxReviewsPerHotel`) | Cap per hotel (default 200). |
| **Sort reviews by** (`sortBy`) | `newest` (default), `oldest`, `highestRating`, `lowestRating`. Reviews are fetched newest-first; highest/lowest reorder the retrieved set. |
| **From / To date** (`fromDate` / `toDate`) | Keep only reviews in a `YYYY-MM-DD` range - ideal for **incremental / since-date** monitoring. |
| **Min / Max rating** (`minRating` / `maxRating`) | Keep only reviews within a 1-5 rating range (input scale is 1-5). |
| **Review sources** (`reviewSources`) | Which Expedia Group brands' reviews to return. Empty = all (cross-brand union); one = that brand only; several = that subset. |
| **Proxy** (`proxyConfiguration`) | Datacenter is enough; use residential for very large runs. |

#### Example input

```json
{
  "hotelUrls": [
    "https://www.expedia.com/Las-Vegas-Hotels-The-Venetian-Resort-Las-Vegas.h1443.Hotel-Information",
    "140596",
    "https://www.hotels.com/ho115902/",
    "https://www.travelocity.com/Las-Vegas-Hotels-Caesars-Palace.h41245.Hotel-Information",
    "https://www.orbitz.com/Las-Vegas-Hotels-The-Palazzo.h1769973.Hotel-Information"
  ],
  "maxReviewsPerHotel": 50,
  "sortBy": "newest",
  "fromDate": "2026-01-01",
  "minRating": 1,
  "maxRating": 5,
  "reviewSources": []
}
````

This example mixes an **Expedia URL**, a **bare property ID**, and **Hotels.com, Travelocity and Orbitz** URLs -
five different hotels across four brands - to show that any Expedia Group input is accepted. When you pass a bare
ID, `hotelName` comes back `null` (the name is read from a URL's descriptor slug, which an ID doesn't have).

### Output

The actor writes to **two datasets**:

- **Reviews** (the default dataset) - **one row per guest review**, with the hotel context
  (`hotelId` / `hotelName` / `hotelUrl` / `source`) merged onto every row.
- **Hotels** - **one row per hotel** with the aggregate: average rating, recency-weighted rating, total
  review count, rating distribution, category sub-ratings, coordinates and how many reviews were extracted.

The **Output** tab shows the Reviews dataset by default, plus an **AI ingest** view (the LLM-ready
`markdownContent` column) and the **Hotels** dataset. You can download any of them in **JSON, HTML, CSV, or
Excel**, or fetch them from the API (the reviews dataset also exposes `?view=aiIngest`).

**Hotels dataset** - one row per hotel with the full aggregate:

![Hotels - one row per hotel](https://raw.githubusercontent.com/factden/apify-actor-assets/main/expedia-hotel-reviews-scraper/04-hotel-overview.png)

**AI ingest view** - the self-contained, LLM-ready markdown for each review:

![AI ingest view - LLM-ready markdown](https://raw.githubusercontent.com/factden/apify-actor-assets/main/expedia-hotel-reviews-scraper/03-reviews-ai-ingest.png)

Here is a **real review row** from a run on the Bellagio (Las Vegas):

```json
{
  "hotelId": 140596,
  "hotelName": "Bellagio",
  "hotelUrl": "https://www.expedia.com/Las-Vegas-Hotels-Bellagio.h140596.Hotel-Information",
  "source": "expedia",
  "reviewId": "6a5163ef5acf8d54499c0073",
  "submittedAt": "2026-07-10T21:29:04Z",
  "overallRating": 10,
  "ratingLabel": "Exceptional",
  "reviewText": "Great as usual!",
  "subRatings": ["Cleanliness: 10", "Service: 10", "Hotel condition: 8", "Amenities: 10"],
  "verified": true,
  "reviewerName": "Alexey",
  "reviewerLocation": null,
  "checkInDate": "2026-07-05T00:00:00Z",
  "checkOutDate": "2026-07-10T00:00:00Z",
  "travelCompanions": ["Family"],
  "travelerCategories": ["Families"],
  "language": "en",
  "isMachineTranslated": false,
  "helpfulVotes": 0,
  "imagesCount": 0,
  "reviewPhotos": [],
  "ownerResponse": null,
  "roomTypeId": "314062401",
  "isAnonymous": false,
  "brandType": "Expedia",
  "markdownContent": "# Bellagio review (Expedia)\n\n**Rating:** 10/10 ★★★★★\n**Travelling as:** Family\n**Sub-ratings:** Cleanliness: 10; Service: 10; Hotel condition: 8; Amenities: 10\n\n## Review\nGreat as usual!"
}
```

...and the matching **hotel row** from the Hotels dataset:

```json
{
  "hotelId": 140596,
  "hotelName": "Bellagio",
  "hotelUrl": "https://www.expedia.com/Las-Vegas-Hotels-Bellagio.h140596.Hotel-Information",
  "source": "expedia",
  "brandName": "MGM",
  "structureType": "hotels",
  "latitude": 36.112488,
  "longitude": -115.17673,
  "avgOverallRating": 8.83,
  "halfLifeRating": 9.02,
  "totalReviewCount": 14700,
  "ratingDistribution": { "1": 523, "2": 512, "3": 1228, "4": 2529, "5": 9908 },
  "hotelSubRatings": ["Cleanliness: 9.23", "Service & staff: 8.88", "Room comfort: 9.03",
                      "Hotel condition: 9.05", "Amenities: 8.88", "Eco-friendliness: 8.54"],
  "reviewsExtracted": 50,
  "extractedAt": "2026-07-11T05:31:08Z"
}
```

Ratings are on the **/10 scale** to match Expedia's public display (the source stores /5; we present ×2).

#### Data fields

**Reviews dataset** - one row per review. Every row also carries the hotel context `hotelId`, `hotelName`,
`hotelUrl` and `source` so it stands alone.

| Field | Description |
|---|---|
| `overallRating`, `ratingLabel` | Per-review score (/10) + label ("Exceptional", "Fair"…). |
| `reviewText`, `verified` | Full written review + verified-stay flag. |
| `subRatings` | Per-review category scores (cleanliness, service, amenities…). |
| `submittedAt`, `checkInDate`, `checkOutDate` | Submission + stay dates. |
| `travelCompanions`, `travelerCategories`, `language`, `isMachineTranslated` | Trip context + language. |
| `reviewPhotos`, `helpfulVotes`, `ownerResponse` | Guest photos (URLs), helpful votes, hotel owner reply `{text,date,responder}`. |
| `brandType` | The brand this individual review was posted on (shown as the **Review source** column) - may differ from the hotel-level `source`, which reflects the input URL/ID. |
| `markdownContent` | Self-contained **LLM-ready** markdown block for RAG / vector-DB ingestion. |

**Hotels dataset** - one row per hotel.

| Field | Description |
|---|---|
| `hotelId`, `hotelName`, `hotelUrl`, `source` | Property id (from the URL), name (from the URL slug), source URL, Expedia Group brand. |
| `brandName`, `structureType`, `latitude`, `longitude` | Hotel chain, property type, coordinates. |
| `avgOverallRating`, `halfLifeRating` | Average and recency-weighted rating (**/10**). |
| `totalReviewCount`, `ratingDistribution` | Total reviews available and their source 1-5 star breakdown. |
| `hotelSubRatings`, `categoryCounts`, `languageCounts` | Aggregate category scores (/10), traveler-type counts, per-language counts. |
| `reviewsExtracted`, `extractedAt` | How many reviews this run pulled, and when. |

### Run it via the API

Run the actor programmatically and get the reviews back in one call:

```bash
curl -X POST "https://api.apify.com/v2/acts/factden~expedia-hotel-reviews-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"hotelUrls":["https://www.expedia.com/Las-Vegas-Hotels-Bellagio.h140596.Hotel-Information"],"maxReviewsPerHotel":50}'
```

The response is the default (reviews) dataset - one row per review. Append `?view=aiIngest` for the LLM-ready
markdown columns. The run's **Hotels** dataset (per-hotel aggregate) is available from the run's list of
datasets in the Console or via the API.

### Integrations & export

Download as **JSON, CSV, Excel, or XML**, or push results straight into **Google Sheets, Make, Zapier, n8n, a
webhook**, or your own app via the **Apify API**. AI agents can call this actor through the **Apify MCP server**,
so assistants like **Claude, ChatGPT and LangChain** can pull Expedia reviews on demand. **Schedule** the actor
to run hourly or daily for continuous, incremental review monitoring.

### How much does it cost to scrape Expedia reviews?

This actor uses **pay-per-event** pricing with **no start fee** - you pay only for the reviews you actually get,
and **nothing** if a run returns zero reviews:

| Plan | Price per 1,000 reviews |
|---|---|
| Free | **$2.50** |
| Bronze | **$2.30** |
| Silver | **$2.15** |
| Gold+ | **$2.00** |

**Examples:** 500 reviews ≈ **$1.25** (Free) · 5,000 reviews ≈ **$12.50** (Free) / **$10.00** (Gold). Lower
**Max reviews per hotel** to cap spend, and your first runs are covered by **Apify's free tier**. Unlike many
alternatives, there is **no per-run start fee** - you are never charged just for launching a run.

### Tips & advanced options

- Reviews are fetched **newest-first**, so a tight **From date** plus a low **Max reviews per hotel** is the
  cheapest way to **monitor only what's new** (schedule it daily for incremental review tracking).
- Feed many hotels in one run - the actor **deduplicates** repeated URLs automatically.
- For very large properties (thousands of reviews) the hotel's reviews may be split across a few dataset items to
  keep each item a manageable size; the **Hotels** view still summarizes each property in one row.
- Use **Review sources** to compare the same hotel's reviews across Expedia vs Hotels.com vs Travelocity.

### Related FactDen scrapers

Building a review-intelligence pipeline? Pair this with other FactDen actors on the Apify Store:

- **[G2 Reviews Scraper](https://apify.com/factden/g2-reviews-scraper)** - B2B software reviews, ratings &
  battlecards.
- **[Indeed Jobs Scraper](https://apify.com/factden/indeed-jobs-scraper)** - job listings & company data.
- **[Trip.com & Ctrip Reviews Scraper](https://apify.com/factden/ctrip-trip-reviews-scraper)** - hotel
  reviews across Trip.com / Ctrip.
- **[Hotels.com Reviews Scraper](https://apify.com/factden/hotels-com-reviews-scraper)** - hotel ratings,
  review text & sentiment.

### FAQ, disclaimers & support

- **Which sites does it support?** All **seven Expedia Group brands** - Expedia, **Hotels.com**, Travelocity,
  Orbitz, Wotif, CheapTickets and ebookers. Paste any brand's hotel URL directly (Hotels.com `/ho<id>/` URLs are
  resolved automatically). Use **Review sources** to pick which brands' reviews to return.
- **Is scraping Expedia reviews legal?** This actor collects only **publicly available** review content and does
  not touch private or account data. You are responsible for complying with Expedia's Terms of Service and
  applicable laws (including data-protection rules like GDPR) when using the data. See Apify's guide,
  [is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/), for background.
- **Do I need an Expedia account or API key?** No.
- **Can I use it via the Apify API or an MCP server?** Yes - run it through the Apify **REST API** (see the
  example above) or connect it to an AI agent via the **Apify MCP server**, so assistants like Claude or ChatGPT
  can fetch Expedia reviews on demand.
- **How many reviews can I get per hotel?** As many as the hotel has - set **Max reviews per hotel** to cap it;
  `totalReviewCount` tells you how many exist in total.
- **How fresh is the data?** Reviews are fetched live and **newest-first**, so you always get the latest ones
  first.
- **Can I get reviews in other languages?** Yes - reviews are returned in their original language with a
  `language` code and an `isMachineTranslated` flag; the hotel aggregate includes per-language counts.
- **A hotel returned fewer reviews than expected.** Your date/rating/source filters, or **Max reviews per
  hotel**, may be limiting the result; `totalReviewCount` shows how many exist in total.
- **Can I schedule it or get only new reviews?** Yes - schedule the actor and set a **From date** to pull only
  reviews since your last run.
- **Found a bug or need a field we don't return?** Open the **Issues** tab on this actor's Apify page.

### Changelog

- **2026-07** - Output split into dedicated **Reviews** and **Hotels** datasets (previously a single dataset
  with views), matching the other FactDen review scrapers.
- **Initial release** - All **7 Expedia Group brands** in one actor; per-review **LLM-ready markdown**;
  incremental **since-date** runs; JSON/CSV/Excel export and full REST API.

***

⭐ **Find this useful?** **Bookmark** the actor and leave a **review** on its Apify Store page - it helps other
travelers and hotel teams find it, and tells us which features to build next.

# Actor input Schema

## `hotelUrls` (type: `array`):

Paste one hotel per line — a hotel page URL from any Expedia Group site (Expedia, Hotels.com, Travelocity, Orbitz, Wotif, CheapTickets, ebookers; any regional domain) or a bare Expedia property ID. Expedia-family URLs carry the id in the `.h<id>.` path; Hotels.com `/ho<id>/` links are resolved automatically. Examples: `https://www.expedia.com/Las-Vegas-Hotels-The-Venetian-Resort-Las-Vegas.h1443.Hotel-Information`, `https://www.hotels.com/ho115902/`, or just `140596`.

## `maxReviewsPerHotel` (type: `integer`):

How many reviews to pull per hotel (fetched newest-first). Lower this to control cost and run time.

## `sortBy` (type: `string`):

Output order of the returned reviews. Reviews are fetched newest-first from the source; `Highest rating` / `Lowest rating` reorder the retrieved set (not a global top-N across the whole hotel).

## `fromDate` (type: `string`):

Keep only reviews submitted on or after this day. Leave empty for no lower bound.

## `toDate` (type: `string`):

Keep only reviews submitted on or before this day. Leave empty for no upper bound.

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

Keep only reviews with an overall rating at or above this value (1–5).

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

Keep only reviews with an overall rating at or below this value (1–5).

## `reviewSources` (type: `array`):

Which Expedia Group brands' reviews to return per hotel. **Leave empty for all brands** (the cross-brand union, e.g. Expedia + Hotels.com reviews for the same property). Pick one for a single-brand filter, or several for a subset.

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

Proxy settings. Datacenter proxies are sufficient for Expedia at typical volumes; switch to residential IPs for very large runs.

## Actor input object example

```json
{
  "hotelUrls": [
    "https://www.expedia.com/Las-Vegas-Hotels-The-Venetian-Resort-Las-Vegas.h1443.Hotel-Information",
    "140596",
    "https://www.hotels.com/ho115902/",
    "https://www.travelocity.com/Las-Vegas-Hotels-Caesars-Palace.h41245.Hotel-Information",
    "https://www.orbitz.com/Las-Vegas-Hotels-The-Palazzo.h1769973.Hotel-Information"
  ],
  "maxReviewsPerHotel": 200,
  "sortBy": "newest",
  "minRating": 1,
  "maxRating": 5,
  "reviewSources": [],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

One row per guest review (hotel context merged onto each row) with ratings, full review text, category sub-ratings, stay dates, traveler type, language, owner responses and an LLM-ready markdownContent block.

## `hotels` (type: `string`):

One row per hotel with aggregate average rating, recency-weighted rating, total review count, category sub-ratings, coordinates and how many reviews were extracted.

# 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 = {
    "hotelUrls": [
        "https://www.expedia.com/Las-Vegas-Hotels-The-Venetian-Resort-Las-Vegas.h1443.Hotel-Information",
        "140596",
        "https://www.hotels.com/ho115902/",
        "https://www.travelocity.com/Las-Vegas-Hotels-Caesars-Palace.h41245.Hotel-Information",
        "https://www.orbitz.com/Las-Vegas-Hotels-The-Palazzo.h1769973.Hotel-Information"
    ]
};

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

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

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

```

## Python example

```python
from apify_client import ApifyClient

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

# Prepare the Actor input
run_input = { "hotelUrls": [
        "https://www.expedia.com/Las-Vegas-Hotels-The-Venetian-Resort-Las-Vegas.h1443.Hotel-Information",
        "140596",
        "https://www.hotels.com/ho115902/",
        "https://www.travelocity.com/Las-Vegas-Hotels-Caesars-Palace.h41245.Hotel-Information",
        "https://www.orbitz.com/Las-Vegas-Hotels-The-Palazzo.h1769973.Hotel-Information",
    ] }

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

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

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

```

## CLI example

```bash
echo '{
  "hotelUrls": [
    "https://www.expedia.com/Las-Vegas-Hotels-The-Venetian-Resort-Las-Vegas.h1443.Hotel-Information",
    "140596",
    "https://www.hotels.com/ho115902/",
    "https://www.travelocity.com/Las-Vegas-Hotels-Caesars-Palace.h41245.Hotel-Information",
    "https://www.orbitz.com/Las-Vegas-Hotels-The-Palazzo.h1769973.Hotel-Information"
  ]
}' |
apify call factden/expedia-hotel-reviews-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Expedia Reviews Scraper ✈️ Hotel Ratings, Text & Sentiment",
        "description": "Scrape Expedia hotel reviews at scale - guest ratings, full review text, sub-ratings, stay dates, traveler type, language & owner responses, plus LLM-ready markdown. Also accepts Hotels.com, Travelocity, Orbitz, Wotif, CheapTickets & ebookers URLs. Filter by date/rating; export JSON/CSV.",
        "version": "1.0",
        "x-build-id": "k46Q9yWJDK9uPt18s"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/factden~expedia-hotel-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-factden-expedia-hotel-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/factden~expedia-hotel-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-factden-expedia-hotel-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/factden~expedia-hotel-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-factden-expedia-hotel-reviews-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "hotelUrls"
                ],
                "properties": {
                    "hotelUrls": {
                        "title": "🏨 Hotel URLs or property IDs",
                        "minItems": 1,
                        "maxItems": 500,
                        "type": "array",
                        "description": "Paste one hotel per line — a hotel page URL from any Expedia Group site (Expedia, Hotels.com, Travelocity, Orbitz, Wotif, CheapTickets, ebookers; any regional domain) or a bare Expedia property ID. Expedia-family URLs carry the id in the `.h<id>.` path; Hotels.com `/ho<id>/` links are resolved automatically. Examples: `https://www.expedia.com/Las-Vegas-Hotels-The-Venetian-Resort-Las-Vegas.h1443.Hotel-Information`, `https://www.hotels.com/ho115902/`, or just `140596`.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxReviewsPerHotel": {
                        "title": "🔢 Max reviews per hotel",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "How many reviews to pull per hotel (fetched newest-first). Lower this to control cost and run time.",
                        "default": 200
                    },
                    "sortBy": {
                        "title": "↕️ Sort reviews by",
                        "enum": [
                            "newest",
                            "oldest",
                            "highestRating",
                            "lowestRating"
                        ],
                        "type": "string",
                        "description": "Output order of the returned reviews. Reviews are fetched newest-first from the source; `Highest rating` / `Lowest rating` reorder the retrieved set (not a global top-N across the whole hotel).",
                        "default": "newest"
                    },
                    "fromDate": {
                        "title": "📅 Reviews from",
                        "type": "string",
                        "description": "Keep only reviews submitted on or after this day. Leave empty for no lower bound."
                    },
                    "toDate": {
                        "title": "📅 Reviews to",
                        "type": "string",
                        "description": "Keep only reviews submitted on or before this day. Leave empty for no upper bound."
                    },
                    "minRating": {
                        "title": "⭐ Minimum rating",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Keep only reviews with an overall rating at or above this value (1–5).",
                        "default": 1
                    },
                    "maxRating": {
                        "title": "⭐ Maximum rating",
                        "minimum": 1,
                        "maximum": 5,
                        "type": "integer",
                        "description": "Keep only reviews with an overall rating at or below this value (1–5).",
                        "default": 5
                    },
                    "reviewSources": {
                        "title": "🏷️ Review sources (brands)",
                        "type": "array",
                        "description": "Which Expedia Group brands' reviews to return per hotel. **Leave empty for all brands** (the cross-brand union, e.g. Expedia + Hotels.com reviews for the same property). Pick one for a single-brand filter, or several for a subset.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "expedia",
                                "hotels",
                                "travelocity",
                                "orbitz",
                                "wotif",
                                "cheaptickets",
                                "ebookers"
                            ],
                            "enumTitles": [
                                "Expedia",
                                "Hotels.com",
                                "Travelocity",
                                "Orbitz",
                                "Wotif",
                                "CheapTickets",
                                "ebookers"
                            ]
                        },
                        "default": []
                    },
                    "proxyConfiguration": {
                        "title": "🌐 Proxy configuration",
                        "type": "object",
                        "description": "Proxy settings. Datacenter proxies are sufficient for Expedia at typical volumes; switch to residential IPs for very large runs.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
