Twenty-six years of US air service as clean JSON: flown seat capacity, hub-adjusted local demand, routes, carriers, fleets and aircraft types for 130 airports and 22 airlines โ including the dead ones. Free, no key, no rate limit, CORS open. Plus a drop-in embed kit to put the plates on your own page.
# one airport, everything we know about it
curl https://www.runwayindex.ai/api/v1/airports/RDU.json
# in the browser โ CORS is open
const rdu = await (await fetch(
"https://www.runwayindex.ai/api/v1/airports/RDU.json")).json();
rdu.seats.at(-1) // 9,966,000 departing seats in 2025
rdu.routes[0] // { dest: "ATL", seats: [...26], monthsServed: [...26] }
Everything is a static file under /api/v1/ โ cacheable, versioned, refreshed
once a year when the federal data lands. Every series is 26 values aligned to the
years array (2000โ2025).
| ENDPOINT | WHAT YOU GET |
|---|---|
/api/v1/index.json | manifest: coverage, endpoints, notes |
/api/v1/national.json | national seats, passengers and load factor by year |
/api/v1/airports.json | all 130 airports: identity, seat series, hub-adjusted local series |
/api/v1/airports/{IATA}.json | the full record โ see field reference below |
/api/v1/airlines.json | 22 national carrier profiles with slugs |
/api/v1/airlines/{slug}.json | per-carrier: seats, load, national share, fleet mix, hub network |
/api/v1/airports/{IATA}.json โ the big one. Units: seats and passengers are
real annual counts; every share and load factor is a fraction (0.392 = 39.2%).
| FIELD | MEANING |
|---|---|
seats | departing seats on scheduled passenger flights, capacity actually flown |
localSeats | hub-adjusted local demand: domestic seats ร local origin share + international seats. A hub's raw count reflects its airline's connecting bank; this strips it out |
localShare2024 | share of departing passengers starting their trip here, 2024 |
passengers, loadFactor | passengers flown; passengers รท seats |
routes[] | every nonstop market: dest, seats per year, monthsServed per year (12 = year-round, 1โ11 = seasonal or partial) |
carriers[] | top operators: seat share, loadFactor, passengers, dominant aircraft topType per year, and their own top routes |
fleetMix | seat share flown on widebody / narrowbody / regional jet / turboprop |
topTypesByYear, typeStrips | top aircraft types per year, and 26-year share strips for the top types, with dominant carrier |
intlShare, intlSeats, intlRegions | international share of seats, absolute international seats, top world regions served |
Two files, no dependencies, no build step. Drop a div on any page and it renders a live plate from the API in the Runway Index style.
<link rel="stylesheet" href="https://www.runwayindex.ai/kit/runway.css">
<script src="https://www.runwayindex.ai/kit/runway.js" defer></script>
<div data-runway="seats" data-airport="PDX"></div>
<div data-runway="fingerprint" data-airport="AUS"></div>
<div data-runway="routes" data-airport="RDU"></div>
Three plates: seats (annual bars), fingerprint (year-over-year heat
cells), routes (top nonstops as 26-year intensity strips). Add
data-metric="local" to seats or fingerprint for the
hub-adjusted series. For dynamic pages, window.Runway.scan() renders any divs you
added after load, and Runway.fetchAirport("JFK") hands you the raw record.
Derived from public-domain US government flight statistics; the derived dataset is free for
any use, commercial or not. Attribution appreciated, not required โ a link to
www.runwayindex.ai does nicely.
Domestic itinerary sampling means international seats count as fully local in the
hub adjustment, which over-credits gateways like MIA. 2020โ21 is a COVID cliff, not a data
error. Aircraft with fewer than roughly 60 seats flown on a segment classify as regional.
The schema under /v1/ won't change shape; new years append to every series.
Embeds send one anonymous render ping (airport, plate, host page) so we know the kit is being
used โ add data-telemetry="off" to the script tag to disable it.