# Expedia Reviews Scraper (`valiant_quarter/expedia-reviews-scraper`) Actor

Scrape Expedia hotel reviews, ratings & guest feedback at scale. Extract review text, scores, dates, themes and management responses as structured JSON/CSV/Excel — no login or API key. Great for sentiment analysis, reputation monitoring and competitive research.

- **URL**: https://apify.com/valiant\_quarter/expedia-reviews-scraper.md
- **Developed by:** [valiant quarter](https://apify.com/valiant_quarter) (community)
- **Categories:** Travel, E-commerce
- **Stats:** 2 total users, 0 monthly users, 46.7% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## 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, ratings and guest feedback at scale — no login, no API key.**
Just paste an Expedia hotel URL and export clean, structured review data (JSON, CSV, Excel)
for competitive analysis, sentiment analysis, reputation monitoring and market research.

This **Expedia review scraper** extracts every review the hotel page exposes — review text,
guest score, reviewer name, stay date, review themes and the hotel's management responses —
and hands it back to you as a ready-to-use dataset.

---

### ✨ What this Expedia scraper does

- ⭐ **Scrapes hotel reviews from Expedia** by property URL or hotel ID
- 📝 Extracts **review text, rating/score, reviewer, date, language and themes**
- 💬 Captures **management (owner) responses** to each review
- 🔢 Reads the property's **overall score and total review count**
- 🔀 Optional **sort order** (newest, highest rated, lowest rated)
- 📦 Outputs structured **JSON / CSV / Excel / HTML** via the Apify dataset
- 🤖 Bypasses Expedia's Akamai bot protection with a real browser + fingerprint rotation

### 💡 Use cases

- **Hotel reputation monitoring** — track new guest reviews and scores over time
- **Sentiment analysis** — feed review text into an NLP/LLM model
- **Competitive analysis** — compare guest feedback across competing hotels
- **Market research** — understand what travelers praise or complain about
- **Review aggregation** — combine Expedia reviews with other OTA sources

### 🚀 How to scrape Expedia reviews (step by step)

1. Open the hotel on Expedia, e.g. `https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information`.
2. Paste that URL into the **Expedia hotel URL** field.
3. Set **Maximum reviews** and (optionally) a **sort order**.
4. Click **Start** and download the results from the dataset.

### ⚙️ Input

| Field | Type | Description |
|-------|------|-------------|
| `hotelUrl` | string | Full Expedia hotel URL. |
| `hotelId` | string | Optional. Numeric Expedia property id (e.g. `438504`). Overrides the URL id. |
| `maxReviews` | integer | Stop after this many reviews. Default `20`. |
| `maxReviewPages` | integer | Cap on review pages (10 each). Default `8`. |
| `sortOrder` | enum | `DEFAULT`, `NEWEST_TO_OLDEST`, `HIGHEST_TO_LOWEST_RATED`, `LOWEST_TO_HIGHEST_RATED`. |
| `proxyConfiguration` | object | Proxy settings. **Residential proxies recommended** (see Reliability). |

#### Example input

```json
{
    "hotelUrl": "https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information",
    "maxReviews": 50,
    "sortOrder": "NEWEST_TO_OLDEST",
    "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
````

### 📤 Output

Each dataset item is a single review:

```json
{
    "hotelId": "438504",
    "hotelName": "London Heathrow Marriott Hotel",
    "hotelUrl": "https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information",
    "reviewId": "6a2c799d489ecd5380815f14",
    "title": null,
    "text": "Loved how close to the airport it was, the staff were super lovely and the rooms were clean and spacious.",
    "score": 10,
    "scoreMax": 10,
    "scoreLabel": "Excellent",
    "scoreText": "10/10 Excellent",
    "author": "Emma",
    "submissionTime": "Jun 12, 2026",
    "locale": "en_AU",
    "managementResponses": [
        {
            "header": "Response from Cristal Balladares on Jun 15, 2026",
            "response": "Dear Emma, thank you for your review..."
        }
    ],
    "themes": ["Liked: Cleanliness, staff & service, amenities, property conditions & facilities"]
}
```

#### Output fields

| Field | Description |
|-------|-------------|
| `hotelId`, `hotelName`, `hotelUrl` | Property the review belongs to |
| `reviewId` | Expedia's unique review id |
| `text` | Full review text |
| `score`, `scoreMax`, `scoreLabel`, `scoreText` | Guest rating, e.g. `10 / 10 Excellent` |
| `author` | Reviewer display name |
| `submissionTime` | When the review was posted |
| `locale` | Reviewer language/locale |
| `managementResponses` | Hotel/owner replies to the review |
| `themes` | Expedia review theme tags (cleanliness, staff, amenities, …) |

### 🔌 Integrations & export

Results are stored in an Apify dataset, so you can **export to JSON, CSV, Excel, HTML or XML**,
or push them to Google Sheets, Slack, Zapier, Make, a webhook or your own database via
Apify Integrations and the API.

### 🛡️ How it works & reliability

Expedia is protected by **Akamai Bot Manager**. This actor loads each hotel page in a real
Chromium browser with rotating fingerprints, waits for the anti-bot challenge to resolve, and
reads reviews directly from the property's own review data — a robust approach that survives
Expedia's frequent front-end changes.

For **reliable, high-volume scraping use Apify Residential proxies**. Datacenter IPs are
almost always blocked by Expedia. Without residential proxies the actor still rotates
fingerprints and can succeed on clean IPs, but results are intermittent — simply re-run if a
run reports a bot-protection block.

### ❓ FAQ

**Do I need an Expedia account or API key?** No. Just a public hotel URL.

**How many reviews can I scrape?** Set `maxReviews`. Reaching hundreds of reviews reliably
requires residential proxies.

**Which fields are returned?** Review text, score, reviewer, date, locale, themes and
management responses — see the Output section.

**Can I sort reviews?** Yes — newest first, highest or lowest rated.

**Is scraping Expedia reviews legal?** This actor collects only **publicly available** review
data. You are responsible for using scraped data in line with Expedia's terms and applicable
laws (e.g. GDPR). Do not scrape personal data you are not entitled to process.

***

⭐ Found this useful? Star and review the actor to help others discover it.

# Actor input Schema

## `hotelUrl` (type: `string`):

Full URL of the Expedia hotel page, e.g. https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information

## `hotelId` (type: `string`):

Optional. The numeric Expedia property ID (e.g. 438504). If provided, it overrides the ID parsed from the hotel URL.

## `maxReviews` (type: `integer`):

Stop after collecting this many reviews.

## `maxReviewPages` (type: `integer`):

Stop after fetching this many review pages (10 reviews per page).

## `sortOrder` (type: `string`):

How Expedia should sort reviews before they are scraped.

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

Proxies to use. Expedia is protected by Akamai bot detection. RESIDENTIAL proxies give by far the highest success rate; if you don't have them, leave this off (the actor rotates browser fingerprints and can still get through on clean IPs, but less reliably). Datacenter proxies are almost always blocked by Expedia.

## `headless` (type: `boolean`):

Disable only for local debugging.

## Actor input object example

```json
{
  "hotelUrl": "https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information",
  "maxReviews": 10,
  "maxReviewPages": 8,
  "sortOrder": "DEFAULT",
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "headless": true
}
```

# 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 = {
    "hotelUrl": "https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information",
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("valiant_quarter/expedia-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 = {
    "hotelUrl": "https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information",
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("valiant_quarter/expedia-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 '{
  "hotelUrl": "https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call valiant_quarter/expedia-reviews-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Expedia Reviews Scraper",
        "description": "Scrape Expedia hotel reviews, ratings & guest feedback at scale. Extract review text, scores, dates, themes and management responses as structured JSON/CSV/Excel — no login or API key. Great for sentiment analysis, reputation monitoring and competitive research.",
        "version": "1.0",
        "x-build-id": "HFB1w0eFqLPeif4MF"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/valiant_quarter~expedia-reviews-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-valiant_quarter-expedia-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/valiant_quarter~expedia-reviews-scraper/runs": {
            "post": {
                "operationId": "runs-sync-valiant_quarter-expedia-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/valiant_quarter~expedia-reviews-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-valiant_quarter-expedia-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",
                "properties": {
                    "hotelUrl": {
                        "title": "Expedia hotel URL",
                        "type": "string",
                        "description": "Full URL of the Expedia hotel page, e.g. https://www.expedia.com/London-Hotels-London-Heathrow-Marriott-Hotel.h438504.Hotel-Information"
                    },
                    "hotelId": {
                        "title": "Expedia hotel ID",
                        "type": "string",
                        "description": "Optional. The numeric Expedia property ID (e.g. 438504). If provided, it overrides the ID parsed from the hotel URL."
                    },
                    "maxReviews": {
                        "title": "Maximum reviews",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Stop after collecting this many reviews.",
                        "default": 10
                    },
                    "maxReviewPages": {
                        "title": "Maximum review pages",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Stop after fetching this many review pages (10 reviews per page).",
                        "default": 8
                    },
                    "sortOrder": {
                        "title": "Review sort order",
                        "enum": [
                            "DEFAULT",
                            "NEWEST_TO_OLDEST",
                            "HIGHEST_TO_LOWEST_RATED",
                            "LOWEST_TO_HIGHEST_RATED"
                        ],
                        "type": "string",
                        "description": "How Expedia should sort reviews before they are scraped.",
                        "default": "DEFAULT"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxies to use. Expedia is protected by Akamai bot detection. RESIDENTIAL proxies give by far the highest success rate; if you don't have them, leave this off (the actor rotates browser fingerprints and can still get through on clean IPs, but less reliably). Datacenter proxies are almost always blocked by Expedia."
                    },
                    "headless": {
                        "title": "Run browser in headless mode",
                        "type": "boolean",
                        "description": "Disable only for local debugging.",
                        "default": 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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
