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.
| # | Frage | Verwendete Daten |
|---|---|---|
| 1 | Wie viele Flugzeuge sind gerade in der Luft, und wie hoch ist die durchschnittliche Flughöhe? | /adsb/aircraft/statistics |
| 2 | Welche Flugzeuge fliegen gerade im Luftraum um KJFK? | /adsb/aircraft |
| 3 | Wie verteilen sich Flugzeuge in einem europäischen Luftraum-Begrenzungsrahmen (Bbox) auf Höhenbänder? | /adsb/aircraft |
Voraussetzungen
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 rich1. 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.