# Expedia Hotel & Flight Scraper – Prices, Reviews & Fares (`rl1987/expedia-api-scraper`) Actor

Scrape Expedia hotel search and flight search in one Actor. Hotel rows carry price, 0-10 guest rating, review count, amenities, photo gallery and mandatory fees; flight rows carry fare, airlines, route, times, duration and stops. No Expedia account or API key needed.

- **URL**: https://apify.com/rl1987/expedia-api-scraper.md
- **Developed by:** [R.L.](https://apify.com/rl1987) (community)
- **Features:** Limited permissions
- **Stats:** 14 total users, 7 monthly users, 99.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.12 / 1,000 hotels

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 & Flight Scraper — hotel prices, ratings, amenities, photos, guest reviews and flight fares

**Expedia Hotel & Flight Scraper** — Scrapes Expedia hotel search with prices, ratings, amenities, photos and guest reviews, plus flight search with fares and journeys, from the Expedia mobile GraphQL API. Read-only public travel data. It reads Expedia's own API directly, so it's **fast, reliable and complete** — no flaky HTML parsing, no headless browser. Export to **JSON, CSV, Excel, or an API**.

***

### What does this Expedia scraper do?

It runs in one of four modes, chosen with `searchType`:

- **`hotels`** — give it a place (`Copenhagen`, `Vilnius Old Town`, an airport code) and a date
  range. You get one row per property: name, Expedia hotel id and URL, the price as Expedia shows
  it plus a parsed number and currency, a lead image, and — on request — the 0–10 guest rating,
  review count, amenities, the photo gallery, mandatory fees and recent guest reviews.
- **`flights`** — give it two IATA codes and a date. You get one row per offer: fare, airlines,
  the route, departure and arrival times, duration in minutes, stop count, trip type and Expedia's
  offer identifier.
- **`hotel-details`** — give it hotel IDs instead of a destination. You get the amenities, photo
  gallery, 0–10 guest rating and mandatory fees for exactly those hotels, with no search in front
  of it and no hotel search rows on the bill.
- **`reviews`** — give it hotel IDs and how many reviews you want. You get **one row per review**
  — score, title, text, date, author and stay length — each carrying the `hotel_id` to join back
  on. Charged per review and nothing else.

Each mode reads its own input fields and ignores the others'. The two by-ID modes take IDs from
an earlier run of this Actor (the `url` or `hotel_id` column) or from your own data.

- **No code required** — set your input, click **Start**, download your data.
- **Fast & accurate** — reads Expedia's own private API and returns structured JSON, not scraped HTML.
- **Rich, structured data** — every field below, clean and ready to use.
- **Deep hotel detail on demand** — amenities, the full photo gallery, rating and mandatory
  fees, fetched only when you ask for them.
- **Guest reviews** — text, score, date, author and stay length per review.
- **Flights too** — switch `searchType` to `flights` for fares, airlines and journey times.
- **Already know the hotels?** `hotel-details` and `reviews` take hotel IDs and skip the search
  entirely, so you are not charged for search rows you did not ask for.
- **Transparent pay-per-event pricing** — you are charged for what a run delivers; the
  **Pricing** tab lists the events, their current prices, and whether Apify platform
  usage is billed on top.
- **Export anywhere** — JSON, CSV, Excel, XML, or pull it live via the Apify API.

***

### What can you do with Expedia data?

- **Rate-parity and price monitoring** — re-run a city and date range on a schedule and diff `price_total`.
- **Competitive set analysis** — pull every property in a neighbourhood with its rating and review count.
- **Amenity and fee research** — see which properties advertise what, and what mandatory fees they disclose.
- **Review mining** — collect guest review text, score and date for sentiment work.
- **Airfare tracking** — watch fares, airlines and stop counts on a route over time.

***

### What do the fields actually mean?

- **Hotel prices are display strings.** Expedia returns a price as text (`"$1,277 total"`), never a number. Rows keep that original string in `price_display` **and** a parsed numeric `price_total` with `currency`, so they sort correctly without losing the "total" / per-night wording — which changes what the number means. Flight fares come back the same way but without the suffix (`"$189"`).
- **`rating` is out of 10.** It is parsed from Expedia's own label, which `rating_text` keeps verbatim: `"8.6 out of 10"`. Some properties genuinely have no rating summary; those rows carry `rating: null` rather than a fabricated value.
- **`destination` is Expedia's resolved region, not your input.** Type `Vilnius Old Town` and rows come back labelled `Vilnius Old Town, Vilnius, Vilnius County, Lithuania`, with `region_id` naming the region Expedia matched. In flights mode `destination` is just the IATA code you asked for and `region_id` is null.
- **`fees`** is Expedia's mandatory-fee disclosure, flattened from HTML to plain text — the "Fee for buffet breakfast…" kind of copy, not a number.
- **`amenities`** and **`images`** are deduplicated and capped at 40 entries each. Amenities are Expedia's own strings, which mix facilities with property facts (`24-hour front desk`, `2 restaurants`, `10 floors`, `1,453 square feet of conference space`).
- **`route` / `itinerary` / `trip_type` / `operated_by`** are flight-only display strings, e.g. `Seattle (SEA) - New York (JFK)`, `11:50am - 8:28pm`, `One way per traveler`, `Alaska Airlines operated by ALASKA`. `duration_minutes` and `stops` are parsed out of Expedia's `"5h 36m (Nonstop)"` wording so they are usable as numbers.
- **`offer_id`** is Expedia's opaque fare token for a flight offer. It identifies the offer within the search; it is not a stable long-term id.
- **Unused fields are `null`, not absent.** Hotel rows carry the flight columns as nulls and vice versa, so a mixed export keeps one consistent shape. The dataset also ships separate **Hotels** and **Flights** views if you'd rather see only the relevant columns.

***

### How do I scrape Expedia? (3 steps)

1. **Set your mode** — `hotels` with a `destination`, or `flights` with two IATA codes.
2. **Pick options** — dates, `adults`, `includeDetails`, `includeReviews`, and a `maxItems` cap. Leave the proxy alone; see **Do I need a proxy?** below.
3. **Run & export** — click **Start**, then download the dataset as JSON/CSV/Excel or fetch it via the API.

***

### What input does it take?

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `searchType` | enum | `hotels` | Which mode to run — one of `hotels`, `flights`, `hotel-details`, `reviews`. Each mode reads its own fields; the others are ignored. |
| **Hotels** | | | |
| `destination` | string | – | A place name: a city, area or neighbourhood, e.g. `Copenhagen` or `Vilnius Old Town`. An airport code works too. **Required** in hotels mode. |
| `checkIn` | string | – | Check-in date. A date, or a relative value like `30 days`. Empty = 30 days from today. |
| `checkOut` | string | – | Check-out date. Empty = 3 nights after check-in. Must be after `checkIn`. |
| `includeDetails` | boolean | `false` | Amenities, photo gallery, rating and fees per hotel. Four extra API calls per hotel — one per surface — so noticeably slower. |
| `includeReviews` | boolean | `false` | Attach recent guest reviews to each hotel. One extra API call per hotel. |
| `reviewsPerHotel` | integer | `5` | Reviews per hotel when reviews are on, and in `reviews` mode. `0` fetches none and charges nothing for them (hotels mode only). Expedia returns at most 50, whatever is asked for. |
| **Flights** | | | |
| `flightOrigin` | string | – | Origin airport IATA code, e.g. `SEA`. **Required** in flights mode. |
| `flightDestination` | string | – | Destination airport IATA code, e.g. `JFK`. **Required** in flights mode. |
| `departureDate` | string | – | Outbound date, absolute or relative. Empty = 30 days from today. |
| `returnDate` | string | – | Return date. Empty = one-way. |
| **Hotel details / Reviews (by hotel ID)** | | | |
| `hotelIds` | array | – | Hotel IDs or Expedia hotel URLs. **Required** by `hotel-details` and `reviews`. Accepts a bare ID (`45263901`), the `url` this Actor outputs, or any Expedia hotel URL. Up to 200 per run. |
| **Both** | | | |
| `adults` | integer | `2` | Adult guests or passengers, 1–14. Expedia returns the same results for every occupancy of 14 or more, so larger values are rejected rather than billed as something they are not. |
| `maxItems` | integer | `100` | 0 = no limit, but see the 200-per-search ceiling under **Limits**. |
| `proxyConfiguration` | object | Apify residential | See **Do I need a proxy?** below — residential is enforced, not merely the default. |

#### Example input

```jsonc
{
  "searchType": "hotels",
  "destination": "Copenhagen",
  "checkIn": "2026-12-05",
  "checkOut": "2026-12-08",
  "adults": 2,
  "includeDetails": false,
  "includeReviews": false,
  "reviewsPerHotel": 5,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

***

### What does a row look like?

A hotel row:

```jsonc
{
  "type": "hotel",
  "destination": "Copenhagen City Centre, Copenhagen, Hovedstaden, Denmark",
  "region_id": "6051779",
  "checkin": "2026-12-05",
  "checkout": "2026-12-08",
  "hotel_id": "45263901",
  "hotel_name": "WIDE Hotel",
  "url": "https://www.expedia.com/h45263901.Hotel-Information",
  "price_display": "$707 total",
  "price_total": 707.0,
  "currency": "USD",
  "image": "https://images.trvl-media.com/lodging/46000000/45270000/45264000/45263901/49f6b716.jpg?impolicy=resizecrop&ra=fit&rw=455&rh=455",
  "rating": 9.0,
  "rating_text": "9.0 out of 10",
  "review_count": 1989,
  "amenities": [
    "24-hour business center",
    "24-hour front desk",
    "24-hour gym",
    "24-hour roundtrip airport shuttle on request for a surcharge",
    "…+35 more"
  ],
  "images": [
    "https://images.trvl-media.com/lodging/46000000/45270000/45264000/45263901/49f6b716.jpg?impolicy=resizecrop&rw=1200&ra=fit",
    "…+39 more"
  ],
  "fees": "Fee for buffet breakfast: approximately DKK 255 for adults and DKK 160 for children\n\nAirport shuttle fee: DKK 1500 per vehicle (one-way, maximum occupancy 4)…",
  "reviews": [
    {
      "title": "Excellent",
      "text": "Beautiful hotel in a great location.",
      "rating": 10.0,
      "date": "Aug 20, 2026",
      "author": "Konrad",
      "stay_info": "Stayed 4 nights in Aug 2026"
    }
  ]
}
```

A flight row:

```jsonc
{
  "type": "flight",
  "origin": "SEA",
  "destination": "JFK",
  "departure_date": "2026-10-27",
  "return_date": null,
  "trip_type": "One way per traveler",
  "route": "Seattle (SEA) - New York (JFK)",
  "itinerary": "11:50am - 8:28pm",
  "airlines": ["Delta"],
  "operated_by": null,
  "duration_minutes": 338,
  "stops": 0,
  "price_display": "$189",
  "price_total": 189.0,
  "currency": "USD",
  "offer_id": "v5-sos-89d379265ca94de8accd7c6e6feeede1-134-1~8.S.1~…"
}
```

***

### Which fields are in the dataset?

Hotel rows (`type: "hotel"`), the dataset's **Hotels** view:

| Field | Type | Description |
| --- | --- | --- |
| `type` | text | Record type |
| `destination` | text | Expedia's resolved region label |
| `region_id` | text | Region ID Expedia matched |
| `checkin` | text | Check-in |
| `checkout` | text | Check-out |
| `hotel_id` | text | Hotel ID |
| `hotel_name` | text | Hotel |
| `url` | link | URL |
| `price_display` | text | Price (as shown) |
| `price_total` | number | Price |
| `currency` | text | Currency |
| `image` | image | Lead image |
| `rating` | number | Guest rating out of 10 |
| `rating_text` | text | Rating as Expedia labels it |
| `review_count` | number | Reviews |
| `amenities` | array | Amenities (max 40) |
| `images` | array | Photo gallery (max 40) |
| `fees` | text | Mandatory-fee disclosure |
| `reviews` | array | Guest reviews |

Flight rows (`type: "flight"`), the dataset's **Flights** view:

| Field | Type | Description |
| --- | --- | --- |
| `type` | text | Record type |
| `origin` | text | Origin IATA code |
| `destination` | text | Destination IATA code |
| `departure_date` | text | Departure date |
| `return_date` | text | Return date, null for one-way |
| `trip_type` | text | Trip type |
| `route` | text | Route |
| `itinerary` | text | Times |
| `airlines` | array | Airlines |
| `operated_by` | text | Operating carrier |
| `duration_minutes` | number | Duration (min) |
| `stops` | number | Stops |
| `price_display` | text | Price (as shown) |
| `price_total` | number | Price |
| `currency` | text | Currency |
| `offer_id` | text | Offer ID |

***

### Which mode should I use?

| You want | Mode | What it charges |
| --- | --- | --- |
| Hotels for a place and some dates | `hotels` | one hotel row per result |
| …with amenities, photos, rating, fees | `hotels` + `includeDetails` | hotel row **+** hotel details |
| …with guest reviews attached | `hotels` + `includeReviews` | hotel row **+** per review |
| Details for hotels you already know | `hotel-details` | hotel details only |
| Reviews for hotels you already know | `reviews` | per review only |
| Flight fares for a route | `flights` | one flight row per offer |

The two by-ID modes exist so you do not pay twice. If you already have hotel IDs — from an
earlier run of this Actor, or from your own data — they fetch only what you asked for, with no
destination search and no hotel search rows on the bill. The data and the price per unit are
identical either way; only the search row differs.

Both take IDs in whatever form you have them:

```json
{
  "searchType": "reviews",
  "hotelIds": ["45263901", "https://www.expedia.com/h9536.Hotel-Information"],
  "reviewsPerHotel": 10
}
```

Rows carry a `type` column saying which mode produced them — `hotel`, `flight`,
`hotel_detail` or `review` — so a mixed dataset can be filtered and a bill line reconciled
against the rows that earned it. The two by-ID modes emit only the columns they can fill, so a
CSV export is not padded with empty hotel or flight columns:

| Mode | Columns |
| --- | --- |
| `hotel-details` | `type`, `hotel_id`, `hotel_name`, `url`, `rating`, `rating_text`, `amenities`, `images`, `fees` |
| `reviews` | `type`, `review_id`, `hotel_id`, `url`, `hotel_review_count`, `review_rating`, `review_title`, `review_text`, `review_date`, `review_author`, `review_stay_info` |

In `reviews` mode `maxItems` counts **review rows**, and `reviewsPerHotel` bounds how many are
taken from each hotel — so `maxItems: 10` stops after ten reviews rather than paying to fetch
every hotel you listed.

***

### How much does it cost?

The current price of every event is on the **Pricing** tab of this Actor's page in Apify Store. That tab is generated from the Actor's own pricing record, so it is always current, and your plan's rung is applied automatically. A figure repeated here would be a second copy that drifts out of date.

You can cap what any single run may spend with **Max total charge**.

### How do I run it from my own code?

Run it programmatically with the [Apify API](https://docs.apify.com/api/v2):

```bash
curl -X POST "https://api.apify.com/v2/acts/expedia-api-scraper/runs?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
  "searchType": "hotels",
  "destination": "Copenhagen",
  "adults": 2,
  "includeDetails": false,
  "includeReviews": false,
  "reviewsPerHotel": 5,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}'
```

Or with the Apify CLI: `apify call expedia-api-scraper -i input.json -o`.

***

### What are the limits?

**200 properties per search.** Expedia's own search returns at most 200 properties for a region
however large it is — measured identically for Berlin, Paris, London and New York. `maxItems` above
that cannot be met by one run, and the log says so rather than leaving you to guess whether you hit
a ceiling or a small region. To go deeper, search neighbourhoods rather than the whole city
(`Vilnius Old Town` rather than `Vilnius`); each is its own region with its own 200.

**Occupancy is meaningful to 13.** From 14 adults up, Expedia returns the same result set whatever
the number, so `adults` is capped at 14.

**Up to 50 reviews per hotel.** `reviewsPerHotel` above that is clamped — Expedia will not return
more.

***

### FAQ

**Do I need an Expedia account or API key?**

No. The actor talks to Expedia's mobile API for you — you only need an Apify account.

**Do I need a proxy?**

You get one whether you ask or not. Expedia's edge throttles by exit IP and throttles Apify's own
egress hard, so a run with no proxy is answered with `Provisioned request rate has been exceeded`
almost immediately. The actor therefore treats Apify **residential** as a floor: if
`proxyConfiguration` is missing, or selects Apify Proxy without the `RESIDENTIAL` group, it is
corrected to residential and the substitution is logged. A custom `proxyUrls` list is used exactly
as given.

One residential exit is held for as long as it keeps working, and replaced the moment Expedia
rate-limits it (403/429/503) or the tunnel through it fails. That is deliberate: re-minting a
session per request means a cold TLS handshake every time and throws away good exits along with
bad ones.

**What if Expedia is throttling?**

The run finishes **SUCCEEDED** with a status message saying so, rather than failing — throttling is
environmental and not a defect in the actor. Rows already collected are kept. Optional enrichment
(details, reviews) is dropped for the rest of the run if it fails on three hotels running; the
listing rows, which are the part worth having, still land, and the log names the surface it gave up
on.

**What happens with bad input?**

The run finishes **SUCCEEDED** with a status message naming the field and the problem — a run that
could never have worked is yours to fix, not a failure of the actor. Rejected before any request:
a missing `destination` or IATA code, a malformed IATA code, a `checkOut` on or before `checkIn`, a
date in the past, `adults` outside 1–14, a negative `maxItems`, and a `destination` carrying
characters no place name has. That last one matters because Expedia answers those with
`403 Access Denied` rather than a result.

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

Run one search per neighbourhood instead of one per city. Expedia treats `Vilnius Old Town` and
`Vilnius` as different regions, each with its own 200-property ceiling, so several neighbourhood
searches reach deeper into a city than one city-wide search ever can.

**Which currency are the prices in?**

Whatever Expedia serves the run, parsed out of the display string into `currency` — `USD` on the
runs measured here. `price_display` always keeps the original text, so you can see exactly what
Expedia said even if the symbol is one the parser doesn't map.

**Can I schedule it?**

Yes — use Apify's scheduler for recurring runs and a webhook to push each finished dataset onward.
For hotels, join runs on `hotel_id` plus `checkin`/`checkout`, since the price only means anything
for a specific stay.

**Is scraping this legal?**

You are responsible for how you use the data. Scrape only public product data and comply with Expedia's Terms and applicable law (e.g. GDPR/CCPA for personal data).

***

### How does it work under the hood?

The actor impersonates Expedia's current Android app — app version and an okhttp TLS fingerprint,
via impit — and calls the same private GraphQL surfaces the app does: region resolution, property
search, and one call each for amenities, gallery, rating summary and fees when details are on, plus
one for reviews. Resolved region ids are cached so a retry does not re-resolve them. Responses are
normalised into the flat records above. No browser, no HTML scraping — just clean, structured data.

***

### Good to know

- Scrape only public product data and respect Expedia's Terms of Service and robots policy.
- For personal data, comply with GDPR/CCPA and applicable law — you are the data controller.
- Fields can be `null` when Expedia doesn't expose them for a given record.

***

### Found this useful?

Give the **Expedia Hotel & Flight Scraper** a star on Apify and check out my other `apify-*-api-scraper` actors.

# Actor input Schema

## `searchType` (type: `string`):

Which search to run. The two by-ID modes skip the search entirely: give them hotel IDs and they fetch only what you asked for, so no hotel search rows are charged.

## `destination` (type: `string`):

HOTELS MODE. A place name, e.g. "Copenhagen" or "Copenhagen City Centre". Resolved through Expedia's own location search.

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

Check-in date. Pick a date or use a relative value like "30 days". Empty = 30 days from today.

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

Check-out date. Empty = 3 nights after check-in.

## `includeDetails` (type: `boolean`):

Fetch amenities, photo gallery, rating and fees per hotel. One extra API call each, so slower.

## `includeReviews` (type: `boolean`):

Attach recent guest reviews to each hotel.

## `flightOrigin` (type: `string`):

FLIGHTS MODE. Origin airport IATA code, e.g. SEA.

## `flightDestination` (type: `string`):

Destination airport IATA code, e.g. JFK.

## `departureDate` (type: `string`):

Outbound date. Pick a date or use a relative value like "30 days". Empty = 30 days from today.

## `returnDate` (type: `string`):

Return date. Leave empty for a one-way search.

## `hotelIds` (type: `array`):

Required by the <b>Hotel details</b> and <b>Hotel reviews</b> modes, ignored by the others. Accepts a numeric Expedia hotel ID (<code>45263901</code>) or any Expedia hotel URL, including the <code>url</code> this Actor outputs. Run a hotel search first if you need to find IDs by destination. Up to 200 per run.

## `reviewsPerHotel` (type: `integer`):

How many guest reviews to fetch per hotel. Used by <b>Hotel reviews</b> mode, and by <b>Hotel search</b> when reviews are enabled there. Expedia returns at most 50 whatever is asked for. Set 0 in hotel search mode to fetch no reviews at all - nothing is requested and nothing is charged for them.

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

Adult guests (hotels) or passengers (flights).

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

0 = all results.

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

Route requests through a proxy (Apify Proxy by default).

## Actor input object example

```json
{
  "searchType": "hotels",
  "destination": "Copenhagen",
  "checkIn": "",
  "checkOut": "",
  "includeDetails": false,
  "includeReviews": false,
  "flightOrigin": "",
  "flightDestination": "",
  "departureDate": "",
  "returnDate": "",
  "hotelIds": [
    "45263901",
    "https://www.expedia.com/h9536.Hotel-Information"
  ],
  "reviewsPerHotel": 5,
  "adults": 2,
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "destination": "Copenhagen",
    "checkIn": "",
    "checkOut": "",
    "flightOrigin": "",
    "flightDestination": "",
    "departureDate": "",
    "returnDate": "",
    "hotelIds": [
        "45263901",
        "https://www.expedia.com/h9536.Hotel-Information"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("rl1987/expedia-api-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 = {
    "destination": "Copenhagen",
    "checkIn": "",
    "checkOut": "",
    "flightOrigin": "",
    "flightDestination": "",
    "departureDate": "",
    "returnDate": "",
    "hotelIds": [
        "45263901",
        "https://www.expedia.com/h9536.Hotel-Information",
    ],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("rl1987/expedia-api-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 '{
  "destination": "Copenhagen",
  "checkIn": "",
  "checkOut": "",
  "flightOrigin": "",
  "flightDestination": "",
  "departureDate": "",
  "returnDate": "",
  "hotelIds": [
    "45263901",
    "https://www.expedia.com/h9536.Hotel-Information"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call rl1987/expedia-api-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,rl1987/expedia-api-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/ESZl7Jho36RKkmXnt/builds/eTPn0M7El65NykCMh/openapi.json
