# Skyscanner Flight Scraper (`axlymxp/skyscanner-flight-scraper`) Actor

Scrape live Skyscanner flight prices and itineraries for any route and dates. Requires your own Scraping Browser or residential proxy (Skyscanner uses PerimeterX).

- **URL**: https://apify.com/axlymxp/skyscanner-flight-scraper.md
- **Developed by:** [axly](https://apify.com/axlymxp) (community)
- **Categories:** Travel
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.00 / 1,000 dataset items

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Skyscanner Flight Scraper

Get **live flight prices and full itineraries from Skyscanner** for any route and
travel dates — as clean, structured JSON. One row per itinerary, with price,
stops, durations, carriers, and per-leg detail. Built on Skyscanner's own
flight-search backend for accurate, up-to-date fares.

### Setup

Skyscanner protects fares with **PerimeterX** anti-bot, which rejects datacenter
and shared IPs. The Actor needs a **residential-quality egress** — pick one (in
order of reliability):

- **Scraping Browser / Web Unblocker (most reliable)** — set `scrapingBrowserUrl`
  to a remote anti-bot browser CDP endpoint (e.g. Bright Data Scraping Browser,
  Oxylabs Web Unblocker browser) as `ws(s)://user:pass@host:port`. The provider
  defeats PerimeterX and manages proxies for you. Overrides the options below.
- **Premium residential proxy** — set `customProxyUrl` to
  `http://user:pass@host:port` (Bright Data / Oxylabs / IPRoyal, etc.).
- **Apify Proxy (default)** — leave the two fields above empty and select
  **Residential** in `proxyConfiguration` (prefilled by default). This works out
  of the box if your plan includes residential proxy. **Datacenter IPs are
  almost always blocked**, so residential is strongly recommended.

`scrapingBrowserUrl` / `customProxyUrl` can also be supplied via the
`SCRAPING_BROWSER_URL` / `CUSTOM_PROXY_URL` environment variables. If every
attempt is blocked, the run stops with a clear message instead of pushing
partial data.

### Who it's for

- **Travel agencies & OTAs** benchmarking fares across routes and dates.
- **Fare-alert & price-comparison apps** needing a reliable live price feed.
- **Analysts & researchers** studying route pricing, seasonality, and carriers.
- **Affiliates & content sites** enriching pages with real prices.

### What you get (output fields)

| Field                         | Description                                                                       |
| ----------------------------- | --------------------------------------------------------------------------------- |
| `priceFormatted` / `priceRaw` | Total price, formatted and numeric                                                |
| `currency`                    | Currency of the price                                                             |
| `stops`                       | Total stops across the trip                                                       |
| `totalDurationMinutes`        | Total travel time                                                                 |
| `carriers`                    | Operating/marketing airlines                                                      |
| `legs[]`                      | Per-leg detail: origin, destination, departure/arrival, duration, stops, carriers |
| `bucket`                      | Result bucket (Best / Cheapest / Fastest)                                         |
| `origin` / `destination`      | Resolved place codes                                                              |
| `departDate` / `returnDate`   | Requested dates                                                                   |
| `deepLinkUrl`                 | Skyscanner results URL                                                            |
| `scrapedAt`                   | UTC timestamp                                                                     |

### Use cases

- **Fare benchmarking** — track prices for key routes on a schedule and store history.
- **Lead-gen for travel** — surface the cheapest options to your users.
- **Market research** — compare carriers, stop counts, and durations across dates.
- **Content enrichment** — embed live "from $X" prices on route/destination pages.

### Input

| Field                            | Type    | Required | Description                                            |
| -------------------------------- | ------- | -------- | ------------------------------------------------------ |
| `origin`                         | string  | yes      | City/airport text or IATA (e.g. "New York", "JFK")     |
| `destination`                    | string  | yes      | City/airport text or IATA                              |
| `departDate`                     | string  | yes      | Outbound date, `YYYY-MM-DD`                            |
| `returnDate`                     | string  | no       | Return date; omit for one-way                          |
| `adults`                         | integer | no       | Adult passengers (default 1)                           |
| `cabinClass`                     | enum    | no       | economy / premiumeconomy / business / first            |
| `sortBy`                         | enum    | no       | best / cheapest / fastest                              |
| `maxItems`                       | integer | no       | Max itineraries (default 100)                          |
| `market` / `locale` / `currency` | string  | no       | Localization (default US / en-US / USD)                |
| `proxyConfiguration`             | object  | no       | Apify Proxy (default: Residential). Used unless a URL below is set |
| `scrapingBrowserUrl`             | string  | no       | Scraping Browser / Web Unblocker CDP URL (most reliable)|
| `customProxyUrl`                 | string  | no       | Premium residential proxy URL (alternative)            |

One residential-quality egress is required — Apify Residential Proxy (default),
`customProxyUrl`, or `scrapingBrowserUrl`. See **Setup** above.

#### Example input

```json
{
    "origin": "New York",
    "destination": "London",
    "departDate": "2026-09-15",
    "returnDate": "2026-09-22",
    "adults": 1,
    "cabinClass": "economy",
    "sortBy": "best",
    "maxItems": 50,
    "scrapingBrowserUrl": "wss://user:pass@brd.superproxy.io:9222"
}
```

#### Example output row

```json
{
    "itineraryId": "13771-2607272035--30596-0-14476-2607272335|...",
    "priceFormatted": "$696",
    "priceRaw": 696.0,
    "currency": "USD",
    "stops": 0,
    "totalDurationMinutes": 245,
    "carriers": ["British Airways"],
    "legs": [
        {
            "origin": "JFK",
            "originName": "New York John F. Kennedy",
            "destination": "LHR",
            "destinationName": "London Heathrow",
            "departure": "2026-09-15T18:30:00",
            "arrival": "2026-09-16T06:35:00",
            "durationMinutes": 425,
            "stopCount": 0,
            "carriers": ["British Airways"]
        }
    ],
    "deepLinkUrl": "https://www.skyscanner.com/transport/flights/nyca/lond/260915/260922/"
}
```

### Scheduling & webhooks

Run on a **schedule** (e.g. daily) to build a price-history dataset, and use
**webhooks** to push new results to your own systems or trigger fare alerts.

### Use with AI assistants (MCP)

Prefer conversational access? See the companion **Skyscanner MCP Server** actor,
which exposes flight search as tools for Claude, Cursor, and other AI agents.

### Reliability & unblocker

Skyscanner is protected by PerimeterX. This actor uses a stealth browser to pass
the challenge and read Skyscanner's own flight API, **driven through the Scraping
Browser or residential proxy you provide** (see Setup). With a Scraping Browser /
Web Unblocker endpoint, runs are consistent; with a raw residential proxy, the
actor retries a few times to ride out PX-flagged IPs.

### FAQ

**How fresh is the data?** Prices are fetched live at run time from Skyscanner's
flight-search backend.

**Can I get one-way flights?** Yes — omit `returnDate`.

**Why do I need my own unblocker?** Skyscanner's PerimeterX anti-bot rejects
datacenter/shared IPs. A Scraping Browser or premium residential proxy is
required for consistent results; the actor stops early with a clear message if
none is provided.

**Is there a limit per run?** Control volume with `maxItems`. A single route
search commonly yields hundreds to thousands of itineraries.

**Is scraping legal?** You are responsible for complying with Skyscanner's terms
and applicable laws. This tool accesses only publicly visible flight results.

# Actor input Schema

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

Departure city or airport — free text or IATA code (e.g. "New York", "JFK", "London").

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

Arrival city or airport — free text or IATA code (e.g. "London", "LHR").

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

Outbound date in YYYY-MM-DD format.

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

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

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

Number of adult passengers.

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

Cabin class.

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

Which result bucket to return first.

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

Maximum number of itineraries to return.

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

Skyscanner market (2-letter).

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

Language-region locale.

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

3-letter currency code.

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

Egress used to reach Skyscanner. Residential is strongly recommended — datacenter IPs are rejected by PerimeterX. For maximum reliability you can instead set `scrapingBrowserUrl` or `customProxyUrl` below, which take priority over this.

## `scrapingBrowserUrl` (type: `string`):

Optional. A remote anti-bot browser CDP endpoint (e.g. Bright Data Scraping Browser, Oxylabs Web Unblocker browser) as ws(s)://user:pass@host:port. The provider defeats Skyscanner's PerimeterX and manages proxies — by far the most reliable option, and it overrides the proxy configuration above. Also settable via the SCRAPING\_BROWSER\_URL env var.

## `customProxyUrl` (type: `string`):

Optional. BYO premium residential proxy as http://user:pass@host:port (e.g. Bright Data / Oxylabs / IPRoyal). Used instead of the Apify proxy configuration above when set (but a Scraping Browser URL takes priority). Also settable via the CUSTOM\_PROXY\_URL env var.

## Actor input object example

```json
{
  "origin": "New York",
  "destination": "London",
  "departDate": "2026-09-15",
  "returnDate": "2026-09-22",
  "adults": 1,
  "cabinClass": "economy",
  "sortBy": "best",
  "maxItems": 100,
  "market": "US",
  "locale": "en-US",
  "currency": "USD",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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": "New York",
    "destination": "London",
    "departDate": "2026-09-15",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("axlymxp/skyscanner-flight-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": "New York",
    "destination": "London",
    "departDate": "2026-09-15",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("axlymxp/skyscanner-flight-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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": "New York",
  "destination": "London",
  "departDate": "2026-09-15",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call axlymxp/skyscanner-flight-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=axlymxp/skyscanner-flight-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ci52D88QZXssdPTxf/builds/cDyXzDvidd0GFmPAB/openapi.json
