Skyscanner Flights Scraper
Get one-way, return and multi-city fares from Skyscanner for the routes and dates you choose, filtered by stops, airline, time of day.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
routes,searchUrls,market(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.000052 per itinerary = $0.052 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Itinerary | One flight itinerary returned. Routes that return nothing are not charged. | $0.000052 |
| Search completed | Each search whose full list came back, one per route and departure day, whatever your filters keep. Searches that are refused, left out to stay within your maximum charge or never finish aren't charged. | $0.005 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-09-15, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
routes | One search per route and date. A one-way route is {"origin": "JFK", "destination": "LAX", "date": "2026-10-20"} or the short form "JFK-LAX-2026-10-20". For a return, add "returnDate", or write "JFK-LAX-2026-10-20-2026-10-27". For a multi-city trip, put two or three legs in order under "legs", each with its own origin, destination and date. Add "lastDate" to a one-way or return route to search every departure day from "date" to it, 7 days at most: each day is a search of its own, so four days means four lists of itineraries to pay for, and on a return the return date moves along with it. Use airport codes such as LHR or JFK, or a city code such as LON, NYC or PAR for every airport in that city. With no date, a one-way route searches the day 30 days after the run. Up to 50 searches a run. They wait together, so five take about as long as one. | array |
searchUrls | Links to Skyscanner results pages, one per line, each run as a search. The airports, dates, adults, children's ages, cabin and 'direct flights only' come from the link; the market, currency and filters come from this form. A link for a whole month, or for more than three legs, is refused. If a link asks for nearby airports, only the airports it names are searched, and PROBLEMS says so. | array |
market | Which country's Skyscanner to search, as a two-letter code: US, UK, CA, DE and so on. For the United Kingdom it is UK; GB is accepted and treated as UK. | string |
locale | Locale sent with the search, such as en-US or en-GB. Keep it in step with the market. | string |
currency | Currency for the prices, as a three-letter code such as USD, GBP or EUR. | string |
adults | Adult passengers, 1 to 8. The price on each row is for everyone on the booking, children included, not a price per person. | integer |
childAges | One age per child: [8, 1] is an eight-year-old and a baby. Ages 0 to 17, up to 8 children. Under 2 counts as an infant, and each infant needs an adult. Leave it empty if only adults are flying. | array |
cabinClass | Which cabin to price. | string |
maxStops | Counted per leg, so on a return both directions have to pass. | string |
maxPrice | For the whole group, in the currency above. Anything dearer is dropped. | number |
maxDurationHours | Per leg, from its first take-off to its last landing, connections included. 7.5 is seven and a half hours. | number |
airlines | Two-character codes such as BA, U2 or B6, or names such as British Airways. An itinerary stays only if every flight in it is sold by one of them. | array |
excludeAirlines | Codes or names, as above. An itinerary is dropped if any flight in it is sold by one of them, or flown by one on another airline's behalf. | array |
departureTimeRange | When the outbound leg leaves, local time, on the 24-hour clock: 06:00-12:00. A range such as 22:00-06:00 runs past midnight. On a multi-city trip this and the arrival time apply to the first leg only. | string |
arrivalTimeRange | When the outbound leg lands, local time at the airport it lands at, such as 12:00-20:00. | string |
returnDepartureTimeRange | Return trips only: when the journey home leaves, local time, such as 15:00-21:00. | string |
returnArrivalTimeRange | Return trips only: when the journey home lands, local time. | string |
sortBy | Fastest counts the whole trip, both ways on a return. Best is this Actor's own ranking, not the one on Skyscanner's site: each itinerary's price divided by the cheapest one's, plus its journey time divided by the quickest one's, lowest first. | string |
maxItinerariesPerRoute | Taken from the top once the filters and the order have run, so Fastest first with 10 gives the ten quickest that pass. A busy route has several hundred itineraries and a return can have over a thousand, and you pay for each one delivered. | integer |
What you get
A structured dataset — each result includes fields like:
routedatereturnDatepricecurrencycheapestSellerpricingOptionscarriersflightNumbersdepartureAirportdeparturearrivalAirportarrivaldurationMinutesstopsitineraryIdExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
Related tools in Developer & Research Tools
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
GitHub Scraper
Search GitHub repos and users: stars, forks, language, topics, licence, plus user bio, company and followers. No token needed. $0.90 per 1,000 rows.
Stack Overflow / Stack Exchange Scraper
Search Stack Overflow and Stack Exchange by keyword or tag. Score, answer count, views, reputation and body text. $2 per 1,000 questions.
Package Registry Scraper (npm + PyPI)
Get npm and PyPI package metadata as JSON. Version, license, author, repo, keywords and npm monthly downloads. $2 per 1,000 packages.
arXiv Scraper
Search arXiv papers by title, author, abstract or category. Get full abstracts, authors, categories, DOI, dates and PDF links. $2 per 1,000 papers.
OpenAlex Scholarly Works Scraper
Search 250M+ OpenAlex papers with no API key. Get titles, authors, venue, year, citations, DOI, OA links and full abstracts. $2.00 per 1,000 papers.
Crossref Scholarly Works Scraper
Search 150M+ papers on Crossref: DOI, title, authors, journal, publisher, date, citations and abstract. No API key. $1.00 per 1,000 works.
Where this tool sits
- Categories
- Developer & Research Tools
Skyscanner Flights Scraper: fares for the routes and dates you pick, one-way, return or multi-city
Give it routes and dates, or paste Skyscanner links. Each search comes back as one row per priced itinerary: the lowest price, who is selling it, the airlines, the flight numbers, local departure and arrival times, journey length and stops.
The thing to plan around is the wait. A Skyscanner search takes about three minutes to settle, because that is how long the site itself takes to collect quotes. Searches in a run wait together, so five routes take about as long as one, but no single search comes back quickly.
| Input | Routes and dates, or Skyscanner links |
| Output | One row per itinerary, plus a PROBLEMS record |
| Ceiling | 50 searches per run, up to 1,000 itineraries each |
| Account needed | None |
| Price | $0.052 per 1,000 itineraries, plus $0.005 per completed search |
✈️ What Skyscanner Flights Scraper does
Three trip shapes, in one field. A one-way is {"origin": "JFK", "destination": "LAX", "date": "2026-10-20"}, or the short form "JFK-LAX-2026-10-20". Add returnDate and it is a return. Put two or three legs under legs and it is a multi-city trip.
Add lastDate to a one-way or return and the run searches every departure day from date to that day, seven at most. Each day is a search of its own, and on a return the return date moves along with the departure.
Airport codes like LHR work, and so do city codes like LON, NYC and PAR, which cover every airport in that city. Codes are checked before anything runs, so a typo is refused rather than quietly searched.
Filters and order run on the full list a search returned, before anything is delivered, so sortBy: "fastest" with maxItinerariesPerRoute: 10 gives the ten quickest that pass.
📥 What you give it
{
"routes": [
{ "origin": "JFK", "destination": "LAX", "date": "2026-10-20", "returnDate": "2026-10-27" },
"LHR-BCN-2026-11-03"
],
"market": "UK",
"currency": "GBP",
"maxStops": "1",
"sortBy": "cheapest",
"maxItinerariesPerRoute": 50
}
| Field | Default | What it is |
|---|---|---|
routes | none | Up to 50 entries, as objects or strings. A one-way with no date is searched 30 days from the run date. |
searchUrls | none | Skyscanner results links, up to 50. Airports, dates, passengers, cabin and "direct only" come from the link. |
market | US | Two letters. The United Kingdom is UK, and GB is accepted for it. |
locale | en-US | Keep it in step with the market. |
currency | USD | Three letters. |
adults | 1 | 1 to 8. |
childAges | none | One age per child, 0 to 17, up to 8. Under 2 counts as an infant and needs an adult. |
cabinClass | economy | economy, premium_economy, business or first. |
maxStops | any | 0, 1 or 2. Counted per leg, so on a return both directions must pass. |
maxPrice | none | For the whole group, in your currency. |
maxDurationHours | none | Per leg, first take-off to last landing. |
airlines, excludeAirlines | none | Codes like BA, U2, or names. Up to 30 each. |
departureTimeRange, arrivalTimeRange | none | 06:00-12:00, local time, outbound leg. A range like 22:00-06:00 runs past midnight. |
returnDepartureTimeRange, returnArrivalTimeRange | none | The same, for the journey home. |
sortBy | cheapest | Also fastest, earliest and best. |
maxItinerariesPerRoute | 500 | 1 to 1,000, taken from the top after the filters and the order. |
best is this actor's own ranking, not the one on Skyscanner's site. It is each itinerary's price over the cheapest price, plus its journey time over the quickest, lowest first. If you need Skyscanner's own idea of "best", this is not it.
Dates run from yesterday to 365 days out. A busy route has several hundred itineraries and a return over a thousand, so set maxItinerariesPerRoute deliberately: you pay for each one delivered.
📤 What you get back
A real row, from run a7USyKNkEZY5JHS8d, with the middle of its three flights cut out here:
{
"ok": true, "recordType": "itinerary",
"route": "JFK-MIA", "tripType": "one-way",
"date": "2026-10-24", "returnDate": null,
"price": 171, "currency": "USD", "pricingOptions": 2, "cheapestSeller": "Kiwi.com",
"carriers": ["jetBlue", "Frontier Airlines"],
"flightNumbers": ["B61201", "B61798", "F93442"],
"departureAirport": "JFK", "arrivalAirport": "MIA",
"departure": "2026-10-24T15:59:00", "arrival": "2026-10-25T10:15:00",
"durationMinutes": 1096, "stops": 2,
"legs": [
{ "from": "JFK", "to": "MIA",
"departure": "2026-10-24T15:59:00", "arrival": "2026-10-25T10:15:00",
"durationMinutes": 1096, "stops": 2,
"carriers": ["jetBlue", "Frontier Airlines"],
"flights": [
{ "flightNumber": "B61201", "carrier": "jetBlue", "carrierCode": "B6",
"operatedBy": null, "operatedByCode": null,
"from": "JFK", "to": "FLL",
"departure": "2026-10-24T15:59:00", "arrival": "2026-10-24T19:16:00",
"durationMinutes": 197 },
{ "flightNumber": "F93442", "carrier": "Frontier Airlines", "carrierCode": "F9",
"operatedBy": null, "operatedByCode": null,
"from": "ATL", "to": "MIA",
"departure": "2026-10-25T08:17:00", "arrival": "2026-10-25T10:15:00",
"durationMinutes": 118 }
] }
],
"itineraryId": "12712-2610241559--32171,-32289-2-14074-2610251015",
"market": "US", "locale": "en-US", "adults": 1, "childAges": [], "cabinClass": "economy",
"searchedAt": "2026-09-15T02:53:13.227Z"
}
| Field | What it is |
|---|---|
price | The total for everyone on the booking, children included. It is not a price per person. |
cheapestSeller, pricingOptions | Who has the lowest price, and how many sellers offer this itinerary. |
departure, arrival | Local time at each airport, with no time zone attached. Subtracting one from the other across time zones will give you the wrong answer: use durationMinutes. |
departureAirport, arrivalAirport | Where the whole trip starts and ends. On a return both are home. |
stops, durationMinutes | Whole-trip totals. The per-leg figures are inside legs. |
operatedBy | Filled in when one airline flies the route on another's behalf. null when it does not. |
itineraryId | Skyscanner's own id for the itinerary. Your dedupe key. |
route | JFK-MIA for a one-way or return, and every leg listed for a multi-city trip. |
🧾 Reading the output
The dataset holds itineraries and nothing else. No refusal rows, no notices, no blank lines in your table.
Anything that went wrong goes into a key-value record called PROBLEMS: one entry per search, with the route, the date, a code and a sentence in plain words. It is written on every way out of a run, as an empty list when nothing went wrong, so it is always there. RUN_SUMMARY sits beside it with the counts and your filters written out.
| Code | What it means |
|---|---|
BAD_INPUT | That route or link could not be read. The rest of the run carries on. |
NO_RESULTS | The search finished and Skyscanner had no priced itineraries for it. |
NO_MATCHES | The search finished and none of its itineraries passed your filters. The reason says how many it found. |
PARTIAL | The list was still filling when time ran out. What had arrived was delivered. |
NOT_ACCEPTED | Skyscanner refused the search, or answered a different one. Check codes, dates and passengers. |
NEARBY_NOT_SEARCHED | Your link asked for nearby airports. Only the airports it named were searched. |
UNAVAILABLE | The search could not be completed. Try it again. |
LIMIT_REACHED, LIMIT_TOO_LOW, RUN_LIMIT, TIME_BUDGET | The run stopped short of that route. The entry says which of the four it was. |
▶️ How to run it
1. Open Skyscanner Flights Scraper and click Try for free. 2. Put your trips in Routes, or paste results links into Skyscanner links. 3. Set Market, Currency and the passengers. 4. Open Filters and order and set Maximum itineraries per search before anything else. 5. Click Start, wait about three minutes, then read the dataset and the PROBLEMS record.
💰 How much does it cost?
$0.052 per 1,000 itineraries, plus $0.005 for each search that finishes. Both rates are the same on every Apify plan, with no volume tiers.
A search that finishes and finds nothing, or finds nothing that passes your filters, still counts as a finished search. A search that is refused, is invalid, could not run, or was cut short before its list finished is not counted, and a cut-short search still delivers the itineraries it had.
Each day of a lastDate range is a search of its own, so a four-day range is four searches.
💡 What people use it for
- Watching one route daily and recording where the cheapest fare moves.
- Comparing a week of departure days at once with
lastDate, to find the cheap day to fly. - Pulling non-stop business fares on a corporate route and feeding them into a travel policy.
- Checking what a competitor's hub pair actually costs before pricing something against it.
- Building a fare history keyed on
routeanddate, withsearchedAtas the timestamp.
🚧 What it does not do
- No booking and no seat availability. These are advertised prices and they move. Treat a row as
a quote from the moment in searchedAt.
- No nearby-airport expansion. A link that asks for it gets the named airports only, and says so
in PROBLEMS. Use a city code if you want every airport in a city.
- No whole-month searches. A month link is refused. Use
lastDate, up to seven days. - Two or three legs on a multi-city trip, no more, and
lastDatedoes not apply to them. - Times carry no time zone. They are local at each airport, exactly as Skyscanner publishes them.
bestis our ranking, not Skyscanner's.- Prices are for the whole party. Divide it yourself if you want a per-person figure.
- 50 searches in a run. Anything past that is reported in
PROBLEMSand left for another run. - Each search takes about three minutes and cannot be hurried. They do run together.
- No baggage, fare rules, seat maps or loyalty pricing.
🧭 Which travel scraper do you need?
| If you want | Use |
|---|---|
| Flight fares for a route and date | This one |
| Hotel prices on Booking.com for your dates | Booking.com Hotels Scraper |
| Hotel prices from Google Hotels | Google Hotels Scraper |
| Guest reviews for a property | Booking.com Reviews Scraper |
| Reviews of hotels, restaurants and attractions | Tripadvisor Reviews Scraper |
❓ Questions people ask
Do I need a Skyscanner account or an API key? No. Nothing to paste in and nothing to renew.
Why did my run take three minutes for one route? Because the search itself does. Put all your routes in one run: they wait together, so fifty take about as long as one.
Why did I get no rows but a PROBLEMS entry? Either Skyscanner had no priced itineraries (NO_RESULTS) or your filters removed all of them (NO_MATCHES). The reason on the entry says how many it found before filtering.
Can I search a whole month? Not in one go. Use lastDate for a range of up to seven departure days, which is seven searches.
Is the price per person? No. It is the total for everyone on the booking, infants included.
Why is the same flight listed twice? Two rows with the same flight numbers are different itineraries, usually different seller combinations. itineraryId separates them.
🆘 If something breaks
Open the Issues tab on the actor page. Send the run ID and the routes you used, and paste the PROBLEMS record from the run's key-value store. It names the route and the reason for every search that did not deliver.