Kayak Multi-OTA Fare Comparison Scraper
Pricing
from $4.00 / 1,000 flight with seller prices founds
Kayak Multi-OTA Fare Comparison Scraper
Every seller's price for the same flight, side by side. One row per flight with up to 40 agency and airline prices, carry-on and checked-bag fees, fare types and a direct booking link. Pick a route, a date and a market, and see who sells that exact seat cheapest.
Most flight scrapers give you one price per flight. This one gives you every price per flight — the same seat, the same aircraft, the same departure time, quoted by every online travel agency and airline selling it, side by side on one row, with the carry-on and checked-bag fees that decide the real all-in cost. On a single New York to Los Angeles flight that is eight sellers between $176 and $181; on London to New York it is twenty. If you price flights for a living — an agency, an airline revenue team, a metasearch product, a corporate travel desk — this is the row you have never been able to buy off the shelf.
What you can do with it
- See who undercuts you, and by how much. One row per flight tells you the cheapest seller, the typical seller, the dearest, and the gap between them — measured only across sellers quoting the same cabin, so a first-class fare never masquerades as a competitor's economy price.
- Compare the real all-in price, not the teaser. Carry-on status, first and second checked-bag fees and the fare types each seller offers come attached, so a $176 fare that costs $67 for a bag can be ranked against a $199 fare that includes one.
- Watch a route across markets. The same seat is often sold by eleven agencies in one country's storefront and two in another, at genuinely different prices. Choose the market and the fares come back the way travellers there see them.
- Build fare and repricing models. Airline, flight number, aircraft type, departure and arrival times, journey length, stops and every layover airport are on the row, so seller pricing can be joined to schedule and equipment.
- Track a route over time. Schedule a daily run on the routes you care about and keep the history: which seller was cheapest, how wide the field was, when a seller entered or left.
- Feed a booking or comparison product. Every seller price carries a direct link straight to that seller's offer for that exact flight.
What you get
One record per flight. Abridged — a real record from a New York to Los Angeles search, trimmed to fit here:
{"origin": "JFK","destination": "LAX","departureDate": "2026-12-08","tripType": "one_way","cabinClass": "economy","price": 176,"currency": "USD","cheapestProviderName": "Cheapflightsfares","cheapestFareCabin": "economy","medianSellerPrice": 179,"highestSellerPrice": 181,"priceSpreadAbs": 5,"priceSpreadPct": 2.8,"sellerCount": 8,"comparableSellerCount": 8,"offerCount": 22,"carryOnBagStatus": "included","carryOnBagFee": 0,"checkedBagStatus": "fee","checkedBag1Fee": 67,"checkedBag2Fee": 149,"priceWithFirstCheckedBag": 243,"isFreeCancellation": true,"airlineNames": ["JetBlue"],"flightNumbers": ["B6701", "B62501"],"aircraftTypes": ["Airbus A220-300", "Airbus A318/A319/A320/A321"],"departureAirport": "JFK","arrivalAirport": "LAX","departureLocal": "2026-12-08T13:45:00","arrivalLocal": "2026-12-08T20:52:00","totalDurationMin": 607,"stops": 1,"layoverAirports": ["FLL"],"layoverDurationsMin": [66],"sellerPrices": [{ "provider": "CHEAPFLIGHTSFARES", "providerName": "Cheapflightsfares","price": 176, "currency": "USD", "cabin": "economy","checkedBag1Fee": 67, "isFreeCancellation": true, "bookingUrl": "https://www.kayak.com/…" },{ "provider": "EXPEDIAAIR", "providerName": "Expedia","price": 178, "currency": "USD", "cabin": "economy","checkedBag1Fee": null, "isFreeCancellation": true, "bookingUrl": "https://www.kayak.com/…" },{ "provider": "CHEAPOAIR", "providerName": "CheapOair","price": 178, "currency": "USD", "cabin": "economy","checkedBag1Fee": 49, "isFreeCancellation": true, "bookingUrl": "https://www.kayak.com/…" }],"bagAllowances": [{ "airline": "B6", "bagType": "personal", "dimensions": "Up to 16 x 12 x 7in", "weight": null },{ "airline": "B6", "bagType": "carryon", "dimensions": "Up to 21 x 13 x 8in", "weight": null }],"fareFamilies": [{ "fareName": "Main Base", "price": 176, "carryOnBag": "included", "checkedBag": "fee","checkedBag1Fee": 67, "seatSelection": "fee", "changes": "fee", "refundable": "not_available" },{ "fareName": "Main", "price": 215, "carryOnBag": "included", "checkedBag": "fee","seatSelection": "included", "changes": "included", "refundable": "not_available" }],"market": "US","collectedAt": "2026-08-16T18:42:11.204Z","bookingUrl": "https://www.kayak.com/…"}
sellerPrices is the whole point: one entry per published offer, cheapest first,
each with its own price, cabin, bag fee, free-cancellation flag and direct link.
A busy route returns up to forty of them on a single flight.
Input reference
| Field | Type | Default | What it does |
|---|---|---|---|
origin | text | — | Where the trip starts. An airport code (JFK), a city-wide code covering every airport in the city (NYC, LON, PAR), a city name, or a comma-separated list of airports (JFK,LGA,EWR). |
destination | text | — | Where the trip ends. Same formats as origin. |
departureDate | date | — | Outbound date, YYYY-MM-DD. Today or later, up to about a year ahead. |
returnDate | date | empty | Return date, YYYY-MM-DD. Leave empty for one way. |
extraSearches | list | empty | Run several routes and dates in one go — each entry takes origin, destination, departureDate and optionally returnDate. Up to 30 searches per run. |
market | choice | US | Which country's storefront to price against: United States, United Kingdom, Germany, France or Spain. Decides the currency and which sellers appear. |
cabinClass | choice | economy | economy, premiumEconomy, business or first. |
adults | number | 1 | Adult travellers, 1 to 8. |
childAges | list | empty | One entry per child, giving each child's age in years (0–17). Up to 6. |
stopsFilter | choice | any | any, nonstop, or upToOneStop. |
sortBy | choice | best | best, cheapest, fastest, earliestDeparture or lowestEmissions. Decides which flights you keep when you cap the result count. |
maxResultsPerSearch | number | 50 | Flights returned per route and date, 1 to 200. |
maxSellersPerFlight | number | 40 | Seller prices kept on each flight, cheapest first, 1 to 40. |
searchesInParallel | number | 2 | How many of your searches run at once, 1 to 4. |
You do not need an account anywhere, and you never supply a login, a password or anything private. Fill in a route and a date and press start.
Output fields
| Field | What it is |
|---|---|
origin, destination, departureDate, returnDate, tripType, cabinClass, adults, childAges | The search this row answers. |
price, currency | The cheapest published price for this exact flight, in the currency the market actually quoted. |
cheapestProvider, cheapestProviderName, cheapestProviderCountry | Who is selling it at that price. |
cheapestFareCabin | The cabin that cheapest offer is actually selling. |
medianSellerPrice | The middle of the field — what this seat normally sells for. |
highestSellerPrice, priceSpreadAbs, priceSpreadPct | The dearest comparable seller and the gap to the cheapest, in money and as a percentage. |
sellerCount | How many different sellers published a price for this flight. |
comparableSellerCount | How many of them quoted the same cabin as the cheapest — the number the gap is measured across. |
offerCount, distinctFareCount | Total offers on the flight, and how many distinct fare types. |
sellerPrices[] | Every offer: provider, providerName, sellerCountry, price, currency, cabin, carryOnBagFee, checkedBag1Fee, checkedBag2Fee, priceWithCarryOn, priceWithFirstCheckedBag, isFreeCancellation, isSplitBooking, bookingUrl. |
carryOnBagStatus, carryOnBagFee | Whether a carry-on is included on the cheapest offer, and what it costs if not. |
checkedBagStatus, checkedBag1Fee, checkedBag2Fee | First and second checked-bag fees on the cheapest offer. |
priceWithCarryOn, priceWithFirstCheckedBag | The all-in price once the bag is added. Empty when the fee was not published — never assumed to be free. |
bagAllowances[] | Published size and weight limits per carrier, by bag type. |
fareFamilies[] | Each fare type on the flight with its price and what it includes: carry-on, checked bag and its fees, seat selection, legroom, changes, refundability. |
isFreeCancellation, freeCancellationSellers, hasSplitTicketOffer | Cancellation terms, and whether any offer is two separate tickets rather than one. |
airlineCodes, airlineNames, flightNumbers, aircraftTypes | Who operates it and on what. |
departureAirport, arrivalAirport, departureLocal, arrivalLocal | Where the outbound leg starts and finishes, and the local times. |
outboundDurationMin, outboundStops, returnDepartureLocal, returnArrivalLocal, returnDurationMin, returnStops | The same per direction on a return trip; empty on a one-way. |
totalDurationMin, stops, layoverAirports, layoverDurationsMin | Journey length across all legs, the most stops on any leg, and every layover with its length in minutes. |
legs[] | Full per-leg detail, down to each individual flight: airline, flight number, airports, times, minutes, aircraft. |
bookingUrl, flightUrl | A direct link to the cheapest offer, and to the flight itself. |
market, source, collectedAt, itineraryId, searchKey | Which market this was priced in, when it was collected, and stable identifiers for joining runs together. |
resultRank, isBestValue, isCheapestOnRoute, isCheapestNonstop | How the source itself ranked this flight against the others in the same search. |
isCachedSnapshot | true when the search was answered from recently stored results rather than searched fresh. Worth knowing before you treat a price as this minute's. |
Alongside the table, every run writes a summary recording how many searches ran, how many returned flights, how many genuinely had none, and how many could not be completed — kept strictly apart, so "nothing found" and "could not be read" are never confused for one another.
It also carries one line per route and date, with cheapestPrice, currency,
cheapestSeller and sellersOnCheapest for that search. Those are measured
across the rows that search actually delivered, not read off the top of the
table, so they mean the same thing whichever sortBy you chose — handy when you
run thirty routes and want the best fare on each without opening the dataset.
Pricing
You pay for what you get, with no monthly fee.
| What is charged | Price |
|---|---|
| Each flight returned, with all its seller prices | $4.00 per 1,000 |
| Each route-and-date searched | $0.030 each |
A flight row is priced above an ordinary marketplace row because it is not one price — it is up to forty of them for the same seat, plus a normalised baggage matrix and the fare types behind each one. The per-search charge exists because a search is real work whatever it returns: one route on one date is taken all the way to completion before anything is returned, and a quiet route that yields six flights costs the same effort as a busy one that yields two hundred.
Worked example. Five routes, one date each, 50 flights per search:
- 250 flights returned → 250 × $0.004 = $1.00
- 5 route-and-date searches → 5 × $0.030 = $0.15
- Total: $1.15 — for roughly two thousand individual seller prices.
A search on a route that genuinely has no flights on that date still counts as a route-and-date searched, because the work was done and the answer is a real one. A search that could not be completed is not charged.
Limits & what this actor cannot do
- Fares are a snapshot. Airline pricing changes continuously and a fare seen
now may be gone minutes later. Treat every row as true at
collectedAt. - It reports what the source publishes to the public. It does not hold seats, does not book, and cannot guarantee a fare is still available when you go to buy it.
- A refused search is reported as a failed search, never as "no flights found". If the source declines to answer, you get an explicit failure in the run summary and no fabricated empty result. This matters more than it sounds: an empty table that should have been an error is the one outcome you cannot detect after the fact.
- Paid placements are dropped, not published. The source repeats its top flight as an advertisement carrying a shortened seller list and a promotional link. That copy is discarded and the flight's own row is kept instead, so the seller count, the price gap and the booking link on every row describe the real market for that seat rather than one agency's placement.
- Nothing is estimated. A fee the source did not publish comes back empty, not as zero, and an all-in price is only produced where the fee was actually published. No price is ever carried across dates or filled in.
- Fares and sellers differ by market. The same seat can be sold by eleven agencies in one market and two in another at genuinely different prices. Those are different inventories, not a currency conversion — never convert between them, and compare only within one market.
- A wide price gap usually means different fare rules, not a bargain. The gap
is measured only across sellers quoting the same cabin, but within one cabin a
fully flexible ticket and a basic one are still both "economy".
medianSellerPriceis the more stable comparison. - Some searches are answered from recently stored results. Those rows are
flagged
isCachedSnapshot. They can carry fewer sellers and a higher price than a fresh search of the same route. - Routes are seasonal. A real route with nothing flying on the dates you searched is reported as having none — that is an answer, not an error.
- Multi-city trips are not offered. One way and return only.
- The source publishes a limited number of results for any one search, so a very broad search returns what it makes available rather than an unlimited list.
- Speed depends on the size of the job and on how quickly the source itself answers. No fixed throughput is promised; a return trip takes appreciably longer than a one-way.
- The source's terms govern automated access. You are responsible for using the data lawfully and in line with those terms, and for handling any personal data in line with applicable privacy law.
FAQ
Do I need an account on Kayak? No. Nothing is signed into and nothing is registered.
Does it need my login or password? No. The only things you provide are a route, a date and a few preferences.
Can I schedule it? Yes. Schedule it daily or twice daily on the routes you care about and keep the history — that is where the value compounds, because you can see which seller moved and when. Anything tighter than that is not worth paying for: prices on this kind of route do not move minute to minute.
Are these fares bookable? They are the prices published at the moment of collection, and every one carries a direct link to that seller's offer. They are not held, not reserved, and not guaranteed — airline pricing moves continuously, and a fare can be gone before you reach the checkout.
Why does one flight have eight sellers and another only one?
Because that is what the market publishes. Popular routes attract many agencies;
a thin route or a premium cabin may only be sold by the airline itself. The row
tells you the truth either way, and sellerCount is never padded.
Why is one seller $2,000 dearer than another for the same flight?
Almost always because they are selling a different fare type — a fully flexible
or refundable ticket rather than a basic one. cheapestFareCabin and each
offer's own cabin let you tell them apart, and medianSellerPrice gives you the
typical price without the outlier.
What happens if a search cannot be completed? It is recorded as a failed search in the run summary, with the reason, and it is not charged. It is never quietly turned into an empty result.
Can I get more than 200 flights on one route and date? No. The source publishes a bounded set of results for any single search. If you need broader coverage, split the job across more dates or more airports rather than expecting one search to return everything.