Historische Tracks
Lauffähige Beispiele für die Suche nach archivierten Flügen, das Abrufen vollständiger Flugdetails und die Abfrage des historischen Flughafenverkehrs. Aufbewahrungszeiträume und Tarifvoraussetzungen finden Sie in der vollständigen Referenz zu historischem ADS-B.
| # | Frage | Verwendete Daten |
|---|---|---|
| 1 | Welche 5 Flüge hat das Luftfahrzeug mit dem Kennzeichen N636JB zuletzt durchgeführt? | /ultra/history/flights |
| 2 | Vollständige Metadaten zum jüngsten Abflug von EGLL | /ultra/history/flights → /ultra/history/flight/{flight_id} |
| 3 | Wie viele Ankünfte hatte KJFK in den letzten 24 Stunden? | /ultra/history/airport/{icao}/traffic |
Voraussetzungen
x-api-key bei jeder Anfrage (Direktabonnement). Mehr erfahren →/ultra/history/... erfordert Pro, Ultra oder Mega — 401/403 bedeutet, dass Ihr Tarif unterhalb dieser Schwelle liegt.
Installation
Die folgenden Skripte verwenden requests für API-Aufrufe und rich für die Terminalausgabe. Einmalig installieren:
pip install requests rich1. Die letzten 5 Flüge nach Kennzeichen
Frage: Welche Routen ist N636JB zuletzt geflogen, und wie lange hat jeder Flug gedauert?
Geben Sie einen registration-Filter an und setzen Sie limit=5, um nur die jüngsten archivierten Flüge abzurufen.
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"
REGISTRATION = "N636JB"
def fetch_recent_flights(registration: str, limit: int = 5) -> list[dict] | None:
r = requests.get(
f"{BASE}/ultra/history/flights",
headers=HEADERS,
params={"registration": registration, "limit": limit},
timeout=(10, 25),
)
if r.status_code in (401, 403):
msg = r.json().get("message", "Plan not entitled.")
console.print(
f"[red]Access denied:[/red] {msg}\n"
"[yellow]Upgrade to Pro or above for /ultra/history/... endpoints.[/yellow]"
)
return None
r.raise_for_status()
return r.json().get("flights", [])
def fmt_duration(seconds: int | None) -> str:
if seconds is None:
return "—"
h, m = divmod(seconds // 60, 60)
return f"{h}:{m:02d}"
def main() -> None:
flights = fetch_recent_flights(REGISTRATION)
if flights is None:
return
if not flights:
console.print(f"[yellow]No archived flights found for {REGISTRATION}.[/yellow]")
return
table = Table(title=f"Recent Flights — {REGISTRATION}", border_style="cyan")
table.add_column("Flight ID", style="dim")
table.add_column("From")
table.add_column("To")
table.add_column("Departure (UTC)")
table.add_column("Duration", justify="right")
for f in flights:
table.add_row(
(f.get("flight_id") or "")[:8],
f.get("departure_icao") or "—",
f.get("arrival_icao") or "—",
(f.get("departure_time") or "—")[:16],
fmt_duration(f.get("duration_sec")),
)
console.print(table)
if __name__ == "__main__":
main()Ausgabe: Eine Tabelle der fünf jüngsten archivierten Flüge: Flug-ID (erste 8 Zeichen) | Von | Nach | Abflugzeit | Dauer (h:mm).
2. Kette Suche → Details: vollständige Metadaten zum jüngsten Abflug von EGLL
Frage: Welches Luftfahrzeug, welche Route und welche Zeitangaben beschreiben den jüngsten Flug, der in London Heathrow gestartet ist?
Zweistufige Kette: Suchen Sie den letzten Abflug von EGLL, um eine flight_id zu erhalten, und rufen Sie anschließend den vollständigen Detaildatensatz einschließlich Flugzeugtyp und GPS-Spoofing-Kennzeichnung ab.
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"
DEPARTURE_ICAO = "EGLL"
def handle_plan_gate(r: requests.Response) -> bool:
"""Return True if request was blocked by plan gating."""
if r.status_code in (401, 403):
msg = r.json().get("message", "Plan not entitled.")
console.print(
f"[red]Access denied:[/red] {msg}\n"
"[yellow]Upgrade to Pro or above for /ultra/history/... endpoints.[/yellow]"
)
return True
return False
def fetch_latest_departure(departure_icao: str) -> str | None:
r = requests.get(
f"{BASE}/ultra/history/flights",
headers=HEADERS,
params={"departure_icao": departure_icao, "limit": 1},
timeout=(10, 25),
)
if handle_plan_gate(r):
return None
r.raise_for_status()
flights = r.json().get("flights", [])
if not flights:
return None
return flights[0]["flight_id"]
def fetch_flight_detail(flight_id: str) -> dict | None:
r = requests.get(
f"{BASE}/ultra/history/flight/{flight_id}",
headers=HEADERS,
timeout=(10, 25),
)
if r.status_code == 404:
return None
if handle_plan_gate(r):
return None
r.raise_for_status()
return r.json()
def fmt_duration(seconds: int | None) -> str:
if seconds is None:
return "—"
h, m = divmod(seconds // 60, 60)
return f"{h}h {m:02d}m"
def main() -> None:
flight_id = fetch_latest_departure(DEPARTURE_ICAO)
if not flight_id:
console.print(f"[yellow]No recent departures found for {DEPARTURE_ICAO}.[/yellow]")
return
detail = fetch_flight_detail(flight_id)
if detail is None:
console.print(f"[yellow]Flight detail not available for ID {flight_id[:8]}.[/yellow]")
return
spoofing = detail.get("gps_spoofing_suspected")
spoofing_str = "[red]YES — review track[/red]" if spoofing else "No"
lines = [
f"[bold]Registration:[/bold] {detail.get('registration') or '—'}",
f"[bold]Callsign:[/bold] {detail.get('callsign') or '—'}",
f"[bold]Aircraft Type:[/bold] {detail.get('aircraft_type') or '—'}",
f"[bold]Route:[/bold] {detail.get('departure_icao') or '—'} → {detail.get('arrival_icao') or '—'}",
f"[bold]Departure:[/bold] {detail.get('departure_airport_name') or detail.get('departure_icao') or '—'}",
f"[bold]Arrival:[/bold] {detail.get('arrival_airport_name') or detail.get('arrival_icao') or '—'}",
f"[bold]Dep time (UTC):[/bold] {(detail.get('departure_time') or '—')[:16]}",
f"[bold]Arr time (UTC):[/bold] {(detail.get('arrival_time') or '—')[:16]}",
f"[bold]Duration:[/bold] {fmt_duration(detail.get('duration_sec'))}",
f"[bold]Distance:[/bold] {detail.get('distance_nm') or '—'} nm",
f"[bold]GPS Spoofing:[/bold] {spoofing_str}",
]
console.print(
Panel("\n".join(lines), title=f"Flight Detail — {flight_id[:8]}", border_style="cyan")
)
if __name__ == "__main__":
main()Ausgabe: Ein Detailpanel mit Kennzeichen, Rufzeichen, Flugzeugtyp, vollständiger Route (Flughafennamen), Abflug- und Ankunftszeiten, Dauer, Entfernung und GPS-Spoofing-Kennzeichnung.
3. Ankünfte in KJFK in den letzten 24 Stunden
Frage: Wie viele Flüge sind in den letzten 24 Stunden in JFK angekommen, und welches waren die ersten fünf?
Berechnen Sie start und end in UTC und fragen Sie den Endpoint für den Flughafenverkehr mit direction=arr ab. Beachten Sie, dass das verfügbare Zeitfenster der Aufbewahrungsgrenze Ihres Tarifs unterliegt (90 Tage beim Ultra-Pfad).
import datetime
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"
AIRPORT = "KJFK"
def fetch_airport_traffic(
icao: str,
start: str,
end: str,
direction: str = "arr",
) -> dict | None:
r = requests.get(
f"{BASE}/ultra/history/airport/{icao}/traffic",
headers=HEADERS,
params={"start": start, "end": end, "direction": direction, "limit": 50},
timeout=(10, 25),
)
if r.status_code in (401, 403):
msg = r.json().get("message", "Plan not entitled.")
console.print(
f"[red]Access denied:[/red] {msg}\n"
"[yellow]Upgrade to Pro or above for /ultra/history/... endpoints.[/yellow]"
)
return None
r.raise_for_status()
return r.json()
def main() -> None:
now = datetime.datetime.now(datetime.timezone.utc)
start = (now - datetime.timedelta(hours=24)).strftime("%Y-%m-%dT%H:%M:%SZ")
end = now.strftime("%Y-%m-%dT%H:%M:%SZ")
result = fetch_airport_traffic(AIRPORT, start=start, end=end, direction="arr")
if result is None:
return
flights = result.get("flights", [])
total = result.get("count", len(flights))
console.print(
f"[bold cyan]{AIRPORT}[/bold cyan] received "
f"[bold]{total:,}[/bold] arrivals in the last 24 hours."
)
if not flights:
console.print("[yellow]No individual flight records returned.[/yellow]")
return
table = Table(title=f"Sample Arrivals — {AIRPORT} (first 5)", border_style="cyan")
table.add_column("Callsign")
table.add_column("From")
table.add_column("Arrival time (UTC)")
for f in flights[:5]:
table.add_row(
f.get("callsign") or "—",
f.get("departure_airport_icao") or "—",
(f.get("landing_time") or "—")[:16],
)
console.print(table)
console.print(
"[dim]Window is subject to your plan's retention limit "
"(Ultra path: up to 90 days).[/dim]"
)
if __name__ == "__main__":
main()Ausgabe: Gesamtzahl der Ankünfte im 24-Stunden-Fenster, gefolgt von einer Beispieltabelle der ersten fünf Ankünfte: Rufzeichen | Von | Ankunftszeit.