Skyscanner.com [Only $1💰] scraper
Pricing
from $1.00 / 1,000 results
Skyscanner.com [Only $1💰] scraper
💰$1 per 1000 results, unlimited extraction. Extract detailed flight itineraries from Skyscanner: prices, airlines, schedules, and routes. Search with a flights link or your parameters—one-way, round trip, cabin, passengers, multi-city legs. Filters and sorting refine results for your Apify dataset.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Muhamed Didovic
Actor stats
0
Bookmarked
7
Total users
4
Monthly active users
3 days ago
Last modified
Categories
Share
Skyscanner flight scraper
Search Skyscanner for real itineraries and export structured flight data—ranked options, full result lists, or spreadsheet-ready rows.
This Apify actor calls Skyscanner’s radar-style unified search API (mobile-style headers) for the route, dates, and passenger mix you configure, then normalizes the response for analysis, pricing workflows, or CSV.
Why use this scraper?
- Two ways to search — Paste a Skyscanner
/transport/flights/…URL (browser address bar) and route + dates are read from the link, or fill departure/arrival/dates in the form when using the homepage URL. - Configurable trips — Origin and destination as city names or airport-style codes, flexible date formats, optional return date for round trips (filter mode).
- Passengers — Adults, children, and infants (placeholder ages in the API until the form exposes real ages).
- Flexible output — Default is one dataset row per itinerary with dashed column names for CSV. You can switch to nested JSON per row, or use advanced
outputFormatmodes (see below). - Rich aggregation — Optional single-dataset “envelope” with
buckets(Best, Cheapest, Fastest, Direct),allFlights,carriers,airports, andstats. - Proxy-friendly — Works with Apify Proxy; residential groups are prefilled in the input schema.
Overview
The actor is aimed at developers, analysts, and travel or pricing teams who need bulk, structured flight quotes from Skyscanner without maintaining their own mobile API integration.
What you get
- With
flattenOutput: true(default), the dataset contains one item per itinerary, flat keys such asprice-raw,legs-0-origin-displayCode, etc. - With
flattenOutput: false, each dataset item is a nested itinerary object (harvest shape). - With
outputFormat: "aggregated"(API-only), you get one object per search withbuckets,allFlights, lookup maps, andstats.
Results reflect what Skyscanner returns for the search (availability, ranking, and pricing are theirs). This is not a booking engine; use it for discovery and analysis.
The radar payload can expose itineraries both in named buckets (e.g. Best / Cheapest) and in a top-level itineraries.results list; the actor merges both and deduplicates by itinerary id across poll snapshots so row counts reflect unique flights (not the same snapshot repeated). Skyscanner may still enforce a maximum number of itineraries per search session (often on the order of hundreds); going beyond that would require a different official API or product surface, not a header tweak.
Supported inputs
The Apify input form uses collapsible sections (sectionCaption / sectionDescription in the schema), similar to “search by URL” vs “search by filters”:
- Scrape with Skyscanner URL —
startUrlswith a full flights path. - Scrape with search filters — airports, dates, cabin class, passengers, and optional market / currency / locale (same collapsible section in the UI; cabin and region still apply when using a flights URL). Then Output and General options (limits, proxy).
Priority: For each start URL, if it matches
…/transport/flights/{origin}/{destination}/{YYMMDD}/{YYMMDD?}/
on skyscanner.net or skyscanner.com, origin, destination, and dates from the URL win; the filter fields are ignored for that request. Adults / children / infants still come from input (the URL does not drive passenger counts).
| Input | Required | Description |
|---|---|---|
startUrls | Yes | Homepage https://www.skyscanner.net/ for filter mode, or a transport/flights URL for URL mode (see priority above). You can queue multiple URLs; each is resolved independently. |
departureAirport | Yes* | Origin in filter mode only. |
arrivalAirport | Yes* | Destination in filter mode only. |
departureDate | Yes* | In filter mode: YYYY-MM-DD or YYMMDD. |
returnDate | No | Filter mode: omit for one-way. URL mode: return segment comes from URL when present. |
cabinClass | No | Default economy. premium_economy | business | first. Applies to every run (unified-search body). |
adults | No | Default 1; minimum 1 in practice. |
children / infants | No | Counts; API uses placeholder ages. |
flattenOutput | No | Default true → dashed flat rows. false → nested itinerary JSON per row. |
skyscannerMarket | No | Default US. UI: select with country/territory list (from cat-guy-inputjson via npm run merge:cat-guy-enums). UK in source files is stored as GB. Raw JSON may still use any 2-letter code; UK → GB at run time. |
skyscannerCurrency | No | Default USD. UI: select with ISO 4217-style list (same merge script). Case normalized for API input. |
skyscannerLocale | No | Default en-US. BCP-47 pattern in the UI (e.g. bs-BA, zh-Hans-CN); normalized at run time. |
maxItems | No | See schema; non-paying Apify users may see stricter caps in logs. |
maxConcurrency / minConcurrency / maxRequestRetries | No | Crawler tuning (effective caps are applied in code). |
proxy | No | Apify Proxy recommended; defaults include RESIDENTIAL. |
resultSort | No | Client-side only: score, cheapest, fastest, departure, or default (keep API merge order). Not sent on the unified-search POST. |
resultLimit | No | Optional cap on rows after filters/sort. Omit for no cap; 0 yields an empty export. Separate from crawler maxItems. |
filterNonStop / filterOneStop / filterTwoPlusStops | No | Client-side stop filters (OR). Uses total stopCount summed across legs. |
multiCityLeg2* / multiCityLeg3* | No | Extra open-jaw legs built into the search payload (filter / harvest mode only). Ignored when the start URL is a transport/flights link; returnDate is ignored if leg 2 is set. |
includeNearbyAirports | No | Logs a warning only; no extra fields are sent on unified-search. |
extraHttpHeaders | No | Optional string→string map merged into POST and poll GET (overrides same header names). |
*Alternatively you can set flightOrigin, flightDestination, and departureDate (and optional returnDate) instead of departureAirport / arrivalAirport; the actor resolves locations via autosuggest.
Aggregated output note: When any of resultSort, stop filters, or resultLimit is set, processed aggregated output collapses buckets into a single Results bucket so tabular/flattened exports match the filtered list.
URL shape
- Supported for auto-parsing: path like
/transport/flights/lax/las/251001/(one-way) or…/251001/251008/(round trip). Other URL shapes may fall back to filter mode if parsing fails. - Guarantees on avoiding blocks: use proxies and reasonable concurrency.
Use cases
| Audience | Example use |
|---|---|
| Travel tech / metasearch | Compare routes and price bands for many date pairs. |
| Revenue / pricing analysts | Snapshot itinerary sets and stats.priceRange for monitoring. |
| Agencies & consultants | One-off or scheduled exports for clients. |
| Researchers | Structured open-itinerary data for models or reports. |
How it works
- You provide
startUrls. If the URL is a transport/flights link, the actor reads route and dates from it; otherwise it uses trip filters (orflightOrigin/flightDestinationAPI fields). Passenger counts always come from input. - The actor resolves place IDs, builds the unified-search JSON payload, and POSTs to Skyscanner.
- If the response is incomplete, it polls the session until the radar run finishes.
- Raw responses are merged and passed through
processFlightData→buckets,allFlights,carriers,airports,stats. - Depending on
flattenOutput/outputFormat, results are pushed to the dataset as flat rows, nested rows, or a single aggregated object.
How to run
URL mode (recommended when you already searched on Skyscanner)
- In the browser, run your search and copy the address bar URL (must include
/transport/flights/…). - Paste it under Scrape with Skyscanner URL.
- Set passengers and proxy; run. Filter fields can stay at defaults—they are ignored.
Filter mode
- Set
startUrlsto the homepage, e.g.https://www.skyscanner.net/. - Fill Scrape with search filters (airports + dates).
- Set passengers, output, proxy; run.
For both modes: enable Apify Proxy when possible, then export JSON or CSV.
Input configuration
Fields match .actor/input_schema.json. skyscannerMarket, skyscannerCurrency, and skyscannerLocale are optional; market and locale also feed the flight autosuggest URL used to resolve city/airport names to place IDs. skyscannerCurrency affects unified-search only. All three localization headers are sent on every unified-search request (initial POST and polling GET) so pricing and availability can match a specific Skyscanner region/locale in the browser.
Optional API-only fields (not in the visual schema) include:
| Field | Purpose |
|---|---|
flightOrigin / flightDestination | Alternate names for origin/destination resolution. |
outputFormat | "tabular" | "flattened" | "aggregated" | "both" | "one_row". Overrides the simple flattenOutput mapping when set. "both" also writes data-harvest.json on disk during the run. |
passengers | Deprecated; prefer top-level adults, children, infants. |
Example A — URL mode (round trip from link, YYMMDD in path)
{"startUrls": [{"url": "https://www.skyscanner.net/transport/flights/atl/ist/260615/260622/"}],"flattenOutput": true,"adults": 1,"children": 0,"infants": 0,"maxItems": 10000,"maxConcurrency": 100,"minConcurrency": 1,"maxRequestRetries": 30,"proxy": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
Example B — Filter mode (homepage + trip fields)
{"startUrls": [{"url": "https://www.skyscanner.net/"}],"flattenOutput": true,"adults": 1,"children": 0,"infants": 0,"departureAirport": "Atlanta","arrivalAirport": "Istanbul","departureDate": "2026-06-15","returnDate": "2026-06-22","maxItems": 10000,"maxConcurrency": 100,"minConcurrency": 1,"maxRequestRetries": 30,"proxy": {"useApifyProxy": true,"apifyProxyGroups": ["RESIDENTIAL"]}}
One-way: omit returnDate or set it to null / "" so the payload only includes the outbound leg set.
Output overview
- Tabular (default) — Many dataset items, one per itinerary; keys use dashes (e.g.
price-raw, nested paths flattened). - Flattened (nested per row) — One harvest-shaped itinerary object per dataset item (no full
bucketsenvelope). - Aggregated — One dataset item per search with:
buckets—Best,Cheapest,Fastest,Direct, each with anitemsarray of itineraries in live output.allFlights— Deduplicated list of itineraries.carriers/airports— ID → metadata maps.stats— e.g.totalFlights,uniqueCarriers,priceRange.
The sample below uses real values from the first object in data-mine.json, but shortened: bucket items arrays are replaced by itemsCount for readability; allFlights shows one itinerary with only the outbound leg and two segments (the full object has a return leg and more segments). carriers / airports are trimmed to entries present in the full run’s lookup maps for that sample.
Output samples
With flattenOutput: true, the actor instead emits one row per flight with dashed field names suitable for CSV.
{"buckets": {"Best": { "id": "Best", "name": "Best", "itemsCount": 138 },"Cheapest": { "id": "Cheapest", "name": "Cheapest", "itemsCount": 144 },"Fastest": { "id": "Fastest", "name": "Fastest", "itemsCount": 138 },"Direct": { "id": "Direct", "name": "Direct", "itemsCount": 16 }},"allFlights": [{"id": "9596-2606151035--32340-1-12585-2606162110|12585-2606222355--32340-2-9596-2606240855","price": {"raw": 2080.85,"formatted": "$2,081","pricingOptionId": "T7Ck9P5ZT5Zg"},"legs": [{"id": "9596-2606151035--32340-1-12585-2606162110","origin": {"id": "ATL","entityId": "95673800","name": "Atlanta Hartsfield-Jackson","displayCode": "ATL","city": "Atlanta","country": "United States","isHighlighted": false},"destination": {"id": "IST","entityId": "95673323","name": "Istanbul","displayCode": "IST","city": "Istanbul","country": "Türkiye (Turkey)","isHighlighted": false},"durationInMinutes": 1655,"stopCount": 1,"isSmallestStops": false,"departure": "2026-06-15T10:35:00","arrival": "2026-06-16T21:10:00","timeDeltaInDays": 1,"carriers": {"marketing": [{"id": -32340,"alternateId": "ET","logoUrl": "https://logos.skyscnr.com/images/airlines/favicon/ET.png","name": "Ethiopian Airlines"}],"operationType": "fully_operated"},"segments": [{"id": "9596-9252-2606151035-2606160750--32340","origin": {"flightPlaceId": "ATL","displayCode": "ATL","parent": {"flightPlaceId": "ATLA","displayCode": "ATL","name": "Atlanta","type": "City"},"name": "Atlanta Hartsfield-Jackson","type": "Airport","country": "United States"},"destination": {"flightPlaceId": "ADD","displayCode": "ADD","parent": {"flightPlaceId": "ADDA","displayCode": "ADD","name": "Addis Ababa","type": "City"},"name": "Addis Ababa","type": "Airport","country": "Ethiopia"},"departure": "2026-06-15T10:35:00","arrival": "2026-06-16T07:50:00","durationInMinutes": 855,"flightNumber": "519","marketingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"},"operatingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"}},{"id": "9252-12585-2606161525-2606162110--32340","origin": {"flightPlaceId": "ADD","displayCode": "ADD","parent": {"flightPlaceId": "ADDA","displayCode": "ADD","name": "Addis Ababa","type": "City"},"name": "Addis Ababa","type": "Airport","country": "Ethiopia"},"destination": {"flightPlaceId": "IST","displayCode": "IST","parent": {"flightPlaceId": "ISTA","displayCode": "IST","name": "Istanbul","type": "City"},"name": "Istanbul","type": "Airport","country": "Türkiye (Turkey)"},"departure": "2026-06-16T15:25:00","arrival": "2026-06-16T21:10:00","durationInMinutes": 345,"flightNumber": "722","marketingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"},"operatingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"}}]},{"id": "12585-2606222355--32340-2-9596-2606240855","origin": {"id": "IST","entityId": "95673323","name": "Istanbul","displayCode": "IST","city": "Istanbul","country": "Türkiye (Turkey)","isHighlighted": false},"destination": {"id": "ATL","entityId": "95673800","name": "Atlanta Hartsfield-Jackson","displayCode": "ATL","city": "Atlanta","country": "United States","isHighlighted": false},"durationInMinutes": 2400,"stopCount": 2,"isSmallestStops": false,"departure": "2026-06-22T23:55:00","arrival": "2026-06-24T08:55:00","timeDeltaInDays": 2,"carriers": {"marketing": [{"id": -32340,"alternateId": "ET","logoUrl": "https://logos.skyscnr.com/images/airlines/favicon/ET.png","name": "Ethiopian Airlines"}],"operationType": "fully_operated"},"segments": [{"id": "12585-9252-2606222355-2606230515--32340","origin": {"flightPlaceId": "IST","displayCode": "IST","parent": {"flightPlaceId": "ISTA","displayCode": "IST","name": "Istanbul","type": "City"},"name": "Istanbul","type": "Airport","country": "Türkiye (Turkey)"},"destination": {"flightPlaceId": "ADD","displayCode": "ADD","parent": {"flightPlaceId": "ADDA","displayCode": "ADD","name": "Addis Ababa","type": "City"},"name": "Addis Ababa","type": "Airport","country": "Ethiopia"},"departure": "2026-06-22T23:55:00","arrival": "2026-06-23T05:15:00","durationInMinutes": 320,"flightNumber": "721","marketingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"},"operatingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"}},{"id": "9252-11493-2606232200-2606240330--32340","origin": {"flightPlaceId": "ADD","displayCode": "ADD","parent": {"flightPlaceId": "ADDA","displayCode": "ADD","name": "Addis Ababa","type": "City"},"name": "Addis Ababa","type": "Airport","country": "Ethiopia"},"destination": {"flightPlaceId": "FCO","displayCode": "FCO","parent": {"flightPlaceId": "ROME","displayCode": "ROM","name": "Rome","type": "City"},"name": "Rome Fiumicino","type": "Airport","country": "Italy"},"departure": "2026-06-23T22:00:00","arrival": "2026-06-24T03:30:00","durationInMinutes": 390,"flightNumber": "518","marketingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"},"operatingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"}},{"id": "11493-9596-2606240430-2606240855--32340","origin": {"flightPlaceId": "FCO","displayCode": "FCO","parent": {"flightPlaceId": "ROME","displayCode": "ROM","name": "Rome","type": "City"},"name": "Rome Fiumicino","type": "Airport","country": "Italy"},"destination": {"flightPlaceId": "ATL","displayCode": "ATL","parent": {"flightPlaceId": "ATLA","displayCode": "ATL","name": "Atlanta","type": "City"},"name": "Atlanta Hartsfield-Jackson","type": "Airport","country": "United States"},"departure": "2026-06-24T04:30:00","arrival": "2026-06-24T08:55:00","durationInMinutes": 625,"flightNumber": "518","marketingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"},"operatingCarrier": {"id": -32340,"name": "Ethiopian Airlines","alternateId": "ET","allianceId": -31999,"displayCode": "ET"}}]}],"isSelfTransfer": false,"isProtectedSelfTransfer": false,"farePolicy": {"isChangeAllowed": false,"isPartiallyChangeable": false,"isCancellationAllowed": false,"isPartiallyRefundable": false},"fareAttributes": {},"tags": ["cheapest","shortest"],"isMashUp": false,"hasFlexibleOptions": false,"score": 1}],"carriers": {"-32340": {"id": -32340,"alternateId": "ET","logoUrl": "https://logos.skyscnr.com/images/airlines/favicon/ET.png","name": "Ethiopian Airlines"}},"airports": {"ATL": {"id": "ATL","entityId": "95673800","name": "Atlanta Hartsfield-Jackson","displayCode": "ATL","city": "Atlanta","country": "United States","isHighlighted": false},"IST": {"id": "IST","entityId": "95673323","name": "Istanbul","displayCode": "IST","city": "Istanbul","country": "Türkiye (Turkey)","isHighlighted": false}},"stats": {"totalFlights": 436,"totalBuckets": 4,"uniqueCarriers": 15,"uniqueAirports": 3,"priceRange": {"min": 1016,"max": 3959.23}}}
Tabular (illustrative) — With flattenOutput: true, expect dashed keys derived from the itinerary tree, for example: price-raw, price-formatted, legs-0-origin-displayCode, legs-0-segments-0-flightNumber, etc. Exact keys depend on nesting depth and optional fields.
Key output fields
| Group | Fields (high level) |
|---|---|
| Itinerary | id, tags, score, isSelfTransfer, farePolicy, fareAttributes |
| Price | price.raw, price.formatted, price.pricingOptionId |
| Legs | legs[].origin / destination (airport-level), departure, arrival, durationInMinutes, stopCount, carriers.marketing |
| Segments | legs[].segments[] — flightNumber, marketingCarrier, operatingCarrier, airport objects, times |
| Buckets | buckets.Best / Cheapest / Fastest / Direct — each with items[] of itineraries in full aggregated export |
| Lookup maps | carriers (numeric/string IDs), airports (IATA-style keys) |
| Stats | totalFlights, uniqueCarriers, uniqueAirports, priceRange, … |
FAQ
Which Skyscanner host does this use?
The integration targets www.skyscanner.net unified search (mobile-style client headers in code). URL parsing also accepts skyscanner.com links with the same /transport/flights/… path pattern.
What is the difference between URL mode and filter mode?
If startUrls contains a parseable /transport/flights/{origin}/{destination}/{YYMMDD}/… link, route and dates come from that URL and the “Scrape with search filters” fields are ignored for that request. Otherwise use the homepage URL and fill airports + dates. Passenger counts always come from the input form.
Can I run one-way searches?
Filter mode: leave returnDate empty or unset. URL mode: use a URL with only one YYMMDD segment after the airports (no second date segment), or omit the inbound segment if your copied link supports it.
Why did my run return fewer rows than expected?
Non-paying Apify accounts may hit stricter maxItems and startUrls limits (see actor logs). Also check HTTP errors, proxy quality, and Skyscanner errors in the API body.
Are prices guaranteed or bookable?
No. Values are as returned by Skyscanner for that search context; always validate on the airline or OTA before booking.
What about child ages?
The API currently uses placeholder ages for children and infants until the input form exposes real ages.
How do I get one big JSON blob instead of many rows?
Set outputFormat to aggregated in raw JSON input (not exposed in the default UI schema), or set flattenOutput: false for nested per-row objects without the full envelope.
Can I trust bearer tokens in the repo?
Tokens in source may expire; if runs fail with auth errors, the actor may need refreshed headers—contact the maintainer or update the implementation.
README image (optional)
For the Apify store listing, add a “How it works” diagram (input → unified search → dataset). Host the image on an Apify key-value store or raw.githubusercontent.com, not only a relative repo path, so it renders on the Console. See readme-stuff/README-GUIDELINES.md for sizing tips.
Support
- For issues or feature requests, please use the Issues section of this actor.
- If you need customization or have questions, feel free to contact the author:
- Author's website: https://muhamed-didovic.github.io/
- Email: muhamed.didovic@gmail.com
Additional Services
- Request customization or whole dataset: muhamed.didovic@gmail.com
- If you need anything else scraped, or this actor customized, email: muhamed.didovic@gmail.com
- For API services of this scraper (no Apify fee, just usage fee for the API), contact: muhamed.didovic@gmail.com
Explore More Scrapers
If you found this Skyscanner scraper useful, be sure to check out other scrapers and actors on memo23's Apify profile.