Airport API Tutorial: Worldwide Airport Data + Schedules in 50 Lines

Tutorial, Guide, Build, Code Examples, Airport API, Airport Data, Schedules

Author
Sergey St.
Share:

Building anything that touches air travel — a flight tracking app, a logistics dashboard, an airport transfer service, a chatbot for travellers — usually starts with the same problem. You need reliable airport data. IATA codes, geo coordinates, timezones, country mappings, live departures, real arrivals. And it tends to live in scattered places: PDFs from regulators, government databases that update twice a year, scraped Wikipedia tables, outdated CSVs from a 2017 dataset.

A proper airport API solves this in one call. In the next fifty lines of code you'll go from a blank file to a working airport dashboard that knows every commercial airport in the world, finds the nearest ones to any coordinates, autocompletes user input, and pulls live departures and arrivals. If you're new to working with aviation data more broadly, the travel APIs integration guide is a good companion read — it covers how the airport layer fits into the broader picture of flights, schedules, routes and airlines.

Everything here uses the AirLabs Airport Database API. The code samples are Python because it keeps the line count honest, but every call is plain HTTP plus JSON. The same pattern works in Node, Go, PHP, or whatever your stack runs.

Setting up

You need one thing: an API key. Sign up on the AirLabs dashboard and copy the key from your profile. The free tier covers every endpoint in this walkthrough, so there's no need to commit to a plan before you've tried it.


https://airlabs.co/api/v9/flight?flight_iata=BA117&_fields=status,delayed,dep_gate,dep_terminal&api_key={KEY}

That's the entire setup. No SDK, no auth flow, no client library to keep in sync with a backend release schedule. Just a key and an HTTP client.

Step 1: Look up an airport by IATA code

The simplest call in the whole API. Pass an IATA or ICAO code, get the full airport record back.

def get_airport(iata):
    r = requests.get(f"{BASE}/airports", params={
        "iata_code": iata,
        "api_key": API_KEY,
    })
    return r.json()["response"]

print(get_airport("JFK"))

A trimmed version of what comes back:

{
  "name": "John F Kennedy International Airport",
  "iata_code": "JFK",
  "icao_code": "KJFK",
  "city": "New York",
  "city_code": "NYC",
  "country_code": "US",
  "lat": 40.6413,
  "lng": -73.7781,
  "timezone": "America/New_York",
  "type": "airport",
  "popularity": 95
}

This is everything you need to identify an airport in a product: a human-readable name for UI, both IATA and ICAO codes for cross-referencing other data sources, exact coordinates for map placement, the timezone the airport operates in (critical for any scheduling logic), and a popularity score so you can sort search results by relevance rather than alphabetically.

If your application needs the full reference set of airport codes — building dropdowns, validating user input, importing into a database — the complete IATA codeset lives in the IATA Codes Database. For broader geographical context like cities, countries and timezones, there's a separate Cities Database API you can use alongside.

Step 2: Find airports near a location

A surprising number of products need this. Given a user's GPS position, a hotel address, a delivery pickup point, an event venue — what airports are within reach? The NearBy Airport API takes coordinates plus a radius and returns sorted results.

def nearby_airports(lat, lng, distance_km=100):
    r = requests.get(f"{BASE}/nearby", params={
        "lat": lat,
        "lng": lng,
        "distance": distance_km,
        "api_key": API_KEY,
    })
    return r.json()["response"]["airports"]

# Airports within 100km of central London
for ap in nearby_airports(51.5074, -0.1278):
    print(f"{ap['iata_code']} - {ap['name']} ({ap['distance']:.1f} km)")

Output:

LCY - London City Airport (10.5 km)
LHR - London Heathrow Airport (22.4 km)
LGW - London Gatwick Airport (40.8 km)
LTN - London Luton Airport (45.1 km)
STN - London Stansted Airport (54.8 km)
SEN - London Southend Airport (60.9 km)

Each result includes the same metadata as Step 1 plus a distance field in kilometres. This is what powers "nearest airport" pickers in transfer apps, multi-airport flight search in booking platforms, and the kind of "what are my options if I land at X?" features in travel planning tools.

The same endpoint also accepts a city_code if you want all airports serving a particular metro area rather than a strict radius around a single point.

Step 3: Airport autocomplete

Users rarely know IATA codes off the top of their head. They type "heathrow" or "frankf" or "kennedy", expect the input to figure out what they mean. The Airport Autocomplete API does fuzzy matching across airport names, city names and codes in one call.

def autocomplete(query):
    r = requests.get(f"{BASE}/suggest", params={
        "q": query,
        "api_key": API_KEY,
    })
    return r.json()["response"]

# A partial, slightly off query
print(autocomplete("frankf"))

Returns:

[
  {
    "name": "Frankfurt am Main Airport",
    "iata_code": "FRA",
    "city": "Frankfurt am Main",
    "country_code": "DE",
    "type": "airport"
  },
  {
    "name": "Frankfurt Hahn Airport",
    "iata_code": "HHN",
    "city": "Frankfurt",
    "country_code": "DE",
    "type": "airport"
  }
]

Plug this directly into a typeahead component. It's the same pattern that powers the airport search box in most flight booking flows — the only difference being you no longer need to maintain your own airport reference file or wire up Elasticsearch for fuzzy matching.

Step 4: Real-time airport schedules

Now the live part. Once you've identified an airport, you usually want to know what's happening there right now. Which flights are leaving, which are arriving, which are running late. The Flight Schedules API returns a real-time departure or arrival board for any airport.

def airport_departures(iata, limit=10):
    r = requests.get(f"{BASE}/schedules", params={
        "dep_iata": iata,
        "api_key": API_KEY,
    })
    return r.json().get("response", [])[:limit]

def airport_arrivals(iata, limit=10):
    r = requests.get(f"{BASE}/schedules", params={
        "arr_iata": iata,
        "api_key": API_KEY,
    })
    return r.json().get("response", [])[:limit]

A single departure record:

{
  "airline_iata": "BA",
  "flight_iata": "BA286",
  "dep_iata": "LHR",
  "dep_terminal": "5",
  "dep_gate": "A12",
  "dep_time": "2026-05-25 14:30",
  "dep_estimated": "2026-05-25 14:45",
  "arr_iata": "SFO",
  "arr_time": "2026-05-25 17:10",
  "status": "scheduled",
  "delayed": 15
}

Everything a passenger-facing UI or operations dashboard cares about. Terminal and gate for wayfinding. The dep_time field is the scheduled time; dep_estimated updates if the flight slips — when those values differ, the flight is delayed by exactly delayed minutes. The status field drives colour coding on a board: scheduled, en-route, landed, cancelled. The full set of status values and how flights transition between them is covered in detail in the flight tracking lifecycle guide — worth a read if your dashboard needs to distinguish between, say, a flight that's about to push back and one that's actively taxiing.

For airports with hundreds of daily movements you'll want to filter and paginate rather than asking for everything at once. The endpoint accepts time windows and airline filters for that reason.

Step 5: Putting it together — the 50-line dashboard

Here's the full script. It takes a city or airport name, finds the right airport via autocomplete, then prints the next departures and arrivals as a clean board.

import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://airlabs.co/api/v9"


def call(endpoint, **params):
    params["api_key"] = API_KEY
    r = requests.get(f"{BASE}/{endpoint}", params=params)
    return r.json().get("response", [])


def find_main_airport(query):
    matches = call("suggest", q=query)
    return matches[0] if matches else None


def fmt(f, direction):
    other = "arr_iata" if direction == "dep" else "dep_iata"
    arrow = "→" if direction == "dep" else "←"
    status = f.get("status", "?").upper()
    delay = f"+{f['delayed']}m" if f.get("delayed") else ""
    return (
        f"{f.get('flight_iata', '???'):>7}  {arrow} "
        f"{f.get(other, '???')}  "
        f"{f.get(f'{direction}_time', '?'):16}  "
        f"{status:10}  {delay}"
    )


def dashboard(query):
    airport = find_main_airport(query)
    if not airport:
        print(f"No airport found for '{query}'")
        return

    iata = airport["iata_code"]
    print(f"\n{airport['name']} ({iata}) — "
          f"{airport['city']}, {airport['country_code']}")
    print("=" * 60)

    print("\nDEPARTURES")
    for f in call("schedules", dep_iata=iata)[:10]:
        print(fmt(f, "dep"))

    print("\nARRIVALS")
    for f in call("schedules", arr_iata=iata)[:10]:
        print(fmt(f, "arr"))


if __name__ == "__main__":
    dashboard("Heathrow")

Forty-nine lines including imports and blank lines. Run it and you get a clean text board for Heathrow right now. Swap "Heathrow" for "Frankfurt", "Dubai", "JFK", or anything else — the same script produces a fresh board for any airport in the world without changing a single line of code.

A few practical notes before you ship it

The fifty-line version above is intentionally minimal so it fits in your head. Before this goes into anything that real users will hit, three things are worth handling.

Cache aggressively for reference data. Airport metadata — names, coordinates, IATA codes, timezones — does not change minute to minute. If you're showing the same airport to twenty users a second, you don't need twenty API calls. Cache the result of the airport lookup endpoint for at least 24 hours; in most production setups, indefinitely with a manual invalidation when needed. Schedules are different — those should be cached for at most a minute or two, and only if you're sure a sixty-second-old departure board is acceptable for your use case.

Handle the empty response. If you request the schedules for an airport that has no movements in the queried window — small regional fields at night, for example — the API returns an empty response list. The script above handles this gracefully because we use .get("response", []), but worth being explicit about in production code so users see something more useful than a blank screen.

Respect rate limits and back off on 429. Every API has them, and the free tier of the AirLabs API is no exception. Add a simple retry-with-backoff around the call() helper for production: if you get a 429, wait a few seconds and retry once. Don't hammer the endpoint in a tight loop.

import time

def call(endpoint, retries=2, **params):
    params["api_key"] = API_KEY
    for attempt in range(retries + 1):
        r = requests.get(f"{BASE}/{endpoint}", params=params)
        if r.status_code == 429 and attempt < retries:
            time.sleep(2 ** attempt)
            continue
        return r.json().get("response", [])

None of this changes the architecture of the dashboard — it's still four endpoint calls behind a tiny helper. It just makes the dashboard ship-ready instead of demo-ready.

Going further

Once airport data is wired in, the rest of the AirLabs platform composes naturally with what you've built.

For live aircraft positions on top of your airport board, the Real-Time Flights API returns every flight currently airborne with coordinates, altitude, speed and heading. Filter by dep_iata or arr_iata and you can show the flights connected to your airport on a map.

For route planning and connection logic, the Routes Database lists every regularly scheduled route in the world. Combine it with airport data to answer "where can I fly direct from BCN?" or to validate connection feasibility in a travel planner.

When a user clicks a specific flight on your departure board and wants the full picture, the Flight Information API returns everything for that single flight: aircraft model, registration, full duration, the precise sequence of times and statuses.

For long-running analysis — building on-time performance dashboards, computing year-over-year delay trends, or auditing past schedules — the live schedules endpoint is the wrong tool. The historical flight data archive is the dedicated companion for accumulated records over time, separate from the rolling operational window the live API covers.

And for production setups where polling the schedules endpoint every minute starts to feel wasteful, the Flight Alert API lets you subscribe to specific flights and receive webhook notifications on status changes. Push instead of pull, with the same JSON shape.

Every one of these endpoints uses the same ?api_key= auth and returns predictable, flat JSON. The work you put into the airport dashboard generalises across the whole platform.

Where this code actually ends up

Some places where this exact pattern shows up in production:

Airport transfer services use NearBy to find the airport closest to a pickup address, then schedules to adjust booking times based on actual flight ETA rather than the scheduled arrival a passenger gave them three days ago.

Travel chatbots use autocomplete for the airport input, departures for "is my flight on time?", and the Flight Information API for "where exactly is my plane right now?".

Operations dashboards — ground handling teams, hotels near airports, ride-share dispatchers — use the schedules endpoint to plan staffing and resources around what's actually happening rather than yesterday's plan.

Map and visualisation projects use the lat/lng fields from the Airport Database API directly with Leaflet or Mapbox, then layer the Real-Time Flights API on top for a live airspace view of any region.

Travel data analysis combines the static airport reference set with operational schedules to compute on-time rates per airport, route popularity, or carrier performance — work that previously needed scraping or paid datasets from analytics vendors.

Wrapping up

Fifty lines of Python, four endpoints, one API key. You've covered airport identification by code, geolocation-based lookup, user-input autocomplete, and live departure and arrival schedules — the full reference and operational layer most travel products ever need.

From here the main question is which surface you put it behind. A web UI built with React. A mobile app calling the same endpoints. A Slack bot for an operations team. An internal dashboard for a logistics company. The data layer stays exactly the same.

The complete Airport Database API documentation covers every field returned by the endpoints used above, plus filtering options that didn't fit in this walkthrough — filter by country, by type, by popularity, by city code. Pair it with the Flight Schedules API and you effectively have the data layer that powers commercial airport information displays.

If you haven't got a key yet, sign up here — the free tier is enough to build and ship this whole tutorial without paying anything.

Ready to get started?

Explore AirLabs, or create an account instantly and start using API.

Get FREE API Key