# Expedia Scraper \[$2💰] | Reviews | Hotels.com (`ahmed_jasarevic/expedia-reviews-scraper`) Actor

Extract Expedia & Hotels.com guest reviews, room rates, and hotel search results for reputation monitoring, competitive intelligence, and market research. No Expedia API key needed.

- **URL**: https://apify.com/ahmed\_jasarevic/expedia-reviews-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Categories:**
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.60 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Expedia Scraper \[Only $2💸] | Hotel Reviews | Price Monitoring | Hotels.com

Extract Expedia and Hotels.com hotel guest reviews, room rates, and search results for reputation monitoring, competitive intelligence, and hospitality market research — no API key required. Scrape Expedia hotel reviews with ratings, sentiment, management responses, and photos at scale via GraphQL.

### Main Use Cases

- **Hotel reputation monitoring** — Track guest sentiment and rating trends for your own or competitor properties over time
- **Competitive intelligence** — Benchmark review scores, pricing, and amenity positioning against competing hotels
- **Hotel price monitoring** — Schedule nightly rate and availability tracking across room types and date ranges
- **Market research** — Analyze traveler types, languages, stay durations, and what guests praise or complain about
- **Sentiment analysis datasets** — Build structured review corpora to train or feed ML/NLP models
- **Travel industry research** — Study booking patterns, review volume, and pricing across whole destinations or regions

### Extract Hotel Reviews Without Official API Access

[Expedia](https://www.expedia.com) and [Hotels.com](https://www.hotels.com) do not offer a public API for guest reviews, room rates, or search listings. The Expedia Rapid API is partner-gated and built for booking flows, not data access. This actor fills that gap by talking directly to the same GraphQL API the Expedia Group websites use — no browser automation, no API key, no payment for scraping infrastructure.

This actor **only accesses publicly available pages** — it does not bypass login walls, solve CAPTCHAs, or access private inventory.

### How It Works

The actor calls Expedia Group's internal GraphQL API — the same data later their web and mobile apps use — to extract structured JSON. It automatically handles:

- **TLS fingerprint impersonation** and session cookie management to mitigate Akamai bot protections
- **Automatic rotation of persisted GraphQL query hashes** when Expedia redeploys their frontend
- **429-aware throttling** — honors the server's Retry-After header and rotates sessions automatically
- **Configurable parallelism** for high-concurrency bulk extraction across many properties
- **Residential proxy support** with Apify's built-in proxy pool

### Build Business Databases Without Manual Collection

Use the actor's three core modes to build structured travel datasets programmatically:

1. **Review scraping** — Pass Expedia or Hotels.com hotel URLs (or bare property IDs), get structured review data with ratings, text, traveler types, stay dates, photos, and management responses
2. **Hotel search** — Search by city or region with check-in/out dates; return hotel listings with pricing, star/guest ratings, amenities, coordinates, and filter options
3. **Room rates** — Fetch room types, nightly rates, rate plans, meal plans, cancellation policies, and availability for specific date windows
4. **Things To Do** — Scrape reviews for Expedia activities, tours, and attractions
5. **Hotel info only** — Set `skipReviews` to emit one summary row per property (plus room rates) with no review rows — ideal for overnight rate-monitoring runs

### Input

| Field | Type | Required | Default | Notes |
|-------|------|----------|---------|-------|
| `startUrls` | array | No\* | — | Expedia/Hotels.com hotel URLs, bare property IDs, activity URLs, or deeplinks |
| `searchLocations` | array | No\* | — | City/region search configs with optional per-location check-in/out dates |
| `checkIn` | string | No | — | Default check-in date for search locations (YYYY-MM-DD) |
| `checkOut` | string | No | — | Default check-out date for search locations (YYYY-MM-DD) |
| `searchSort` | string | No | `RECOMMENDED` | `RECOMMENDED`, `PRICE_LOW_TO_HIGH`, `PRICE_HIGH_TO_LOW`, `GUEST_RATING`, `STAR_RATING_HIGH_TO_LOW` |
| `searchAmenities` | array | No | `[]` | Filter by `pool`, `gym`, `hot_tub`, `spa`, `parking`, `wifi`, etc. |
| `minStars` | integer | No | `0` | Minimum star rating (1-5, 0=any) |
| `minRating` | number | No | `0` | Minimum guest rating out of 10 |
| `maxResults` | integer | No | `50` | Max hotel results per search location |
| `maxItems` | integer | No | `1000` | Max review rows per URL (not a run total) |
| `reviewsFrom` | string | No | — | Only emit reviews on/after this date (YYYY-MM-DD) |
| `sortBy` | string | No | `newest` | `newest`, `highest`, `lowest`, `mostHelpful` |
| `includeReviewPhotos` | boolean | No | `true` | Strip `reviewPhotos[]` when false (for compact CSV exports) |
| `includeOwnerResponses` | boolean | No | `true` | Strip `hotelResponse` (management replies) when false |
| `includeRoomRates` | boolean | No | `false` | Fetch room types, pricing, and availability via GraphQL |
| `includeHotelInfo` | boolean | No | `false` | Fetch hotel name/rating via property-info GraphQL op (flaky, off by default) |
| `includePropertyDetails` | boolean | No | `false` | Fetch descriptive block, address, coordinates, amenities, photo gallery |
| `includeCategoryRatings` | boolean | No | `false` | Fetch 5-category ratings (requires `includePropertyDetails`) |
| `includeRatingDistribution` | boolean | No | `false` | Fetch verified rating distribution (requires `includePropertyDetails`) |
| `includePropertyImages` | boolean | No | `true` | Property photo gallery (with details mode) |
| `maxPropertyImages` | integer | No | `200` | Max gallery photos per property |
| `skipReviews` | boolean | No | `false` | Emit one hotel-summary row instead of reviews (for rate/price runs) |
| `roomsCheckIn` | string | No | today | Check-in for room availability queries |
| `roomsCheckOut` | string | No | tomorrow | Check-out for room availability queries |
| `roomsAdults` | integer | No | `2` | Adult count for room availability queries |
| `roomsRegion` | string | No | — | ISO country code for quoted-for country (US, DE, SG, etc.) |
| `roomsLanguage` | string | No | — | `en_US`-style locale override for room queries |
| `requestDelayMs` | integer | No | `2500` | Pause between GraphQL review pages (lower to 1000-1500 on dedicated residential IPs) |
| `maxConcurrency` | integer | No | `2` | Parallel properties scraped at once (keep 1-2 on shared proxies) |
| `maxRequestRetries` | integer | No | `20` | Retry budget per property |
| `proxyConfiguration` | object | No | Residential | **Residential proxies strongly recommended** — datacenter IPs are rate-limited by Expedia Group |
| `debug` | boolean | No | `false` | Store fallback HTML in KV store for troubleshooting |

*\*Either `startUrls` or `searchLocations` is required.*

### Output

The actor emits flat, structured JSON rows tagged by `rowType`. Fields vary by mode:

#### Review row (`rowType: "review"`)

`provider`, `rowType`, `inputUrl`, `url`, `hotelId`, `hotelName`, `reviewId`, `reviewTitle`, `reviewText`, `reviewRating`, `reviewDate`, `reviewLanguage`, `authorName`, `tripType`, `traveledWith`, `stayDuration`, `sentiments` (liked/disliked), `reviewPhotos`, `hotelResponse` (management reply), `hotelOverallRating`, `hotelTotalReviews`, and optional enrichment fields: `hotelCategoryRatings`, `ratingDistribution`, `propertyName`, `starRating`, `propertyType`, `propertyAddress`, `propertyCoordinates`, `propertyDescription`, `propertyAmenities`, `propertyHighlights`, `propertyImages`, `scrapedAt`.

#### Search result row (`rowType: "searchResult"`)

`hotelId`, `name`, `starRating`, `guestRating`, `reviewCount`, `nightlyPrice`, `totalPrice`, `currency`, `freeCancellation`, `propertyUrl`, `city`, `neighborhood`, `latitude`, `longitude`, `amenities`, `imageUrl`, `locationSearched`, `checkIn`, `checkOut`.

#### Room rate row (`rowType: "roomRate"`)

`roomId`, `roomType`, `ratePlan`, `pricePerNight`, `totalPrice`, `currency`, `cancellationPolicy`, `freeCancellation`, `details`, `mealPlans`, `cancellationOptions`, `quotedFor`, `amenities`, `beds`, `maxOccupancy`.

#### Activity review row (`rowType: "activityReview"`)

`provider`, `activityId`, `activityName`, `reviewId`, `reviewText`, `reviewRating`, `reviewLanguage`, `authorName`, `submissionDate`, `locale`, `currency`, `overallRating`, `totalReviews`, `activityHighlights`, `activityFeatures`, `activityPrice`, `activityUrl`.

#### Hotel info row (`rowType: "hotel"`, with `skipReviews: true`)

Single summary row per property with `hotelId`, `hotelName`, `url`, `hotelOverallRating`, `hotelTotalReviews`, plus all enabled enrichment fields.

### Example Input

#### Scrape hotel reviews by URL

```json
{
  "startUrls": [
    { "url": "https://www.expedia.co.uk/London-Hotels.h196459.Hotel-Information" },
    { "url": "https://el.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/" },
    "600217"
  ],
  "maxItems": 500,
  "sortBy": "newest",
  "reviewsFrom": "2024-01-01"
}
```

#### Search hotels by city + track rates

```json
{
  "searchLocations": [
    { "location": "Miami, Florida", "checkIn": "2026-10-01", "checkOut": "2026-10-05" },
    { "location": "Barcelona, Spain", "checkIn": "2026-10-01", "checkOut": "2026-10-05" }
  ],
  "searchSort": "PRICE_LOW_TO_HIGH",
  "maxResults": 30,
  "minStars": 3,
  "excludeVacationRentals": true
}
```

### Example Output

```json
{
  "provider": "expedia",
  "rowType": "review",
  "hotelId": "196459",
  "hotelName": "The Grand Hotel London",
  "reviewId": "abc123",
  "reviewTitle": "Excellent stay",
  "reviewText": "The hotel was clean and the staff were friendly...",
  "reviewRating": 9.0,
  "reviewDate": "2025-06-15",
  "authorName": "John D.",
  "tripType": "Solo travel",
  "traveledWith": "Family",
  "stayDuration": "3 nights",
  "sentiments": { "liked": ["clean room", "great breakfast"], "disliked": ["noisy street"] },
  "reviewPhotos": ["https://example.com/photo1.jpg"],
  "hotelResponse": { "responseText": "Thank you!", "respondedOn": "2025-06-16", "responderName": "Manager" },
  "hotelOverallRating": 8.5,
  "hotelTotalReviews": 1234,
  "scrapedAt": "2025-07-01T12:00:00Z"
}
```

### Integrations & Automation

This actor runs on the Apify platform, giving you:

- **REST API** — trigger runs programmatically from any language
- **Webhooks** — get notified when runs complete
- **Zapier / Make** — connect runs to your existing automation stack
- **Google Sheets, BigQuery, Snowflake** — push results to your data stack
- **Scheduling** — run on a daily, weekly, or hourly cadence

**Recommended schedule for recurring use:** For **reputation/review monitoring**, run **weekly** to catch new reviews and rating shifts. For **price/rate intelligence** or **parity tracking**, run **daily** — hotel rates change frequently. Recurring runs build your time-series dataset and become more valuable over time.

### Related Actors

- [Expedia.com & Hotels.com Reviews \[$2.5\]](https://apify.com/memo23/expedia-scraper) — companion actor covering all three Expedia Group brands
- [Expedia Hotel Reviews Scraper](https://apify.com/factden/expedia-hotel-reviews-scraper) — cross-brand (7 brands) review extraction with AI-ready markdown
- [Tripadvisor Reviews](https://apify.com/maxcopell/tripadvisor-reviews) — guest reviews from TripAdvisor
- [Google Maps Reviews Scraper](https://apify.com/compass/Google-Maps-Reviews-Scraper) — reviews from Google Maps listings
- [Trustpilot Reviews](https://apify.com/automation-lab/trustpilot) — business reviews from Trustpilot

### FAQ

#### Why use this actor instead of the official Expedia API?

Expedia does not offer a public reviews or data API. The **Expedia Rapid API (EPS Rapid)** is partner-gated — you must apply, be approved, and sign a contract — and it's built for booking flows, not for reading guest reviews or shopping competitor rates. Reviews are explicitly outside its scope. This actor provides self-serve access to the same data the Expedia website serves, without the application process.

#### What are alternatives to this actor / to scraping Expedia reviews?

If you need reviews from other platforms, consider actors for **TripAdvisor reviews**, **Google Maps reviews**, **Booking.com reviews**, or **Trustpilot reviews**. For Expedia specifically, the closest Apify alternatives are the other Expedia Group scrapers (see Related Actors above). Off-Apify, third-party data APIs (StayAPI, Outscraper) offer Expedia review endpoints at monthly subscription cost.

#### How is this different from scraping Expedia's HTML pages?

This actor uses Expedia's **GraphQL API** directly instead of parsing HTML. That means: structured JSON output, no CSS selector maintenance, access to fields not always rendered on the page, and stability across frontend redesigns. It also handles anti-bot protections and hash rotation automatically.

#### Does Expedia's bot protection block this?

The actor impersonates a real browser's TLS fingerprint and manages session cookies, which mitigates Expedia's Akamai bot protection. It also rotates residential proxy IPs when rate-limited. However, **residential proxies are strongly recommended** — datacenter IPs are rate-limited by Expedia Group.

#### Can I scrape reviews for my competitor's hotels?

Yes. Any publicly listed Expedia or Hotels.com property can be scraped — there's no ownership restriction. This is useful for competitive benchmarking and market research.

#### Can I filter reviews by date to build incremental datasets?

Yes. Set `reviewsFrom` (e.g., `"2025-01-01"`) to only emit reviews on/after that date. The actor stops paginating once it reaches older reviews, saving compute time on incremental runs.

#### Can this scrape Things To Do activities and tours?

Yes. Pass any Expedia `/things-to-do/...a{id}.activity-details` URL in `startUrls` and the actor scrapes its reviews, pricing, highlights, and features.

#### Does this extract hotel room rates and pricing?

Yes. Set `includeRoomRates: true` to fetch room types, rate plans, nightly and total prices, cancellation policies, meal plans, and availability for the specified dates. Combine with `skipReviews: true` for fast price-only runs.

#### Is this available via the Apify API or MCP server?

Yes. Run it through the Apify REST API or via the Apify MCP server, so AI assistants (Claude, GPT, LangChain) can pull Expedia reviews on demand.

### SEO Keywords

expedia scraper, expedia reviews scraper, hotels.com scraper, hotels.com reviews, scrape expedia reviews, expedia hotel reviews, hotel review scraping, expedia data extraction, hotels.com data, hotel price monitoring, hotel rate tracking, hotel competitive intelligence, hotel reputation management, hotel sentiment analysis, hospitality market research, guest review data, expedia graphql, expedia api alternative, hotels.com api alternative, scrape hotel reviews, travel data scraping, hotel review dataset, price parity monitoring, expedia uk, expedia de, expedia au

### For AI Agents & LLM Apps

**What it returns:** Structured JSON rows of Expedia/Hotels.com hotel guest reviews (ratings, text, sentiments, traveler metadata, photos, management responses), hotel search results (pricing, amenities, coordinates), and room rate data (types, rates, availability, cancellation policies).

**Minimal working input:**

```json
{
  "startUrls": [
    { "url": "https://www.expedia.com/London-Hotels.h196459.Hotel-Information" }
  ],
  "maxItems": 100
}
```

**Variant inputs:**

- Hotel search mode:

```json
{
  "searchLocations": ["Miami, Florida"],
  "checkIn": "2026-10-01",
  "checkOut": "2026-10-05",
  "maxResults": 20
}
```

- Price-only / hotel-info mode:

```json
{
  "startUrls": [{ "url": "https://www.expedia.com/Hotel.h600217.Hotel-Information" }],
  "skipReviews": true,
  "includeRoomRates": true
}
```

**Output fields:** `provider`, `rowType`, `inputUrl`, `url`, `hotelId`, `hotelName`, `reviewId`, `reviewTitle`, `reviewText`, `reviewRating`, `reviewDate`, `reviewLanguage`, `authorName`, `tripType`, `traveledWith`, `stayDuration`, `sentiments`, `reviewPhotos`, `hotelResponse`, `hotelOverallRating`, `hotelTotalReviews`, plus optional `hotelCategoryRatings`, `ratingDistribution`, `propertyName`, `starRating`, `propertyAddress`, `propertyCoordinates`, `propertyDescription`, `propertyAmenities`, `propertyHighlights`, `propertyImages`, `scrapedAt`. Search/room-rate/activity modes return their own field sets (see Output section above).

**Behaviors an agent should know:**

- `maxItems` is per-URL (not a run total): N URLs × `maxItems` = max row count. Set it deliberately to control cost.
- `startUrls` and `searchLocations` are mutually complementary — you can use either or both; at least one is required.
- `skipReviews: true` skips review rows entirely and emits one summary row per property — use it for rate/price intelligence runs.
- Enrichment flags (`includePropertyDetails`, `includeCategoryRatings`, `includeRatingDistribution`) add extra GraphQL calls per property and set off a chain — leave off unless the fields are needed.
- `maxConcurrency` is per-IP rate-limited by Expedia's GraphQL endpoint. Keep at 1-2 unless you have dedicated residential proxy IPs.
- Residential proxies are strongly recommended (`"apifyProxyGroups": ["RESIDENTIAL"]`).

**Billing model:** Pay-per-event. Charged on actor start (per GB memory) + per result in the default dataset.

### Legal & Compliance Disclaimer

This actor is an independent tool and is not affiliated with, endorsed by, or sponsored by Expedia Group, Expedia, or Hotels.com. It accesses only **publicly available pages** rendered by Expedia Group's own websites — it does not bypass login walls, solve CAPTCHAs, or access private inventory or membership data. Users are responsible for ensuring their use complies with Expedia Group's Terms of Service and applicable data-protection laws, including GDPR and CCPA where EU or California personal data is involved. Review data may include personally identifiable information (reviewer names); do not use it for unsolicited outreach in violation of applicable law (e.g., CAN-SPAM, GDPR).

# Actor input Schema

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

Any mix of: Expedia hotel URLs (long slug, short path, or minimal slug), Hotels.com hotel URLs (/ho{id}/), bare property IDs (600217 or h600217), and Expedia deeplinks (expe.app.link / expe.onelink.me). All regional Expedia TLDs work (.co.uk, .de, .com.sg, ...).

## `searchLocations` (type: `array`):

Search for hotels by city or region name. Each entry can be a string (city name) or an object { location, checkIn, checkOut }. Requires checkIn/checkOut dates.

## `checkIn` (type: `string`):

Default check-in date for search locations (YYYY-MM-DD). Can be overridden per location.

## `checkOut` (type: `string`):

Default check-out date for search locations (YYYY-MM-DD). Can be overridden per location.

## `searchSort` (type: `string`):

How to sort hotel search results.

## `searchAmenities` (type: `array`):

Filter search results by amenities. Common values: pool, gym, hot\_tub, spa, parking, free\_parking, pet\_friendly, restaurant, breakfast, wifi, airport\_shuttle, kitchen, indoor\_pool.

## `minStars` (type: `integer`):

Minimum hotel star class (1-5). Set 0 to disable.

## `minRating` (type: `number`):

Minimum guest rating out of 10 (e.g. 7.0). Set 0 to disable.

## `excludeVacationRentals` (type: `boolean`):

Filter out Vrbo/Airbnb-style vacation rentals from search results.

## `maxResults` (type: `integer`):

Maximum hotel results per search location (for search mode).

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

Maximum review rows per Start URL (newest first) - not a run total. A run with N URLs returns up to maxItems x N rows.

## `reviewsFrom` (type: `string`):

Format YYYY-MM-DD. Only emit reviews on/after this date; pagination stops early once older reviews are reached (reviews are sorted newest-first). Leave empty for all reviews.

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

Order of the review list. newest is the site default and the safest for date filtering. "Most relevant" is not offered because Expedia's server errors on it over this GraphQL path.

## `includeReviewPhotos` (type: `boolean`):

Set false to strip reviewPhotos\[] from every row (useful for compact CSV exports).

## `includeOwnerResponses` (type: `boolean`):

Set false to strip hotelResponse (management replies) from every row.

## `includeRoomRates` (type: `boolean`):

Fetch and output room types, pricing, and availability via GraphQL alongside reviews.

## `includeHotelInfo` (type: `boolean`):

Fetch hotel name/rating via the property-info GraphQL operation. Off by default - that operation is the flakiest call in the chain (HTTP 400/429) and reviews don't need it.

## `includePropertyDetails` (type: `boolean`):

Fetch the hotel's descriptive block (address, coordinates, description, amenities, highlights, languages, photo gallery) and merge it onto every review row. Sets off a chain of extra GraphQL calls per property.

## `includeCategoryRatings` (type: `boolean`):

Fetch per-category ratings (Cleanliness, Staff & service, Amenities, Property conditions, Eco-friendliness) and overall rating + total reviews. Requires includePropertyDetails.

## `includeRatingDistribution` (type: `boolean`):

Fetch the verified review distribution (count + % per band: Excellent, Very good, Good, Alright, Poor). Requires includePropertyDetails.

## `includePropertyImages` (type: `boolean`):

Fetch the property photo gallery with URL, category, and caption per image, attached to every row as propertyImages\[]. On by default when includePropertyDetails is on.

## `maxPropertyImages` (type: `integer`):

Maximum number of gallery photos to collect per property.

## `skipReviews` (type: `boolean`):

True = do not scrape review rows; emit one hotel-summary row (+ rooms when includeRoomRates) instead. Useful for overnight pricing/availability runs.

## `roomsCheckIn` (type: `string`):

Check-in date for room availability queries (YYYY-MM-DD). Defaults to today.

## `roomsCheckOut` (type: `string`):

Check-out date for room availability queries (YYYY-MM-DD). Defaults to tomorrow.

## `roomsAdults` (type: `integer`):

Number of adults for room availability queries.

## `roomsRegion` (type: `string`):

ISO country code for the quoted-for country (e.g. US, DE, SG). Defaults to the context country of the start URL.

## `roomsLanguage` (type: `string`):

en\_US-style locale override for room availability queries. Defaults to the context locale of the start URL.

## `requestDelayMs` (type: `integer`):

Pause between consecutive GraphQL review-page requests per property (jitter added). 2500ms default survives shared proxies; lower to 1000-1500 only on dedicated residential IPs.

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

Parallel properties scraped at once. The GraphQL endpoint rate-limits PER IP - each property gets its own proxy IP, but keep at 1-2 on shared proxy plans.

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

Retry budget for GraphQL review pages per property. Each 429 rotates to a fresh session + proxy IP and honors the server Retry-After header.

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

Residential proxies are strongly recommended - datacenter IPs are rate-limited by Expedia Group.

## `debug` (type: `boolean`):

Stores the fallback property-page HTML per property in the key-value store for troubleshooting response-shape changes.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.expedia.co.uk/Kastoria-Hotels-Hotel-Anastassiou.h6136437.Hotel-Information"
    },
    {
      "url": "https://el.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/"
    }
  ],
  "searchLocations": [
    {
      "url": "New York, New York, United States of America"
    },
    {
      "url": "Miami, Florida, United States of America"
    }
  ],
  "searchSort": "RECOMMENDED",
  "searchAmenities": [],
  "minStars": 0,
  "minRating": 0,
  "excludeVacationRentals": true,
  "maxResults": 50,
  "maxItems": 1000,
  "sortBy": "newest",
  "includeReviewPhotos": true,
  "includeOwnerResponses": true,
  "includeRoomRates": false,
  "includeHotelInfo": false,
  "includePropertyDetails": false,
  "includeCategoryRatings": false,
  "includeRatingDistribution": false,
  "includePropertyImages": true,
  "maxPropertyImages": 200,
  "skipReviews": false,
  "roomsAdults": 2,
  "requestDelayMs": 2500,
  "maxConcurrency": 2,
  "maxRequestRetries": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  },
  "debug": false
}
```

# Actor output Schema

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

No description

## `searchResults` (type: `string`):

No description

## `roomRates` (type: `string`):

No description

# API

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

## JavaScript example

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

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

// Prepare Actor input
const input = {
    "startUrls": [
        {
            "url": "https://www.expedia.co.uk/Kastoria-Hotels-Hotel-Anastassiou.h6136437.Hotel-Information"
        },
        {
            "url": "https://el.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/"
        }
    ],
    "searchLocations": [
        {
            "url": "New York, New York, United States of America"
        },
        {
            "url": "Miami, Florida, United States of America"
        }
    ],
    "searchSort": "RECOMMENDED",
    "searchAmenities": [],
    "excludeVacationRentals": true,
    "sortBy": "newest",
    "includeReviewPhotos": true,
    "includeOwnerResponses": true,
    "includeRoomRates": false,
    "includeHotelInfo": false,
    "includePropertyDetails": false,
    "includeCategoryRatings": false,
    "includeRatingDistribution": false,
    "includePropertyImages": true,
    "skipReviews": false,
    "debug": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/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 = {
    "startUrls": [
        { "url": "https://www.expedia.co.uk/Kastoria-Hotels-Hotel-Anastassiou.h6136437.Hotel-Information" },
        { "url": "https://el.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/" },
    ],
    "searchLocations": [
        { "url": "New York, New York, United States of America" },
        { "url": "Miami, Florida, United States of America" },
    ],
    "searchSort": "RECOMMENDED",
    "searchAmenities": [],
    "excludeVacationRentals": True,
    "sortBy": "newest",
    "includeReviewPhotos": True,
    "includeOwnerResponses": True,
    "includeRoomRates": False,
    "includeHotelInfo": False,
    "includePropertyDetails": False,
    "includeCategoryRatings": False,
    "includeRatingDistribution": False,
    "includePropertyImages": True,
    "skipReviews": False,
    "debug": False,
}

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

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

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

```

## CLI example

```bash
echo '{
  "startUrls": [
    {
      "url": "https://www.expedia.co.uk/Kastoria-Hotels-Hotel-Anastassiou.h6136437.Hotel-Information"
    },
    {
      "url": "https://el.hotels.com/ho434012/hotel-anastassiou-kastoria-ellada/"
    }
  ],
  "searchLocations": [
    {
      "url": "New York, New York, United States of America"
    },
    {
      "url": "Miami, Florida, United States of America"
    }
  ],
  "searchSort": "RECOMMENDED",
  "searchAmenities": [],
  "excludeVacationRentals": true,
  "sortBy": "newest",
  "includeReviewPhotos": true,
  "includeOwnerResponses": true,
  "includeRoomRates": false,
  "includeHotelInfo": false,
  "includePropertyDetails": false,
  "includeCategoryRatings": false,
  "includeRatingDistribution": false,
  "includePropertyImages": true,
  "skipReviews": false,
  "debug": false
}' |
apify call ahmed_jasarevic/expedia-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/expedia-reviews-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/LbBKXS5XmmV8mDBBO/builds/1eSzc6a48YlBG5qM6/openapi.json
