Navaids

Runnable examples for querying navigational aids using the Navaids endpoint: sectional chart overlays near an airport and ILS approach filtering.

#QuestionData used
1List all navaids near KJFK for a sectional chart overlay/navaids
2Find all ILS approaches at an airport/navaids

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. Navaids near an airport for sectional chart overlay

Question: List all navaids near KJFK for a sectional chart overlay.

VHF navaids (VOR, VOR-DME, VORDME, ILS, LOC) report frequency_khz — divide by 1000 for the MHz value shown on sectional charts. NDB frequencies stay in kHz. Results are grouped by navaid type.

import os
from collections import defaultdict

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"

VHF_TYPES = {"VOR", "VOR-DME", "VORDME", "ILS", "LOC", "DME", "TACAN"}


def fetch_navaids(airport: str) -> list[dict]:
    r = requests.get(
        f"{BASE}/navaids",
        headers=HEADERS,
        params={"airport": airport},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return []
    r.raise_for_status()
    return r.json().get("navaids") or []


def format_freq(navaid: dict) -> str:
    freq_khz = navaid.get("frequency_khz")
    if freq_khz is None:
        return "—"
    nav_type = navaid.get("type", "").upper()
    if nav_type in VHF_TYPES:
        return f"{freq_khz / 1000:.3f} MHz"
    return f"{freq_khz:.0f} kHz"


def main() -> None:
    navaids = fetch_navaids("KJFK")
    if not navaids:
        console.print("[yellow]No navaids found near KJFK.[/]")
        return

    grouped: dict[str, list[dict]] = defaultdict(list)
    for nav in navaids:
        grouped[nav.get("type", "UNKNOWN")].append(nav)

    for nav_type in sorted(grouped):
        table = Table(title=f"{nav_type} Navaids")
        table.add_column("Ident", style="cyan", no_wrap=True)
        table.add_column("Name")
        table.add_column("Frequency")
        table.add_column("Lat", justify="right")
        table.add_column("Lon", justify="right")

        for nav in grouped[nav_type]:
            table.add_row(
                nav.get("ident", "—"),
                nav.get("name", "—"),
                format_freq(nav),
                f"{nav.get('latitude_deg', '—')}",
                f"{nav.get('longitude_deg', '—')}",
            )

        console.print(table)


if __name__ == "__main__":
    main()

Output: One table per navaid type (VOR, NDB, ILS, etc.) listing ident, name, frequency (MHz for VHF types, kHz for NDB), and coordinates for all navaids near KJFK.


2. ILS approaches at an airport

Question: Find all ILS approaches at an airport (filter by type ILS).

Filtering by type=[ILS](https://en.wikipedia.org/wiki/Instrument_landing_system) returns only instrument landing system navaids. Small and regional airports often lack ILS — the script handles that case explicitly.

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_ils(airport: str) -> list[dict]:
    r = requests.get(
        f"{BASE}/navaids",
        headers=HEADERS,
        params={"airport": airport, "type": "ILS"},
        timeout=(10, 15),
    )
    if r.status_code == 404:
        return []
    r.raise_for_status()
    return r.json().get("navaids") or []


def main() -> None:
    icao = "EGLL"
    ils_list = fetch_ils(icao)

    if not ils_list:
        console.print(
            f"[yellow]No ILS approaches found at {icao}. "
            "Small and regional airports often rely on RNAV/GPS approaches only.[/]"
        )
        return

    table = Table(title=f"ILS Approaches — {icao}")
    table.add_column("Ident", style="cyan", no_wrap=True)
    table.add_column("Name")
    table.add_column("Frequency (MHz)", justify="right")
    table.add_column("Associated Airport")

    for ils in ils_list:
        freq_khz = ils.get("frequency_khz")
        freq_str = f"{freq_khz / 1000:.2f}" if freq_khz is not None else "—"
        table.add_row(
            ils.get("ident", "—"),
            ils.get("name", "—"),
            freq_str,
            ils.get("associated_airport", "—"),
        )

    console.print(table)
    console.print(
        f"\n[dim]{len(ils_list)} ILS approach(es) found. "
        "Ident typically encodes the runway (e.g. I-27L → Runway 27L).[/]"
    )


if __name__ == "__main__":
    main()

Output: A table of ILS approaches at EGLL with ident, name, localizer frequency in MHz, and associated airport. Prints a count and runway-decoding note at the bottom.