# Skyscanner Hotels Scraper API $1.5/1k — Prices & Content (`memo23/skyscanner-hotels-scraper`) Actor

Search Skyscanner hotels by destination and dates. One row per hotel with the cheapest live price and the partner offering it (Booking.com, Trip.com, Hotels.com, Expedia and more), room and cancellation terms, ratings and images, plus optional full content with AI review summaries.

- **URL**: https://apify.com/memo23/skyscanner-hotels-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Travel
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 hotel results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Skyscanner Hotels Scraper

Search Skyscanner hotels by destination and dates, get prices, ratings, images, partner offers and full content in one structured stream.
Pure HTTP against Skyscanner's mobile hotel API — no anti-bot, no token pipeline, no browser overhead.

### Why Use This Scraper?

- ✅ Search any Skyscanner hotel destination by entityId or hotels URL
- ✅ Cheapest live price per hotel, compared across Booking.com, Trip.com, Hotels.com, Expedia and more
- ✅ Full content enrichment — description, amenities, gallery, AI review summary
- ✅ Filter by stars, guest rating, price, property type, amenities, meal plan and free cancellation
- ✅ Relative dates ("30 days" ahead) keep scheduled price tracking current
- ✅ Sort by recommended, price, rating, distance or stars
- ✅ Clean JSON or CSV output, one row per hotel

### Overview

The actor talks to Skyscanner's hotel-unified-bff mobile API, the same endpoint the Android app uses. The hotel API is a separate surface from the flights one and is not behind PerimeterX, so no token or cookie is needed. You provide a destination (an entityId, or a Skyscanner hotels URL it is read from) and optionally check-in/check-out dates; the actor runs the search, polls until results settle, pages through them 50 at a time, and returns one row per hotel with its cheapest price and booking partner, rating, images, location and optional full content.

### Supported Inputs

**Entity ID mode** — pass `entityId` directly:

```
27544008   (London)
27539733   (Paris)
27547375   (New York)
```

**URL mode** — paste Skyscanner hotels URLs; the destination id is read from the link:

```
https://www.skyscanner.net/hotels/search?entity_id=27544008&checkin=2026-12-10&checkout=2026-12-12&adults=2&rooms=1
https://www.skyscanner.net/hotels/united-kingdom/london-hotels/ci-27544008
https://www.skyscanner.com/hoteles/reino-unido/londres-hoteles/cerca-pri-initiative/pl-207147685
https://www.skyscanner.net/hotels/united-kingdom/london-hotels/some-hotel/ht-129259677?search_entity_id=27544008
```

A hotel page (`ht-…`) only works when it carries `search_entity_id`; on its own it names a hotel, not a destination. A URL with no destination id is skipped with a warning in the log.

**Required:** either `entityId` or a usable URL in `startUrls`. `checkIn` and `checkOut` are optional: without them the actor searches a 2-night stay starting 30 days from today.

### Use Cases

| Audience | Use |
|---|---|
| Travel aggregators | Feed Skyscanner hotel prices into a comparison engine |
| Market researchers | Track hotel pricing and rating trends across destinations |
| SEO / content teams | Build destination guides with real hotel data and images |
| Revenue analysts | Monitor competitor pricing across OTAs in one pull |
| Trip planners | Pull a structured hotel shortlist for any city and date range |

### How It Works

1. **Resolve destination** — entityId is taken from input or parsed from the start URL.
2. **Trigger search** — POST to `v1/hotelsearch` with the entityId, dates and traveller context.
3. **Poll until complete** — repeat the call with the session token until `completionPercentage` hits 100.
4. **Parse hotels** — each hotel becomes a row with price, rating, images, partner offers, location.
5. **Optional content enrichment** — one batched POST to `v1/content/hotel/batch` adds description, amenities, full gallery and the AI review summary.

![How it works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-skyscanner-hotels.png)

### Input Configuration

| Field | Type | Default | Description |
|---|---|---|---|
| `startUrls` | array | — | Skyscanner hotels URLs; the destination id is read from the link (see URL mode above). |
| `entityId` | string | — | Skyscanner destination id (city, neighbourhood, place). London is 27544008. Needed when startUrls has no usable URL. |
| `checkIn` | string | 30 days from today | Check-in date: `YYYY-MM-DD`, or a distance from the day the run starts such as `"30 days"`, `"2 weeks"` or `"1 month"`. A date in the past is rejected. |
| `checkOut` | string | checkIn + 2 nights | Check-out date: `YYYY-MM-DD`, or a distance from the day the run starts (`"32 days"` with check-in `"30 days"` is 2 nights). |
| `adults` | integer | 2 | Adults per room (12+). |
| `rooms` | integer | 1 | Number of rooms. |
| `childrenAges` | array | — | Ages of children (0-17), one per entry. |
| `maxItems` | integer | 50 | Max hotels to return. Fetched 50 at a time until reached. |
| `includeContent` | boolean | false | Enrich each hotel with full content (description, amenities, gallery, AI summary). Add-on: $0.001 per enriched hotel. |
| `sortBy` | enum | RECOMMENDED | RECOMMENDED, PRICE_LOW, PRICE_HIGH, RATING (guest rating), DISTANCE, STARS (5 to 1), STARS_LOW (1 to 5). |
| `minStars` | integer | — | Only hotels with at least this many stars (1-5). |
| `minReviewScore` | number | — | Min guest rating out of 5. Skyscanner offers 3, 3.5, 4, 4.5 and 5; another value is rounded down to one of them. |
| `minPricePerNight` | number | — | Lowest price per night, in `currency`. |
| `maxPricePerNight` | number | — | Highest price per night, in `currency`. |
| `freeCancellationOnly` | boolean | false | Only hotels with free cancellation. |
| `mealPlans` | array | — | Any of `breakfast_included`, `half_board`, `all_inclusive`. |
| `propertyTypes` | array | — | Any of `accom_type_hotels`, `accom_type_homes_and_apartments`, `accom_type_guesthouses_and_bed_and_breakfasts`, `accom_type_villas_and_holiday_rentals`, `accom_type_hostels_and_capsule_hotels`, `accom_type_motels`, `accom_type_resorts_and_wellness`, `accom_type_camping_and_holiday_parks`, `accom_type_boats_and_floating_stays`, `accom_type_local_style`. |
| `amenities` | array | — | A hotel must have all of them: `hotel_amenity_wifi_service`, `hotel_amenity_parking`, `hotel_amenity_pool`, `hotel_amenity_spa`, `hotel_amenity_fitness_center`, `hotel_amenity_pets_allowed_service` and other `hotel_amenity_*` codes. |
| `market` | string | GB | Country Skyscanner searches from (GB, US, DE…). GB is sent as UK internally. |
| `locale` | string | en-GB | Language of names, descriptions and AI summaries (en-GB, de-DE, ja-JP…). |
| `currency` | string | GBP | Currency of every price and of the price filters (GBP, USD, EUR…). |
| `proxy` | object | Apify proxy | Proxy configuration. Paying users use our residential pool automatically. |

#### Example: London search with content

```json
{
    "entityId": "27544008",
    "checkIn": "2026-11-15",
    "checkOut": "2026-11-18",
    "adults": 2,
    "rooms": 1,
    "maxItems": 50,
    "includeContent": true,
    "sortBy": "PRICE_LOW"
}
```

#### Example: filtered search by URL

```json
{
    "startUrls": [{ "url": "https://www.skyscanner.net/hotels/search?entity_id=27544008" }],
    "checkIn": "2026-12-01",
    "checkOut": "2026-12-04",
    "minStars": 4,
    "minReviewScore": 4,
    "freeCancellationOnly": true,
    "maxPricePerNight": 200,
    "amenities": ["hotel_amenity_pool"]
}
```

#### Example: daily price tracking with relative dates

A run scheduled every day searches the same distance ahead, so the dates never go stale:

```json
{
    "entityId": "27544008",
    "checkIn": "30 days",
    "checkOut": "32 days",
    "sortBy": "PRICE_LOW",
    "maxItems": 100
}
```

### Output Overview

One row per hotel. Each row carries the search result (cheapest price and the partner offering it, rating, images, location) and, when `includeContent` is on, the full content block (description, amenities, full gallery, AI review summary with category scores). Skyscanner compares the booking partners itself and returns the hotel's cheapest offer, so `partnerOffers` holds that one offer.

### Output Samples

```json
{
    "hotelId": "130757982",
    "name": "Park Grand Heathrow",
    "url": "https://www.skyscanner.net/hotels/united-kingdom/london-hotels/park-grand-heathrow/ht-130757982?adults=2&checkin=2026-11-15&checkout=2026-11-18&rooms=1",
    "stars": 4,
    "starLabel": "4 stars",
    "reviewSummary": { "rating": 4, "reviewCount": 669 },
    "pricePerNight": 60.34,
    "totalPrice": 181,
    "currency": "GBP",
    "partner": "Booking.com",
    "partnerOffers": [
        {
            "partnerId": "h_bc",
            "partnerName": "Booking.com",
            "pricePerNight": 60.34,
            "totalPrice": 181,
            "roomName": "Standard Double Room",
            "features": ["Non refundable"],
            "deeplinkUrl": "https://www.skyscanner.net/hotel_deeplink/4.0/UK/en-GB/GBP/h_bc/130757982/..."
        }
    ],
    "images": [
        { "type": "HOTEL_IMAGE_TYPE_OUTLOOK", "url": "https://content.skyscnr.com/available/2647017206/2647017206_WxH.jpg" }
    ],
    "location": {
        "address": "449 Great West Road, Heathrow, London, TW5 0BU, United Kingdom",
        "latitude": 51.47869,
        "longitude": -0.36372
    },
    "distance": { "label": "London Borough of Hounslow, London" },
    "checkIn": "2026-11-15",
    "checkOut": "2026-11-18",
    "adults": 2,
    "rooms": 1,
    "market": "UK",
    "locale": "en-GB"
}
```

With `includeContent: true`, each row also carries:

```json
{
    "description": "Just a 10-minute drive from London Heathrow Airport, this hotel provides modern accommodation with free Wi-Fi and satellite TV...",
    "amenities": ["Parking", "WiFi", "Fitness centre", "Air conditioning", "Room service", "Front desk 24 hour"],
    "llmSummary": {
        "summaryPhrases": ["Best location", "Very clean rooms", "Helpful staff"],
        "categoryReviewSummary": [
            { "category": "REVIEW_CATEGORY_LOCATION", "title": "Convenient for Heathrow and transport", "score": 4, "label": "Location 4.0/5" },
            { "category": "REVIEW_CATEGORY_CLEANLINESS", "title": "Cleanliness generally good but inconsistent", "score": 3, "label": "Cleanliness 3.0/5" }
        ]
    }
}
```

### Key Output Fields

**Identity & search context**
`hotelId`, `name`, `url`, `stars`, `starLabel`, `checkIn`, `checkOut`, `adults`, `rooms`, `market`, `locale`

**Pricing**
`pricePerNight`, `totalPrice`, `currency`, `partner`, `partnerOffers[]` (the cheapest offer: partner, price, room name, terms, deeplink)

**Reviews**
`reviewSummary.rating`, `reviewSummary.reviewCount`, `reviewSummary.subratings[]`

**Location**
`location.address`, `location.city`, `location.country`, `location.latitude`, `location.longitude`, `distance.label`

**Content (when `includeContent` is on)**
`description`, `amenities[]`, `images[]` (full typed gallery), `llmSummary.summaryPhrases[]`, `llmSummary.categoryReviewSummary[]`

### FAQ

**Where do I find an entityId?** Search hotels on Skyscanner and look at the results URL: the `entity_id=` value is the entityId (London is 27544008). City and place pages carry it as `ci-…` or `pl-…`. You can also pass the full URL via `startUrls` and the actor reads it for you.

**Does this scrape reviews?** No. Reviews are a separate actor: `memo23/skyscanner-hotel-reviews-scraper`. It pulls reviews aggregated from partners such as Hotels.com, Expedia and Tripadvisor in one call.

**Is there an anti-bot or token I need?** No. The hotel BFF is plain JSON. The actor works out of the box with no PX token, no cookies, no browser.

**Do I have to set dates?** No. Without `checkIn` and `checkOut` the actor searches a 2-night stay starting 30 days from today. Dates you set are used as given; a check-in date in the past is rejected, because Skyscanner only has availability from today on.

**Can a scheduled run keep searching ahead?** Yes. Set relative dates such as `"checkIn": "30 days"` and `"checkOut": "32 days"` (in the Console, switch the date picker to relative). Both count from the day each run starts.

**What's the difference between `pricePerNight` and `totalPrice`?** `pricePerNight` is the per-night rate; `totalPrice` is the full stay total (nights × rate + taxes and fees).

### Support

- Issues: [Apify Console Issues tab](https://console.apify.com/actors/memo23%2Fskyscanner-hotels-scraper)
- Email: support@memo23.dev

### Additional Services

Need a custom export format, a specific filter combination, or a batch of destinations? We build tailored integrations on top of this actor. Reach out via the Issues tab or email.

### Explore More Scrapers

- [Skyscanner Hotel Reviews Scraper](https://apify.com/memo23/skyscanner-hotel-reviews-scraper) — aggregated reviews + AI insights
- [Skyscanner Flight Scraper](https://apify.com/memo23/skyscanner-scraper) — itineraries, fares, multi-city

### 🤖 For AI Agents & LLM Apps

This actor is callable via the Apify MCP server. Quick reference:

**Purpose:** Search Skyscanner hotels by destination and dates; return one row per hotel with price, rating, images, partner offers and optional full content.

**Minimal input (tested):**

```json
{
    "entityId": "27544008",
    "maxItems": 20
}
```

**Output fields (flat):** `hotelId`, `name`, `url`, `stars`, `starLabel`, `reviewSummary.rating`, `reviewSummary.reviewCount`, `pricePerNight`, `totalPrice`, `currency`, `partner`, `partnerOffers[].partnerName`, `partnerOffers[].deeplinkUrl`, `images[].url`, `location.address`, `location.latitude`, `location.longitude`, `distance.label`, `description`, `amenities`, `llmSummary.summaryPhrases` (with `includeContent`).

**Billing:** Pay-per-event. $0.0015 per hotel row ($1.50 per 1,000), $0.002 per destination searched, $0.001 per hotel enriched with `includeContent`, and $0.007 per GB of memory at run start. Free-tier runs are capped.

**Agent notes:** `entityId` is required (or a Skyscanner hotels URL in `startUrls`). Dates are optional; set them as YYYY-MM-DD, today or later. The actor polls the search to completion and pages through it internally, so one input = one full search result set up to `maxItems`.

### ⚠️ Disclaimer

This scraper is not affiliated with, endorsed by, or sponsored by Skyscanner Limited. "Skyscanner" is a trademark of Skyscanner Limited. This tool accesses publicly available data via Skyscanner's mobile API for research and analysis purposes only. Users are responsible for complying with Skyscanner's Terms of Service and all applicable laws, including GDPR and CCPA. The actor does not bypass authentication, paywalls, or access controls. For any concerns about data usage, contact the operator via the Issues tab.

### SEO Keywords

skyscanner hotels scraper, skyscanner hotel prices, skyscanner hotel search, hotel price comparison api, hotel availability api, skyscanner mobile api, hotel data feed, hotel rates scraper, accommodation search api, travel data scraping, hotel booking data, skyscanner hotel deals, hotel aggregator api, london hotels api, paris hotels api, hotel content enrichment, hotel images api, hotel amenities data, hotel review summary, skyscanner hotel partner offers

# Actor input Schema

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

Skyscanner hotels URLs. The destination id is read from a search URL (…/hotels/search?entity_id=27544008…), a city or place page (…/london-hotels/ci-27544008, …/pl-207147685), or a hotel page that carries search_entity_id=….

## `entityId` (type: `string`):

Skyscanner destination id (city, neighbourhood or place). London is 27544008. It is the entity_id or search_entity_id value in a Skyscanner hotels URL. Not needed when startUrls has a usable URL.

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

Pick a date, or switch to relative to search a fixed distance ahead ("30 days" means 30 days from the day the run starts), which keeps a scheduled run current. Leave empty to search a stay starting 30 days from today.

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

Pick a date, or a relative value counted from the day the run starts, like check-in ("32 days" with check-in "30 days" is a 2-night stay). Leave empty for a 2-night stay.

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

Adults per room (12+).

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

Number of rooms.

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

One age per entry, 0 to 17. Leave empty for no children.

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

Maximum number of hotels to return. Hotels are fetched 50 at a time until this is reached.

## `includeContent` (type: `boolean`):

Add full content to each hotel: description, amenities, full gallery and the AI review summary, via the content/batch endpoint. Add-on: $0.001 per hotel it enriches.

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

Order of the hotels.

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

Only hotels with at least this many stars (1 to 5). Unrated properties are left out when set.

## `minReviewScore` (type: `number`):

Only hotels with at least this guest rating, out of 5. Skyscanner offers 3, 3.5, 4, 4.5 and 5; another value is rounded down to one of them.

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

Lowest price per night, in the currency below.

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

Highest price per night, in the currency below.

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

Only return hotels with free cancellation.

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

Only hotels offering one of these meal plans.

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

Only these kinds of property.

## `amenities` (type: `array`):

Only hotels that have all of these. Pick from the list, or type another amenity code from Skyscanner (hotel_amenity\_…).

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

Country Skyscanner searches from, which can change prices and partners. Pick one or type another country code.

## `locale` (type: `string`):

Language of hotel names, descriptions and AI summaries. Pick one or type another locale code.

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

Currency of every price, and of the price filters. Pick one or type another currency code.

## `proxy` (type: `object`):

Proxy configuration (non-paying users). Paying users use our residential pool automatically.

## Actor input object example

```json
{
  "entityId": "27544008",
  "adults": 2,
  "rooms": 1,
  "maxItems": 20,
  "includeContent": false,
  "sortBy": "RECOMMENDED",
  "freeCancellationOnly": false,
  "market": "GB",
  "locale": "en-GB",
  "currency": "GBP",
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One row per hotel found for the destination and dates.

# 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 = {
    "entityId": "27544008",
    "maxItems": 20,
    "proxy": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/skyscanner-hotels-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 = {
    "entityId": "27544008",
    "maxItems": 20,
    "proxy": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/skyscanner-hotels-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 '{
  "entityId": "27544008",
  "maxItems": 20,
  "proxy": {
    "useApifyProxy": true
  }
}' |
apify call memo23/skyscanner-hotels-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,memo23/skyscanner-hotels-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/jaR1A6z9iHfMsLruZ/builds/qo1LW29Xqc0bW2VNX/openapi.json
