Save up to 17% with yearly billing

See pricing

Live-Tracking

Lauffähige Beispiele zur Abfrage von Live-Positionen von Luftfahrzeugen und Feed-Statistiken. Filterparameter und Antwortstruktur finden Sie in der vollständigen Referenz ADS-B-Flugzeugtracking.

#FrageVerwendete Daten
1Wie viele Flugzeuge sind gerade in der Luft, und wie hoch ist die durchschnittliche Flughöhe?/adsb/aircraft/statistics
2Welche Flugzeuge fliegen gerade im Luftraum um KJFK?/adsb/aircraft
3Wie verteilen sich Flugzeuge in einem europäischen Luftraum-Begrenzungsrahmen (Bbox) auf Höhenbänder?/adsb/aircraft

Voraussetzungen

Auth
x-api-key bei jeder Anfrage (Direktabonnement). Mehr erfahren →

Installation

Die folgenden Skripte verwenden requests für API-Aufrufe und rich für die Terminalausgabe. Einmalig installieren:

pip install requests rich

1. Live-Luftraumstatistiken

Frage: Wie viele Flugzeuge werden gerade getrackt, wie viele davon sind in der Luft, und wie hoch ist die durchschnittliche Flughöhe?

Der Statistik-Endpoint aggregiert die Zahlen über den gesamten Feed — Parameter sind nicht erforderlich.

import os

import requests
from rich.console import Console
from rich.panel import Panel

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_statistics() -> dict:
    r = requests.get(
        f"{BASE}/adsb/aircraft/statistics",
        headers=HEADERS,
        timeout=(10, 15),
    )
    r.raise_for_status()
    return r.json()


def main() -> None:
    stats = fetch_statistics()
    alt = stats.get("altitude_stats") or {}

    avg_ft = alt.get("avg_altitude")
    max_ft = alt.get("max_altitude")
    avg_fl = round(avg_ft / 100) if avg_ft is not None else None
    max_fl = round(max_ft / 100) if max_ft is not None else None

    lines = [
        f"[bold]Total tracked:[/bold]    {stats.get('total_aircraft', 0):,}",
        f"[bold]Airborne:[/bold]         {stats.get('airborne', 0):,}",
        f"[bold]On ground:[/bold]        {stats.get('on_ground', 0):,}",
    ]
    if avg_ft is not None:
        lines.append(f"[bold]Avg altitude:[/bold]     {avg_ft:,.0f} ft  (FL{avg_fl:03d})")
    if max_ft is not None:
        lines.append(f"[bold]Max altitude:[/bold]     {max_ft:,.0f} ft  (FL{max_fl:03d})")

    console.print(Panel("\n".join(lines), title="Live ADS-B Statistics", border_style="cyan"))
    console.print(
        "[dim]ADS-B data refreshes every few seconds — do not cache these results.[/dim]"
    )


if __name__ == "__main__":
    main()

Ausgabe: Ein Panel mit der Gesamtzahl getrackter Flugzeuge, der Anzahl in der Luft, der Anzahl am Boden, der durchschnittlichen Flughöhe in ft und als FL sowie der maximalen Flughöhe.

Hinweis: ADS-B-Daten sind kurzlebig — der Feed wird alle paar Sekunden aktualisiert. Speichern Sie Antworten nicht im Cache; rufen Sie für Echtzeit-Anwendungsfälle immer aktuelle Daten ab.


2. Flugzeuge im Luftraum um KJFK

Frage: Welche Flugzeuge befinden sich derzeit im Umkreis von 80 km um den John F. Kennedy International Airport in der Luft?

Filtern Sie mit lat, lon und radius und schließen Sie anschließend Einträge am Boden aus, um nur Flugzeuge in der Luft anzuzeigen. Die Ergebnisse werden absteigend nach Flughöhe sortiert.

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"

# KJFK coordinates
LAT = 40.6413
LON = -73.7781
RADIUS_KM = 80
LIMIT = 20


def fetch_aircraft_near(lat: float, lon: float, radius: int, limit: int) -> list[dict]:
    r = requests.get(
        f"{BASE}/adsb/aircraft",
        headers=HEADERS,
        params={"lat": lat, "lon": lon, "radius": radius, "limit": limit},
        timeout=(10, 15),
    )
    r.raise_for_status()
    return r.json().get("aircraft", [])


def main() -> None:
    aircraft = fetch_aircraft_near(LAT, LON, RADIUS_KM, LIMIT)

    airborne = [
        a for a in aircraft
        if not a.get("is_on_ground")
    ]
    airborne.sort(key=lambda a: a.get("altitude") or 0, reverse=True)

    table = Table(
        title=f"Airborne Aircraft within {RADIUS_KM} km of KJFK  ({len(airborne)} shown)",
        border_style="cyan",
    )
    table.add_column("Callsign")
    table.add_column("ICAO24")
    table.add_column("Altitude (ft)", justify="right")
    table.add_column("Speed (kt)", justify="right")
    table.add_column("Track (°)", justify="right")
    table.add_column("Type")

    for a in airborne:
        alt = f"{int(a['altitude']):,}" if a.get("altitude") is not None else "—"
        spd = str(int(a["ground_speed"])) if a.get("ground_speed") is not None else "—"
        trk = f"{a['track']:.0f}" if a.get("track") is not None else "—"
        table.add_row(
            a.get("callsign") or "—",
            a.get("icao24") or "—",
            alt,
            spd,
            trk,
            a.get("aircraft_type") or "—",
        )

    console.print(table)
    console.print("[dim]On-ground aircraft excluded. ADS-B data refreshes every few seconds.[/dim]")


if __name__ == "__main__":
    main()

Ausgabe: Eine Tabelle der Flugzeuge in der Luft, absteigend nach Flughöhe sortiert: Callsign | ICAO24 | Altitude (ft) | Speed (kt) | Track (°) | Type.


3. Verteilung auf Höhenbänder in einer europäischen Bbox

Frage: Wie verteilen sich die Flugzeuge derzeit auf Höhenbänder im Korridor Paris–Frankfurt?

Fragen Sie einen Begrenzungsrahmen mit bbox=lat1,lon1,lat2,lon2 ab und ordnen Sie anschließend jedes Flugzeug einer der Kategorien Ground / Low / Medium / High zu. None-Flughöhen werden anhand des Flags is_on_ground behandelt.

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"

# Roughly Paris–Frankfurt bounding box
BBOX = "48,2,52,8"


def fetch_bbox(bbox: str) -> list[dict]:
    r = requests.get(
        f"{BASE}/adsb/aircraft",
        headers=HEADERS,
        params={"bbox": bbox, "limit": 200},
        timeout=(10, 15),
    )
    r.raise_for_status()
    return r.json().get("aircraft", [])


def classify(aircraft: dict) -> str | None:
    alt = aircraft.get("altitude")
    if alt is None:
        return "Ground" if aircraft.get("is_on_ground") else None
    if alt < 100:
        return "Ground"
    if alt < 10_000:
        return "Low  (<10,000 ft)"
    if alt <= 25_000:
        return "Medium  (10,000–25,000 ft)"
    return "High  (>25,000 ft)"


def main() -> None:
    aircraft = fetch_bbox(BBOX)

    bands: dict[str, list[str]] = defaultdict(list)
    for a in aircraft:
        band = classify(a)
        if band is None:
            continue
        callsign = a.get("callsign") or a.get("icao24") or "?"
        bands[band].append(callsign)

    order = ["Ground", "Low  (<10,000 ft)", "Medium  (10,000–25,000 ft)", "High  (>25,000 ft)"]

    table = Table(title=f"Altitude Distribution — bbox {BBOX}", border_style="cyan")
    table.add_column("Band", style="bold")
    table.add_column("Count", justify="right")
    table.add_column("Example callsigns")

    for band in order:
        entries = bands.get(band, [])
        examples = ", ".join(entries[:3]) if entries else "—"
        table.add_row(band, str(len(entries)), examples)

    console.print(table)
    console.print(
        f"[dim]Total aircraft returned: {len(aircraft)}. "
        "Aircraft with unknown altitude and not on_ground are excluded.[/dim]"
    )


if __name__ == "__main__":
    main()

Ausgabe: Eine Tabelle mit vier Höhenbändern, der jeweiligen Anzahl und bis zu drei Beispiel-Rufzeichen pro Band.