# Expedia Hotel Search Scraper (`boncross/expedia-hotel-search`) Actor

Scrape every hotel Expedia and Hotels.com list for a destination and your dates. Just add place names and get hotel name, guest rating, nightly price, stay total with taxes, neighbourhood, photos and the booking link. $1.20 per 1,000 properties.

- **URL**: https://apify.com/boncross/expedia-hotel-search.md
- **Developed by:** [BonCross API](https://apify.com/boncross) (community)
- **Categories:** Travel
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.84 / 1,000 hotel-listeds

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Expedia Hotel Search Scraper

### What is Expedia Hotel Search Scraper?

Expedia Hotel Search Scraper returns up to 200 hotels for a destination and your dates, and each one has the nightly rate and the stay total as two separate numbers. Type a city, a neighbourhood, an airport or a landmark, pick the dates, and you get one row per hotel from Expedia or from Hotels.com.

Why people choose it over a general hotel scraper:

- You get the price the Expedia website shows. Checked against a live expedia.com page in the same minute, the totals matched on 90 of 90 hotels and the nightly rates on 92 of 92. The app can show a lower price on some hotels, and that isn't what you get here.
- Two prices per hotel, and a flag that tells you which one has tax in it. `priceTotal` is what a guest pays. `pricePerNight` is what the site displays, and `pricesIncludeTax` says whether tax is already inside it.
- It's quick. Five cities at 200 hotels each came back as 959 rows in 8 seconds.
- Expedia does the filtering. Property class, guest rating, nightly price, property type, meal plans, free cancellation, pay later and anything else on its filter panel are applied by the site, and a hotel it filters out is never charged.
- $1.20 per 1,000 hotels on the Free plan, $0.84 on Business, with proxy usage and platform usage included.

**BonCross Verified** means we tested this actor against the live site before release and kept the record:

- 47 of 47 live checks on its inputs and filters passed on 7 October 2026
- 12 destinations run the same day across Expedia and Hotels.com, in two Expedia markets: 199 hotels, none empty
- A guest-rating or distance sort Expedia does not apply gets an uncharged error row

What else it does:

- Searches several destinations and several date ranges in one run
- Reads Expedia in 40 country markets, each in its own currency, and Hotels.com in the United States
- Returns the guest rating out of 10, the site's word for it and the review count
- Gives you gallery photos and the booking link for each hotel, with your dates in it
- Sorts the way the site does, with eight orders to choose from
- Remembers which hotels earlier runs returned, and can hand you only the new ones
- States the currency each price is really in, whatever you asked for
- Tells you why in a row when a destination can't be resolved or a search isn't answered

People use it to build a priced hotel index for a city and refresh it on a schedule, to find the competitor set around a station or a landmark, and to watch how an area's prices move as a date approaches. It's also the usual first step before a rate-grid pull: pick the hotels worth it here, then pass their IDs to [Expedia Room Rates Scraper](https://apify.com/boncross/expedia-room-rates).

### What do you get for each hotel?

| | |
|---|---|
| 🏨 Hotel name and property ID | Site (Expedia or Hotels.com) |
| 📍 Neighbourhood or area | Distance from the landmark you searched |
| ⭐ Guest rating out of 10 | Rating in words, and review count |
| 💵 Price per night | 💰 Stay total with taxes and fees |
| Both prices as displayed | 💱 Currency the price is really in |
| Whether tax is in the nightly price | Pre-tax nightly price, where it is one |
| 📅 Check-in, check-out and nights | Adults, child ages and rooms priced |
| 🖼 Gallery photos | 🔗 Link to the booking page |
| Destination and market searched | Timestamp of the run |

### How to search Expedia hotels with it

There's nothing to install. You fill in a form and download a spreadsheet.

1. [Create a free Apify account](https://console.apify.com/sign-up) and open [Expedia Hotel Search Scraper](https://apify.com/boncross/expedia-hotel-search).
2. Type place names into Destinations, for example "Chicago", "Santorini" or "Yellowstone National Park".
3. Set the check-in and check-out dates. If you leave them empty, the stay starts 30 days from today for one night.
4. Choose how many hotels you want per destination (50 unless you change it) and any filters.
5. Click Start, then download the hotels as Excel, CSV, JSON, XML or HTML.

### How much does it cost?

| Event | Free plan | Starter | Scale | Business |
|---|---|---|---|---|
| `actor-start`, once per run | $0.002 | $0.002 | $0.002 | $0.002 |
| `destination-resolved`, per destination and date range the site answered | $0.0005 | $0.0005 | $0.0005 | $0.0005 |
| `hotel-listed`, per property returned | $0.0012 | $0.00108 | $0.00096 | $0.00084 |

Enterprise plans pay the Business price.

**$1.20 per 1,000 properties** on the Free plan, $0.84 on Business. That's the whole price: proxy usage and platform usage are included, and there's no proxy to set up.

- 20 destinations × 50 properties = 1,000 rows: $0.002 + 20 × $0.0005 + 1,000 × $0.0012 = **$1.212** ($0.852 on Business).
- One destination, 200 properties: $0.002 + $0.0005 + 200 × $0.0012 = **$0.2425** ($0.1705 on Business).

Apify's Free plan includes $5 of credits a month. That's about 80 searches of 50 hotels each, or roughly 4,000 hotels, before you pay anything.

You pay nothing for a destination the site never answered, or for one that couldn't be resolved to a place.

### ⬇️ Input

Give it place names. Each one is matched against the site's own place list: an exact name match wins, an airport name or code gives you the airport, and otherwise the most general place is used. "Kyoto" gives you the city, not Kyoto Station. If you want a station or a neighbourhood, name it.

You have two limits. "Maximum hotels per destination" (1 to 200, default 50) applies to each destination and date range separately. "Maximum rows for the whole run" stops the run once that many rows exist in total, and 0 means no limit.

#### A weekend in two cities

```json
{
  "destinations": ["Chicago", "Barcelona"],
  "checkIn": "2026-11-13",
  "checkOut": "2026-11-15",
  "maxHotelsPerDestination": 20
}
```

#### Cheapest first, well rated, under a nightly price

```json
{
  "destinations": ["Savannah"],
  "checkIn": "2026-11-13",
  "checkOut": "2026-11-15",
  "sortBy": "PRICE_LOW_TO_HIGH",
  "minRating": 8,
  "maxPricePerNight": 250,
  "maxHotelsPerDestination": 50
}
```

#### One destination across three stays, refundable with breakfast

```json
{
  "destinations": ["Cape Town"],
  "checkIn": "2026-11-13",
  "checkOut": "2026-11-15",
  "stays": ["2026-12-31_2027-01-02", "2027-02-10_2027-02-13"],
  "freeCancellationOnly": true,
  "mealPlans": ["breakfast"],
  "adults": 2,
  "rooms": 1
}
```

#### The same search on Hotels.com

```json
{
  "destinations": ["Chicago", "Lake Tahoe"],
  "site": "hotels",
  "checkIn": "2026-11-20",
  "checkOut": "2026-11-22",
  "maxHotelsPerDestination": 15
}
```

#### A scheduled run that returns only hotels you haven't seen

```json
{
  "destinations": ["Santorini"],
  "checkInDaysAhead": 30,
  "nights": 2,
  "dedupStoreName": "santorini-hotels",
  "onlyNew": true,
  "maxItems": 500
}
```

**Filters are Expedia's own.** "Minimum property class" keeps that class and above. "Minimum guest rating" uses the site's 7+ / 8+ / 9+ filter and then checks each row. The two nightly price bounds use its budget filter, in the market's currency. "Property types" and "Meal plans" (`breakfast`, `half_board`, `full_board`, `all_inclusive`) work the same way, as do "Only fully refundable properties" and "Only reserve now, pay later". For anything else on the panel, put its label in "More Expedia filters": "Pool", a neighbourhood, a hotel brand.

**Sorting.** You get the six orders on Expedia's menu plus two it accepts without showing: guest rating only, and price blended with its picks. Price orders follow the price the market puts first, which is the nightly rate in Japan and the stay total in the US.

**Guests and rooms.** Your party is the number of adults (1 to 14, default 2) plus one age per child. "Rooms" prices a booking of several rooms, not one room several times: the nightly rate stays per room and the stay total covers them all, which is how the site quotes it. Asking for more rooms can return fewer hotels, because a room with one unit left can't be booked twice. That's a real answer about availability.

**Market decides the money.** Expedia runs a separate site per country, 40 of them, and each quotes its own currency. Choose Japan and you get JPY, choose the United States and you get USD, for the same hotel on the same dates. Nothing is converted afterwards. With Market on Auto, a search uses the US site in USD. Where a market offers USD, that's the default for "Currency". Eleven of the forty markets offer a choice (the US offers ten currencies). Elsewhere the market's own money is used and the run log says so. Clear the field to take the market's own.

**Compare nightly prices inside one market only.** 18 of the 40 markets quote a nightly rate with tax already in it, and there the stay total is exactly the nightly rate times the nights. The other 22 add tax on top. `priceTotal` is what you'd pay either way, and that's the number to compare on.

**Hotels.com** works on the United States market only. Each run reads one site. Run it twice if you want to compare the two.

**Label language** is English unless you pick the market's own language, which translates the site's wording (such as `ratingText`) and leaves prices unchanged. "Include photos" is on by default. Turn it off for a smaller row.

#### For developers

- `maxHotelsPerDestination` is the per-search limit and `maxItems` the run-wide one. The price bounds are `minPricePerNight` and `maxPricePerNight`, the party is `adults` and `childrenAges`. `stays` takes `CHECKIN_CHECKOUT` lines, and every destination is searched for every stay.
- With no `checkIn`, the window is `checkInDaysAhead` (default 30) and `nights` (default 1, up to 30), counted from the day the run starts. That keeps a scheduled run pointed at a moving window.
- `filters` takes a label or `field=value`: `hotelName=Hilton` (a property-name search), `bedroomFilter=2`, `availableFilter=SHOW_AVAILABLE_ONLY`, `amenities=POOL`. A label matches whole words on that search's own panel, and the run log names the options it matched. The panel, with every option's code, is saved in the run's `SEARCH_OPTIONS` record. A label that matches nothing returns an error row for that search and no charge.
- `STATS` records, per destination, the place chosen, the alternatives Expedia offered, and Expedia's own total for the filtered search.
- `sortBy` values `REVIEW_RELEVANT` ("Guest rating + our picks") and `DISTANCE` are checked on every search against a recommended search asked at the same moment. If Expedia answers its default order, the search is asked again. One that stays unsorted returns an error row, uncharged, in place of the default order under the wrong name.
- `dedupStoreName` names the store that remembers what you've had, and `onlyNew` returns only properties no earlier run returned.
- `maxConcurrency` (default 4, up to 8) is how many searches are fetched at once. `delayMs` (default 0) pauses after each request, per parallel lane, and values above 2000 are treated as 2000. We'd leave both alone.
- If the platform moves or restarts a run part-way, it carries on where it stopped. Searches already in the dataset aren't repeated, delivered or billed a second time. That was tested by restarting a 10-city run part-way, and no row appeared twice.

### ⬆️ Output

You get one row per hotel. This one is from a Chicago search run on 7 October 2026:

```json
{
  "id": "15849775-2026-11-13-2026-11-15",
  "brand": "expedia",
  "market": "us",
  "hotelId": 15849775,
  "name": "Hampton Inn Chicago West Loop Fulton Market Area",
  "area": "Chicago",
  "distanceText": null,
  "rating": 9.2,
  "ratingScale": 10,
  "ratingText": "Wonderful",
  "reviewCount": 1000,
  "priceTotal": 593,
  "pricePerNight": 249,
  "pricesIncludeTax": false,
  "pricePerNightExcludingTax": 249,
  "priceText": "$249 nightly",
  "priceTotalText": "$593 total",
  "currency": "USD",
  "checkIn": "2026-11-13",
  "checkOut": "2026-11-15",
  "nights": 2,
  "photo": "https://images.trvl-media.com/lodging/16000000/15850000/15849800/15849775/12da6fa3.jpg?impolicy=fcrop&w=456&h=286",
  "photos": ["https://images.trvl-media.com/lodging/16000000/15850000/15849800/15849775/12da6fa3.jpg?impolicy=fcrop&w=456&h=286"],
  "url": "https://www.expedia.com/Chicago-Hotels-Hampton-Inn-Chicago-Downtown-West-Loop.h15849775.Hotel-Information?chkin=2026-11-13&chkout=2026-11-15",
  "destination": "Chicago",
  "regionId": "829",
  "regionName": "Chicago, Illinois, United States of America",
  "adults": 2,
  "childrenAges": [],
  "rooms": 1,
  "scrapedAt": "2026-10-07T20:26:23.217Z"
}
```

Things worth knowing before you build on it:

- `pricePerNight` and `priceTotal` aren't multiples of each other. Two nights at $249 comes to $593 here, not $498, because the US market adds taxes and fees on top. Use `priceTotal` to compare costs and `pricePerNight` for display.
- `priceTotal` always includes taxes and fees. `pricesIncludeTax` tells you whether `pricePerNight` does too. It's `true` in markets such as the UK, Germany and France, and `false` in markets such as the US and Japan. Where it's `false`, the nightly price is also in `pricePerNightExcludingTax`. On 2 October 2026 it was filled on every priced row in the US, Japan, the UK, Germany and France, in English and in the site's own language. It's null on a hotel with no price.
- `hotelId` joins these rows to the room rates, reviews and hotel details actors listed at the end.
- `id` combines the property ID and the stay dates, and one hotel on two date ranges gives you two distinct rows. `regionId` is the resolved destination, which makes a run reproducible without resolving the name again.
- `distanceText` is filled when your destination is a landmark or a station, where there's something to measure from ("2.2 km from Kyoto Station"). It's null for a whole-city search.
- A destination that couldn't be resolved, or a search the site never answered, is written as a row with an `error` and is never charged.

### How many hotels can you get, and how fast?

One request covers one destination and one date range and returns the whole list at once, up to **200 properties per request**. Several destinations and date ranges are searched at the same time. Measured on Apify on 2 October 2026:

| Run | Rows | Run time |
|---|---|---|
| Kyoto, one stay, 15 properties | 14 to 15 | 4 to 7 s |
| Tokyo, Osaka and Kyoto, two stays each, 50 properties per search | 291 to 292 | 8 s |
| Tokyo, Osaka, Kyoto, Sapporo and Fukuoka, 200 properties each | 959 | 8 s |
| 10 Japanese cities, 100 properties each | about 965 | 8 to 10 s |

A run over 20 destinations at 50 properties each returns roughly 1,000 rows, and thousands of destination-and-date searches fit in the default one-hour run limit.

Not every hotel has every field. On a 20-property Tokyo sample, name, price, stay total, photo and link were present on all 20, and the guest rating on 17. A hotel with too few reviews has no rating yet.

### FAQ

#### Are these the prices the website shows?

For Expedia, they are: each price is the one the Expedia website shows a traveller in a browser for that market and those dates. The app can show a lower price on some properties, because it has app-only discounts, and those aren't returned. Member-only rates aren't included either. You get what an anonymous visitor sees.

#### How do I search a neighbourhood, a station or an airport?

Name it. A neighbourhood, a station such as "Kyoto Station", a landmark such as "Yellowstone National Park" or an airport code is resolved on its own. A bare city name gives you the whole city.

#### Why don't the nightly price and the stay total divide evenly?

The total includes taxes and fees, and in 22 of the 40 markets the nightly price doesn't. Both numbers come from the site, and neither is derived from the other.

#### Why did my sorted search return an error row?

Expedia at times answers its default order when asked for "Guest rating + our picks" or "Distance". The actor checks for that on each search and asks again. If the list still isn't sorted, you get an error row and no charge, which is better than the default order labelled as something else. Run it again later, or use one of the price orders, which aren't affected.

#### Where did the amenities go?

Expedia's result cards no longer list them: 0 of 220 cards measured on three markets had any. [Expedia Hotel Details Scraper](https://apify.com/boncross/expedia-hotel-details) returns each property's amenities, along with the star class and the coordinates, which a search row doesn't have either.

#### Can I search Hotels.com instead?

On the United States market, set Site to Hotels.com. Hotels.com Japan isn't supported. Ask for it and the run returns one error row that says so, at no charge. Expedia Japan (expedia.co.jp) is fully supported.

#### How do I get more than 200 hotels for a city?

200 per destination and date is what the site's own list returns. Search the city's neighbourhoods one by one to go deeper. A hotel returned by two searches for the same dates has the same `id`, which makes the overlap easy to drop.

#### Do I need proxies or an Expedia account?

Neither. There's no login, no cookie of yours is used, and proxy usage is included in the price with nothing to set up.

#### Is it legal to scrape Expedia and Hotels.com?

Everything it reads is what Expedia and Hotels.com show a visitor who isn't signed in. There's no account access and no private data involved. Collecting public search results this way is generally lawful in the UK, EU and US. How you use what you collect is your responsibility, including under GDPR where data identifies a person, and under the site's own terms.

#### What are the limits?

- A nightly price from one market can't be set against another's. Use the stay total.
- Star ratings aren't returned. The site publishes no star class on a search result. "Minimum property class" is still applied by the site, and the guest rating out of 10 is returned.
- Coordinates aren't on a search row.
- A property with too few reviews has a `null` rating, not zero.
- A Hotels.com search the site doesn't answer returns an error row and costs nothing. The row says Hotels.com didn't answer on this run. It's never an empty result.
- Hotels.com US search prices can differ from hotels.com on some hotels. Measured side by side, 10 of 77 hotels were priced differently, by up to about 11%, most of them higher. Expedia prices aren't affected.
- Most markets quote one currency only. Each row states the currency its price is actually in.

### Run it on a schedule or from your own code

A daily price index needs no code. Create an Apify Schedule, leave the dates empty and set days ahead, and the window moves with the calendar. A webhook can fire when a run finishes, and the rows can go to Google Sheets, Slack, Make, Zapier or Airbyte.

From code, one call runs a search and returns the hotels:

```bash
curl -X POST "https://api.apify.com/v2/acts/boncross~expedia-hotel-search/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"destinations":["Chicago"],"checkIn":"2026-11-13","checkOut":"2026-11-15"}'
```

An AI agent can do the same through the Apify MCP server (`mcp.apify.com`), where the actor appears as `boncross/expedia-hotel-search`. Ask it for the cheapest well-rated hotels in a city for your dates and it has priced rows to answer from.

### More from BonCross

- [Expedia Hotel Details Scraper](https://apify.com/boncross/expedia-hotel-details): The full property record from Expedia and Hotels.com.
- [Expedia Reviews Scraper](https://apify.com/boncross/expedia-reviews): Expedia guest reviews for any hotel, including hotels given as Hotels.com links.
- [Expedia Room Rates Scraper](https://apify.com/boncross/expedia-room-rates): Every room Expedia and Hotels.com are selling for a hotel and your dates.
- [Google Hotels Prices Scraper](https://apify.com/boncross/google-hotels-prices): Google Hotels price comparisons for any hotel and stay.
- [Google Hotels Search Scraper](https://apify.com/boncross/google-hotels-search): Google Hotels prices for a whole city or map area.
- [Hilton Hotel Details Scraper](https://apify.com/boncross/hilton-hotel-details): Everything a Hilton property publishes about itself: address, coordinates, phone,…

### Your feedback

Seen a price that doesn't match the Expedia page, or a destination that resolves to the wrong place? Open an issue on this actor's Issues tab with the destination, dates and market you ran. We read each report and answer there.

# Changelog

This Actor's version history is a separate document: https://apify.com/boncross/expedia-hotel-search/changelog.md

# Actor input Schema

## `destinations` (type: `array`):

Place names to search: a city, neighbourhood, airport, station or landmark. For example Chicago, Santorini or Yellowstone National Park.

## `site` (type: `string`):

Which site to read. Links you paste already name their own site, so this only applies to bare property IDs. Hotels.com is read on the United States site only.

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

Stop once this many rows have been returned, across every destination and date. 0 means no limit.

## `maxHotelsPerDestination` (type: `integer`):

How many properties to return for each destination and stay.

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

Check-in date as YYYY-MM-DD, for example 2026-11-10.

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

Check-out date as YYYY-MM-DD, for example 2026-11-12.

## `checkInDaysAhead` (type: `integer`):

Used only when no check-in date is given. The stay starts this many days from the day the run starts, which keeps a scheduled run pointed at a moving window.

## `nights` (type: `integer`):

Length of the stay when the dates are computed from "days ahead" rather than given.

## `stays` (type: `array`):

More date ranges to price, one per line as CHECKIN_CHECKOUT, for example 2026-11-10_2026-11-12. Each one is fetched for every hotel.

## `adults` (type: `integer`):

Number of adults in the room.

## `childrenAges` (type: `array`):

One age per child, in years. Leave empty for an adults-only stay.

## `rooms` (type: `integer`):

How many rooms to price, each with the same guests. The nightly rate stays per room and the stay total covers them all, which is how the site quotes a multi-room booking.

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

Expedia's orderings: the six on its Sort menu, plus two it accepts without showing them (guest rating only, and price blended with its picks). Price sorts follow the price the market shows first: the nightly rate in Japan, the stay total in the US. The guest-rating-plus-picks and distance orders are checked on every search: when Expedia answers its default order instead, the search is asked again, and one that stays unsorted returns an error row and is not charged.

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

Drop properties rated below this, out of 10. Expedia's own 7+ / 8+ / 9+ filter is applied first and each row is then checked. 0 means no limit.

## `minPricePerNight` (type: `number`):

Expedia's own budget filter, in the market's currency, then checked on each row. Rows without a price are left out when a price limit is set. 0 means no limit.

## `maxPricePerNight` (type: `number`):

Expedia's own budget filter, in the market's currency, then checked on each row. Rows without a price are left out when a price limit is set. 0 means no limit.

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

Expedia's property class filter: 3 keeps 3, 4 and 5-star properties. 0 keeps everything.

## `propertyTypes` (type: `array`):

Keep only these kinds of property, by the names on Expedia's Property type filter: Hotel, Hostel, Ryokan, Apartment, Capsule hotel and so on. What is on offer varies by destination.

## `mealPlans` (type: `array`):

Keep properties offering any of these, as Expedia's Meal plans filter.

## `freeCancellationOnly` (type: `boolean`):

Expedia's "Fully refundable property" filter.

## `payLaterOnly` (type: `boolean`):

Expedia's "Reserve now, pay later" filter.

## `filters` (type: `array`):

Anything else on Expedia's filter panel, by its label ("Pool", "City view", "Roll-in shower", "Shinjuku", "Hilton") or as field=value ("amenities=POOL"). Labels are matched on each search's own panel, which every run saves with its codes in the SEARCH_OPTIONS record; the run log says which options a label matched.

## `includePhotos` (type: `boolean`):

Add the property's gallery image links to each row.

## `market` (type: `string`):

Which country's site to read, which is what decides the currency: each one quotes its own money and will not quote another's. Auto follows each pasted link's own site, so an expedia.se link is quoted in SEK, and a place name uses the US site, in USD. Some markets quote a nightly rate that already includes tax and others add it on top, so a nightly price is only comparable within one market: compare on the stay total.

## `currency` (type: `string`):

Three-letter currency code, default USD. Only currencies the chosen region offers are accepted: 11 regions offer a choice, the rest quote one currency only. Anything else is ignored and the region's own currency is used, which the rows report. Clear it for the region's own currency.

## `language` (type: `string`):

Language of the room names, board and cancellation wording. Prices are unaffected: they always follow the region. English is recommended: with the region's own language the refundable and meal-included flags cannot be determined and come back empty.

## `dedupStoreName` (type: `string`):

Name of a storage area to remember the properties already returned. Leave empty to remember nothing.

## `onlyNew` (type: `boolean`):

Return only properties that no earlier run returned. Needs a memory store.

## `delayMs` (type: `integer`):

Pause after each request, per parallel lane. 0 runs at full speed; raise it only to make a large run gentler. Values above 2000 are treated as 2000.

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

How many searches are fetched at once. Higher is faster; the default suits almost every run.

## Actor input object example

```json
{
  "destinations": [
    "Chicago",
    "Barcelona",
    "Cape Town"
  ],
  "site": "expedia",
  "maxItems": 0,
  "maxHotelsPerDestination": 50,
  "checkIn": "2026-11-10",
  "checkOut": "2026-11-12",
  "checkInDaysAhead": 30,
  "nights": 1,
  "stays": [
    "2026-11-10_2026-11-12",
    "2026-12-24_2026-12-27"
  ],
  "adults": 2,
  "childrenAges": [
    "7",
    "3"
  ],
  "rooms": 1,
  "sortBy": "RECOMMENDED",
  "minRating": 0,
  "minPricePerNight": 0,
  "maxPricePerNight": 0,
  "minStars": 0,
  "propertyTypes": [],
  "mealPlans": [],
  "freeCancellationOnly": false,
  "payLaterOnly": false,
  "filters": [],
  "includePhotos": true,
  "market": "auto",
  "currency": "USD",
  "language": "english",
  "onlyNew": false,
  "delayMs": 0,
  "maxConcurrency": 4
}
```

# Actor output Schema

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

Expedia hotel search: every row the run returned.

## `stats` (type: `string`):

Counts for the run: what was resolved, fetched, filtered and returned.

# 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 = {
    "destinations": [
        "Chicago"
    ],
    "rooms": 1
};

// Run the Actor and wait for it to finish
const run = await client.actor("boncross/expedia-hotel-search").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 = {
    "destinations": ["Chicago"],
    "rooms": 1,
}

# Run the Actor and wait for it to finish
run = client.actor("boncross/expedia-hotel-search").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 '{
  "destinations": [
    "Chicago"
  ],
  "rooms": 1
}' |
apify call boncross/expedia-hotel-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,boncross/expedia-hotel-search"
        }
    }
}
```

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/SUMjymqcL3a3zQHei/builds/HxhbtGLLgn3neSAUB/openapi.json
