Airports

Runnable examples for airport data: key facts, radio frequencies, and multi-airport runway comparison using the Airports endpoint.

#QuestionData used
1What are the key facts and longest runway at a given airport?/airports/search
2What radio frequencies does this airport publish?/airports/search
3Compare two airports by runway specs for aircraft planning/airports/search

Requirements

Auth
x-api-key on every request (direct subscription). Learn more →

Install

The scripts below use requests for API calls and rich for terminal output. Install once:

pip install requests rich

1. Airport key facts and longest runway

Question: What are the key facts and longest runway at a given airport?

The /airports/search endpoint returns full airport metadata including all runways. This script extracts the essentials and identifies the longest available runway.

import os

import requests
from rich.console import Console
from rich.table import Table

console = Console()

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"


def fetch_airport(icao: str) -> dict | None:
    r = requests.get(
        f"{BASE}/airports/search",
        headers=HEADERS,
        params={"icao": icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return None
    r.raise_for_status()
    return r.json()


def main() -> None:
    airport = fetch_airport("KJFK")
    if not airport:
        console.print("[yellow]Airport not found.[/]")
        return

    runways = airport.get("runways") or []
    longest = max((rwy.get("length_ft") or 0 for rwy in runways), default=0)

    table = Table(title=f"Airport Facts — {airport.get('ident', 'N/A')}")
    table.add_column("Field", style="cyan", no_wrap=True)
    table.add_column("Value")

    table.add_row("Name", airport.get("name", "—"))
    table.add_row("ICAO", airport.get("icao_code", "—"))
    table.add_row("IATA", airport.get("iata_code", "—"))
    table.add_row("Type", airport.get("type", "—"))
    table.add_row("Elevation", f"{airport.get('elevation_ft', '—')} ft")
    table.add_row("Municipality", airport.get("municipality", "—"))
    table.add_row("Country", (airport.get("country") or {}).get("name", "—"))
    table.add_row("Runways", str(len(runways)))
    table.add_row("Longest Runway", f"{longest:,} ft" if longest else "—")

    console.print(table)


if __name__ == "__main__":
    main()

Output: A table with name, ICAO/IATA codes, type, elevation, municipality, runway count, and longest runway length for KJFK.


2. Airport radio frequencies

Question: What radio frequencies does this airport publish?

ATC frequencies (ATIS, GND, TWR, APP, DEP) are embedded in the airport response. Sorted by type for easy reference during preflight planning.

import os

import requests
from rich.console import Console
from rich.table import Table

console = Console()

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"


def fetch_airport(icao: str) -> dict | None:
    r = requests.get(
        f"{BASE}/airports/search",
        headers=HEADERS,
        params={"icao": icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return None
    r.raise_for_status()
    return r.json()


def main() -> None:
    airport = fetch_airport("EGLL")
    if not airport:
        console.print("[yellow]Airport not found.[/]")
        return

    frequencies = airport.get("frequencies") or []
    if not frequencies:
        console.print(f"[yellow]No frequencies published for {airport.get('ident')}.[/]")
        return

    frequencies.sort(key=lambda f: f.get("type", ""))

    table = Table(title=f"Radio Frequencies — {airport.get('name', 'N/A')}")
    table.add_column("Type", style="cyan", no_wrap=True)
    table.add_column("Description")
    table.add_column("Frequency (MHz)", justify="right")

    for freq in frequencies:
        table.add_row(
            freq.get("type", "—"),
            freq.get("description", "—"),
            str(freq.get("frequency_mhz", "—")),
        )

    console.print(table)
    console.print(
        "\n[dim]Tip: chain to [bold]/v3/weather/metar/EGLL[/bold] for live wind and altimeter to "
        "cross-check ATIS readback.[/]"
    )


if __name__ == "__main__":
    main()

Output: A sorted table of ATIS, GND, TWR, APP, and DEP frequencies for London Heathrow (EGLL), plus a tip linking to the METAR endpoint for live conditions.


3. Compare two airports by runway specs

Question: How do two airports compare by runway configuration for aircraft planning?

Fetches KLAX and KJFK concurrently and prints a side-by-side summary. For takeoff performance calculations, chain the ICAO codes to /v3/weather/metar/{icao} for current temperature and pressure.

import os
from concurrent.futures import ThreadPoolExecutor, as_completed

import requests
from rich.console import Console
from rich.table import Table

console = Console()

HEADERS = {
    "X-RapidAPI-Key": os.getenv("RAPIDAPI_KEY", "YOUR_RAPIDAPI_KEY"),
    "X-RapidAPI-Host": "skylink-api.p.rapidapi.com",
}
BASE = "https://skylink-api.p.rapidapi.com"

AIRPORTS = ["KLAX", "KJFK"]


def fetch_airport(icao: str) -> tuple[str, dict | None]:
    r = requests.get(
        f"{BASE}/airports/search",
        headers=HEADERS,
        params={"icao": icao},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return icao, None
    r.raise_for_status()
    return icao, r.json()


def main() -> None:
    results: dict[str, dict | None] = {}
    with ThreadPoolExecutor(max_workers=2) as pool:
        futures = {pool.submit(fetch_airport, icao): icao for icao in AIRPORTS}
        for future in as_completed(futures):
            icao, data = future.result()
            results[icao] = data

    table = Table(title="Runway Comparison")
    table.add_column("Field", style="cyan", no_wrap=True)
    for icao in AIRPORTS:
        table.add_column(icao, justify="right")

    def runway_stat(data: dict | None, stat: str) -> str:
        if not data:
            return "—"
        runways = data.get("runways") or []
        if stat == "count":
            return str(len(runways))
        if stat == "longest":
            longest = max((r.get("length_ft") or 0 for r in runways), default=0)
            return f"{longest:,} ft" if longest else "—"
        return "—"

    def field(data: dict | None, key: str) -> str:
        if not data:
            return "—"
        val = data.get(key, "—")
        return str(val) if val is not None else "—"

    rows = [
        ("Airport Name", lambda d: field(d, "name")),
        ("Municipality", lambda d: field(d, "municipality")),
        ("Elevation", lambda d: f"{field(d, 'elevation_ft')} ft"),
        ("Runways", lambda d: runway_stat(d, "count")),
        ("Longest Runway", lambda d: runway_stat(d, "longest")),
    ]

    for label, getter in rows:
        table.add_row(label, *[getter(results.get(icao)) for icao in AIRPORTS])

    console.print(table)
    console.print(
        "\n[dim]For takeoff performance: fetch [bold]/v3/weather/metar/{icao}[/bold] "
        "to get current OAT and QNH for density altitude calculation.[/]"
    )


if __name__ == "__main__":
    main()

Output: A side-by-side table comparing KLAX and KJFK by name, municipality, elevation, runway count, and longest runway length.