# Skyscanner Flights Scraper (`datascrapers/skyscanner-scraper`) Actor

Search Skyscanner one-way and return flights, apply baggage, stop, and time filters, and optionally collect booking-panel details.

- **URL**: https://apify.com/datascrapers/skyscanner-scraper.md
- **Developed by:** [Farhan Ali](https://apify.com/datascrapers) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 flights

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

**Skyscanner Flights Scraper** creates a structured dataset of flight itineraries collected from [Skyscanner](https://www.skyscanner.com). Each dataset item represents one itinerary and can include the price, currency, trip type, cabin, passengers, origin and destination airports, outbound and return times, duration, stops, carriers, the cheapest agent, a booking link, and — when enabled — booking-panel details such as baggage and amenities. Query the source using origin, destination, and dates, apply baggage, stop, and time filters, control the result limit with `maxItems`, and retrieve records through the Apify Dataset API or export them as JSON, CSV, or Excel.

### Dataset at a glance

| Property | Value |
|---|---|
| Source | skyscanner.com |
| Record unit | One flight itinerary |
| Input methods | Origin + destination + dates, or multiple routes via `searches` |
| Main identifiers | `itineraryId` |
| Delivery | Apify Dataset and API |
| Export formats | JSON, CSV, Excel |
| Update model | Fresh records per Actor run |
| Pricing | Pay per event, from $1.50 per 1,000 flights |

### Coverage and available records

The Actor collects one-way and round-trip itineraries:

- **Single route** — set `origin`, `destination`, and `departDate`; add `returnDate` for a round trip.
- **Multiple routes** — pass a `searches` array of routes; a non-empty list replaces the single route while passenger, cabin, market, and filter settings still apply to every route.

Supported behavior:

- **Filters** — cabin (`economy`, `premiumeconomy`, `business`, `first`), checked bag, cabin bag, stop counts, maximum duration, and outbound/return takeoff and landing windows.
- **Optional flight details** (`includeFlightDetails`) loads the booking panel — agents, baggage, amenities, and booking links — billed as a separate `flight-details` event.
- `maxItems` caps how many flights are saved (`0` = no limit).

`return*` fields are null for one-way searches. `agents`, `legs`, and `flightDetails` are conditional on the corresponding option.

### Data dictionary

| Field | Type | Nullable | Description | Example |
|---|---:|---|---|---|
| `itineraryId` | string | No | Stable itinerary identifier | `11983-240106...` |
| `price` | number | No | Cheapest fare | `312.40` |
| `currency` | string | No | Price currency | `EUR` |
| `priceFormatted` | string | No | Display price label | `€312` |
| `tripType` | string | No | Trip type | `roundTrip` |
| `cabinClass` | string | No | Cabin | `economy` |
| `adults` | integer | No | Adult passenger count | `1` |
| `childAges` | array | No | Child ages | `[]` |
| `originCode` | string | No | Departure airport code | `BER` |
| `originName` | string | Yes | Departure airport name | `Berlin Brandenburg` |
| `originCity` | string | No | Departure city | `Berlin` |
| `destinationCode` | string | No | Arrival airport code | `ISB` |
| `destinationName` | string | Yes | Arrival airport name | `Islamabad International` |
| `destinationCity` | string | No | Arrival city | `Islamabad` |
| `outboundDeparture` | string | No | Outbound departure time | `2027-01-06T06:30:00` |
| `outboundArrival` | string | No | Outbound arrival time | `2027-01-06T15:45:00` |
| `outboundDurationMinutes` | integer | No | Outbound duration | `615` |
| `outboundStops` | integer | No | Outbound stops | `1` |
| `outboundCarriers` | array | No | Outbound airlines | `["Turkish Airlines"]` |
| `returnDeparture` | string | Yes | Return departure (round trip) | `2027-02-14T10:00:00` |
| `returnArrival` | string | Yes | Return arrival | `2027-02-14T21:00:00` |
| `returnDurationMinutes` | integer | Yes | Return duration | `660` |
| `returnStops` | integer | Yes | Return stops | `1` |
| `returnCarriers` | array | Yes | Return airlines | `["Turkish Airlines"]` |
| `cheapestAgent` | string | Yes | Cheapest booking agent | `Kiwi.com` |
| `bookingUrl` | string | Yes | Booking link | `https://www.skyscanner.net/...` |
| `isSelfTransfer` | boolean | No | Self-transfer flag | `false` |
| `isChangeAllowed` | boolean | No | Changes allowed | `false` |
| `isCancellationAllowed` | boolean | No | Cancellation allowed | `false` |
| `url` | string | No | Results page URL | `https://www.skyscanner.net/...` |
| `searchUrl` | string | No | Search URL | `https://www.skyscanner.net/...` |
| `score` | number | No | Skyscanner itinerary score | `0.9` |
| `agents` | array | Yes | Other agents with ratings | `[{...}]` |
| `legs` | array | Yes | Segment detail per direction | `[{...}]` |
| `flightDetails` | object | Yes | Booking-panel details (enabled) | `{...}` |

Use `itineraryId` as the stable field for deduplication across runs.

### Example dataset record

```json
{
  "itineraryId": "11983-2401060615--31462-1-15436-2401061545",
  "price": 312.40,
  "currency": "EUR",
  "priceFormatted": "€312",
  "tripType": "roundTrip",
  "cabinClass": "economy",
  "adults": 1,
  "childAges": [],
  "originCode": "BER",
  "originCity": "Berlin",
  "destinationCode": "ISB",
  "destinationCity": "Islamabad",
  "outboundDeparture": "2027-01-06T06:30:00",
  "outboundArrival": "2027-01-06T15:45:00",
  "outboundDurationMinutes": 615,
  "outboundStops": 1,
  "outboundCarriers": ["Turkish Airlines"],
  "returnDeparture": "2027-02-14T10:00:00",
  "returnArrival": "2027-02-14T21:00:00",
  "returnDurationMinutes": 660,
  "returnStops": 1,
  "returnCarriers": ["Turkish Airlines"],
  "cheapestAgent": "Kiwi.com",
  "isSelfTransfer": false,
  "isChangeAllowed": false,
  "isCancellationAllowed": false
}
```

This record was produced by a Berlin to Islamabad round-trip search with flight details disabled.

### Query and input reference

| Input | Type | Required | Default | Accepted values | Description |
|---|---:|---|---|---|---|
| `origin` | string | Yes | `Berlin` | City, airport, or IATA | Departure point. |
| `destination` | string | Yes | `Islamabad` | City, airport, or IATA | Arrival point. |
| `departDate` | string | Yes | — | `YYYY-MM-DD` | Outbound date. |
| `returnDate` | string | No | — | `YYYY-MM-DD` | Return date (round trip). |
| `searches` | array | No | `[]` | Route objects | Replaces the single route when non-empty. |
| `adults` | integer | No | `1` | 1–8 | Adult passengers. |
| `childAges` | array | No | `[]` | 0–17 | Child ages. |
| `cabinClass` | string | No | `economy` | `economy`, `premiumeconomy`, `business`, `first` | Cabin. |
| `market` | string | No | `DE` | Skyscanner market code | Market. |
| `locale` | string | No | `en-GB` | Language-region | Locale. |
| `currency` | string | No | `EUR` | `EUR`, `USD`, `GBP`, etc. | Price currency. |
| `checkedBag` | boolean | No | `false` | `true` / `false` | Require checked bag. |
| `cabinBag` | boolean | No | `false` | `true` / `false` | Require cabin bag. |
| `includeDirect` | boolean | No | `true` | `true` / `false` | Include non-stop. |
| `includeOneStop` | boolean | No | `true` | `true` / `false` | Include one-stop. |
| `includeTwoPlusStops` | boolean | No | `true` | `true` / `false` | Include two-plus stops. |
| `maxDurationMinutes` | integer | No | `0` | `0` = no limit | Drop longer itineraries. |
| `outboundDepartureFrom` / `outboundDepartureTo` | string | No | — | `HH:MM` | Outbound takeoff window. |
| `outboundArrivalFrom` / `outboundArrivalTo` | string | No | — | `HH:MM` | Outbound landing window. |
| `returnDepartureFrom` / `returnDepartureTo` | string | No | — | `HH:MM` | Return takeoff window. |
| `returnArrivalFrom` / `returnArrivalTo` | string | No | — | `HH:MM` | Return landing window. |
| `includeFlightDetails` | boolean | No | `false` | `true` / `false` | Load booking panel (billed as `flight-details`). |
| `maxItems` | integer | No | `20` | `0` = no limit | Maximum flights to save. |
| `proxyConfiguration` | object | No | Apify residential | Proxy editor | Proxy settings. |

Minimal request:

```json
{ "origin": "Berlin", "destination": "Islamabad", "departDate": "2027-01-06" }
```

Advanced request (round trip with filters and details):

```json
{
  "origin": "Berlin",
  "destination": "Islamabad",
  "departDate": "2027-01-06",
  "returnDate": "2027-02-14",
  "cabinClass": "economy",
  "currency": "EUR",
  "checkedBag": true,
  "includeDirect": true,
  "includeOneStop": true,
  "includeFlightDetails": true,
  "maxItems": 20,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

### Retrieve the data through the API

1. Start the Actor with a JSON input.
2. Wait for the run to finish, or use the synchronous endpoint for small jobs.
3. Retrieve items from the run's default dataset.
4. Paginate or export the dataset.

Python example:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")
run = client.actor("datascrapers/skyscanner-scraper").call(
    run_input={
        "origin": "Berlin",
        "destination": "Islamabad",
        "departDate": "2027-01-06",
        "maxItems": 10,
    }
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["price"], item["currency"])
```

For other languages, use the generated API tab on the Actor page.

### Data quality and record handling

- **Completeness** — core fields (`price`, `originCode`, `destinationCode`, times) are returned when Skyscanner exposes them; `flightDetails`, `agents`, and `legs` are conditional on the corresponding option.
- **Source changes** — Skyscanner page structure changes can cause individual fields to come back empty.
- **Deduplication** — the Actor writes one row per itinerary per run and does not persist dedup state across runs. Deduplicate on `itineraryId` when merging runs over time.
- **Retry/error behavior** — a route that returns nothing is reported without discarding flights already saved.
- **Normalization** — `price` is numeric with a separate `currency` code; `priceFormatted` keeps Skyscanner's display string.

### Export and pipeline examples

| Destination | Recommended method | Typical use |
|---|---|---|
| PostgreSQL/Supabase | Dataset API or webhook consumer | Fare history for monitoring |
| Google Sheets | Apify integration | Fare comparison sheets |
| S3/cloud storage | Scheduled export or integration | Archive daily fare snapshots |

### Pricing and cost examples

Billing is pay per event. You are not charged Apify platform usage on top of these events.

| Event | When charged | Price |
|---|---|---|
| `flight` | Each flight saved to the dataset | $1.50 per 1,000 |
| `flight-details` | Each flight with booking-panel details fetched (when enabled) | $1.50 per 1,000 |

| Records | Estimated base cost |
|---:|---:|
| 1,000 flights | $1.50 |
| 10,000 flights | $15.00 |

Estimates assume flights only. Enabling `includeFlightDetails` adds one `flight-details` event per flight, and Apify plan discounts may reduce the per-event price.

### Limitations and responsible data use

- The Actor reads publicly accessible Skyscanner fare data.
- Fares change frequently; results reflect the moment of the run and are not guaranteed to match a later booking.
- No guarantee of historical snapshots unless you store results yourself.
- You are responsible for compliance with applicable terms, privacy, and legal requirements when using the data.

### Dataset questions

#### What does one dataset item represent?

One flight itinerary (a set of outbound and, when applicable, return legs sold together at one price).

#### Which field should I use as a unique identifier?

`itineraryId` is the stable identifier for comparing the same itinerary across runs.

#### Are fields nullable or conditional?

`return*` fields are null for one-way searches. `agents`, `legs`, and `flightDetails` are present only when the matching option is enabled.

#### Can I retrieve the records as CSV or JSON?

Yes. Export from the Output tab as JSON, CSV, or Excel, or read the dataset through the Apify API.

#### How do I paginate large datasets?

Use `maxItems` to cap saved flights. For API retrieval, paginate the default dataset items endpoint.

#### Does the Actor return historical data?

No. Each run captures fares at run time; store runs yourself to build history.

#### What counts as a billable result?

Each saved flight is a `flight` event. When enabled, each flight with booking-panel details is an additional `flight-details` event.

### Related datasets from Data Scrapers

- **[Booking.com Scraper](https://apify.com/datascrapers/booking-com-scraper)** — Hotel listings that can be joined with flights for full trip planning.
- **[TripAdvisor Reviews Scraper](https://apify.com/datascrapers/tripadvisor-reviews-scraper)** — Destination and property reviews to complement travel research.

### Data Scrapers support

Need an additional field, record type, or export workflow? Contact Data Scrapers at stardustspotlight@gmail.com. Include a sample source URL, required fields, expected record volume, and preferred delivery format.

# Actor input Schema

## `origin` (type: `string`):

Departure city, airport, or IATA code, such as Berlin or BER.

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

Arrival city, airport, or IATA code, such as Islamabad or ISB.

## `departDate` (type: `string`):

Outbound date in YYYY-MM-DD format.

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

Return date in YYYY-MM-DD format. Leave empty for a one-way search.

## `searches` (type: `array`):

Optional list of routes. When this list is not empty, it replaces Origin, Destination, and the dates above. Passenger, cabin, market, and filter settings still apply to every route.

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

Number of adult passengers.

## `childAges` (type: `array`):

Age of each child passenger, from 0 to 17. Leave empty when there are no children.

## `cabinClass` (type: `string`):

Cabin to search.

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

Skyscanner market code, such as DE, US, or UK.

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

Language and region, such as en-GB.

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

Price currency, such as EUR, USD, or GBP.

## `checkedBag` (type: `boolean`):

Only return fares that include a checked bag.

## `cabinBag` (type: `boolean`):

Only return fares that include a cabin bag.

## `includeDirect` (type: `boolean`):

Include non-stop flights.

## `includeOneStop` (type: `boolean`):

Include flights with one stop.

## `includeTwoPlusStops` (type: `boolean`):

Include flights with two or more stops.

## `maxDurationMinutes` (type: `integer`):

Drop a flight when any leg is longer than this. 0 means no limit.

## `outboundDepartureFrom` (type: `string`):

Earliest outbound departure, HH:MM in local time. Leave empty for no limit.

## `outboundDepartureTo` (type: `string`):

Latest outbound departure, HH:MM in local time. Leave empty for no limit.

## `outboundArrivalFrom` (type: `string`):

Earliest outbound arrival, HH:MM in local time. Leave empty for no limit.

## `outboundArrivalTo` (type: `string`):

Latest outbound arrival, HH:MM in local time. Leave empty for no limit.

## `returnDepartureFrom` (type: `string`):

Earliest return departure, HH:MM in local time. Leave empty for no limit.

## `returnDepartureTo` (type: `string`):

Latest return departure, HH:MM in local time. Leave empty for no limit.

## `returnArrivalFrom` (type: `string`):

Earliest return arrival, HH:MM in local time. Leave empty for no limit.

## `returnArrivalTo` (type: `string`):

Latest return arrival, HH:MM in local time. Leave empty for no limit.

## `includeFlightDetails` (type: `boolean`):

Also load the booking panel for each flight: agents, baggage, amenities, and booking links. This is billed as a separate flight-details event.

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

Maximum number of flights to save. 0 means no limit.

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

Proxy settings. Residential proxies are used by default.

## Actor input object example

```json
{
  "origin": "Berlin",
  "destination": "Islamabad",
  "departDate": "2027-01-06",
  "returnDate": "2027-02-14",
  "adults": 1,
  "childAges": [],
  "cabinClass": "economy",
  "market": "DE",
  "locale": "en-GB",
  "currency": "EUR",
  "checkedBag": false,
  "cabinBag": false,
  "includeDirect": true,
  "includeOneStop": true,
  "includeTwoPlusStops": true,
  "maxDurationMinutes": 0,
  "includeFlightDetails": false,
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Dataset of flight itineraries. Booking-panel details are included when includeFlightDetails is enabled.

## `runStats` (type: `string`):

Record counts and timestamps for this run.

# 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 = {
    "origin": "Berlin",
    "destination": "Islamabad",
    "departDate": "2027-01-06",
    "returnDate": "2027-02-14",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("datascrapers/skyscanner-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 = {
    "origin": "Berlin",
    "destination": "Islamabad",
    "departDate": "2027-01-06",
    "returnDate": "2027-02-14",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("datascrapers/skyscanner-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 '{
  "origin": "Berlin",
  "destination": "Islamabad",
  "departDate": "2027-01-06",
  "returnDate": "2027-02-14",
  "maxItems": 20
}' |
apify call datascrapers/skyscanner-scraper --silent --output-dataset

```

## MCP server setup

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