METAR
METARs (Meteorological Aerodrome Reports) sind Bodenwetterbeobachtungen, die an einem bestimmten Flugplatz oder einer bestimmten Station erfasst werden. Standard-METARs werden in regelmäßigen Abständen herausgegeben (in der Regel stündlich oder halbstündlich), während eine Sondermeldung (SPECI) veröffentlicht wird, wenn sich die Bedingungen an einem besetzten Standort erheblich ändern. Jedes METAR enthält wichtige meteorologische Daten wie Temperatur, Windgeschwindigkeit und -richtung, Sicht, Bewölkung und Luftdruck. Piloten, Fluglotsen, Dispatcher und Meteorologen nutzen diese Meldungen, um das Wetter am Flughafen zu beurteilen – als Grundlage für Flugplanung, Navigation und betriebliche Entscheidungen.
Anfrage
Voraussetzungen
x-api-key bei jeder Anfrage (Direktabonnement). Mehr erfahren →Senden Sie eine GET-Anfrage mit dem ICAO-Code des Flughafens im Pfad. Optionale Query-Flags steuern die Dekodierung.
https://data.skylinkapi.com/v3.1/weather/metar/{icao}| Parameter | Typ | Erforderlich | Standard | Beschreibung |
|---|---|---|---|---|
icao | string | Ja | - | Vierstelliger ICAO-Code — Suche, z. B. KJFK |
parsed | boolean | Nein | false | Dekodierte Felder unter einem parsed-Schlüssel hinzufügen |
Antwort
Rohdaten (Standard)
{
"raw": "METAR KJFK 062251Z 24017G23KT 10SM FEW060 FEW075 SCT110 BKN180 BKN250 28/17 A2974 RMK AO2 SLP072 T02830167 $",
"icao": "KJFK",
"airport_name": "John F. Kennedy International Airport",
"timestamp": "2026-06-06T23:09:37Z"
}| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
raw | string | Ja | Vollständiger METAR-String wie herausgegeben |
icao | string | Ja | ICAO-Code |
airport_name | string | Ja | Name des Flughafens |
timestamp | string (ISO 8601) | Ja | Zeitpunkt, zu dem die API diese Daten abgerufen hat — nicht die Beobachtungszeit |
Dekodiert (parsed=true)
{
"raw": "METAR KJFK 062251Z 24017G23KT 10SM FEW060 FEW075 SCT110 BKN180 BKN250 28/17 A2974 RMK AO2 SLP072 T02830167 $",
"icao": "KJFK",
"airport_name": "John F. Kennedy International Airport",
"timestamp": "2026-06-06T23:09:37Z",
"parsed": {
"time": "2026-06-07T00:51:00+02:00",
"wind": {
"direction": 240,
"speed": 17,
"gust": 23,
"variable": []
},
"visibility": {
"value": 10,
"repr": "10"
},
"clouds": [
{ "type": "FEW", "base": 60, "repr": "FEW060" },
{ "type": "FEW", "base": 75, "repr": "FEW075" },
{ "type": "SCT", "base": 110, "repr": "SCT110" },
{ "type": "BKN", "base": 180, "repr": "BKN180" },
{ "type": "BKN", "base": 250, "repr": "BKN250" }
],
"temperature": 28,
"dewpoint": 17,
"altimeter": 29.74,
"flight_rules": "VFR",
"wx_codes": [],
"remarks": "RMK AO2 SLP072 T02830167 $",
"density_altitude": 1792,
"pressure_altitude": 193,
"relative_humidity": 0.49
}
}| Feld | Typ | Erforderlich | Beschreibung |
|---|---|---|---|
parsed | object | Ja (mit parsed=true) | Fehlt bei parsed=false — ist dann nicht null |
parsed.time | string (ISO 8601) | Ja | Beobachtungszeit aus dem METAR-Kopf — für das Datenalter diese verwenden, nicht timestamp |
parsed.wind.direction | integer | Ja | Grad rechtweisend. 0 bei Windstille oder wenn keine Richtung gemeldet ist |
parsed.wind.speed | integer | Ja | Knoten. Nie null — 0 bedeutet Windstille |
parsed.wind.gust | integer | null | Ja (Schlüssel immer vorhanden) | Knoten. null, wenn keine Böen gemeldet sind (nicht 0) |
parsed.wind.variable | integer[] | Ja | Richtungsbereich bei wechselnder Windrichtung, z. B. [180, 270]. [], wenn nicht wechselnd |
parsed.visibility.value | number | null | Ja (Schlüssel immer vorhanden) | Statute Miles. null bei P6SM (> 6 SM) — als „> 6“ behandeln |
parsed.visibility.repr | string | Ja | Rohes Token aus dem METAR |
parsed.clouds | array | Ja | Schichten von der niedrigsten zur höchsten. [] bei wolkenlosem Himmel |
parsed.clouds[].type | string | Ja (pro Element) | Codes für den Bedeckungsgrad |
parsed.clouds[].base | integer | Ja (pro Element) | Hunderte Fuß AGL. 60 = 6.000 ft |
parsed.clouds[].repr | string | Ja (pro Element) | Rohes Token. BKN050CB = Cumulonimbus in 5.000 ft |
parsed.temperature | number | Ja | °C |
parsed.dewpoint | number | Ja | °C |
parsed.altimeter | number | Ja | QNH-Einstellung in inHg |
parsed.flight_rules | string | Ja | Flugwetterkategorie (VFR, MVFR, IFR, LIFR) |
parsed.wx_codes | array | Ja | Aktuelles Wetter. [], wenn keines gemeldet ist — siehe Codes für das aktuelle Wetter |
parsed.remarks | string | Ja | Alles nach RMK im Roh-String |
parsed.density_altitude | integer | Ja | Fuß — effektive, um Temperatur und Luftdruck korrigierte Höhe (Dichtehöhe); relevant für die Flugleistung |
parsed.pressure_altitude | integer | Ja | Fuß — auf die Standardatmosphäre bezogene Höhe (Druckhöhe) |
parsed.relative_humidity | number | Ja | Dezimalwert von 0 bis 1 |
Objektschemas und Nullbarkeit
Mit parsed=true enthält das parsed-Objekt immer jeden Schlüssel — bei fehlenden Daten wird nichts weggelassen. Verwenden Sie je nach Feld null, 0 oder []. Ohne parsed=true fehlt der Schlüssel parsed (er ist nicht null).
| Situation | Was Sie erhalten | Nicht so |
|---|---|---|
| Keine Böen | wind.gust: null | Schlüssel fehlt oder 0 |
| Windstille | wind.direction: 0, wind.speed: 0 | null, Schlüssel fehlt |
| Windrichtung nicht wechselnd | wind.variable: [] | null |
Sicht > 6 SM (P6SM) | visibility.value: null, visibility.repr: "P6" | value: 0 |
| Kein aktuelles Wetter | wx_codes: [] | null, Schlüssel fehlt |
Wolkenloser Himmel (SKC/CLR) | clouds: [] | null, Schlüssel fehlt |
Schemas der verschachtelten Objekte (Wind, Sicht, Wolken, aktuelles Wetter)Abschnitt aufklappen
Wind
JSON-Pfad: parsed.wind. Immer als Objekt vorhanden.
| Feld | Typ | Erforderlich | Null? | Wenn leer |
|---|---|---|---|---|
direction | integer | Ja | Nie | 0 = Windstille oder keine Richtung angegeben |
speed | integer | Ja | Nie | 0 = Windstille |
gust | integer | null | Ja | Ja | null, wenn das METAR keine Böen enthält |
variable | integer[] | Ja | Nie | [], wenn nicht wechselnd; [180, 270] bei 180V270 in den Rohdaten |
Sicht
JSON-Pfad: parsed.visibility. Immer als Objekt vorhanden.
| Feld | Typ | Erforderlich | Null? | Wenn leer |
|---|---|---|---|---|
value | number | null | Ja | Ja | null bei P6SM — als „> 6“ behandeln. Andernfalls numerisch |
repr | string | Ja | Nie | Rohes Token: "10", "3", "P6" usw. |
Wolkenschichten
JSON-Pfad: parsed.clouds[]. Immer ein Array (möglicherweise leer).
| Feld | Typ | Erforderlich | Null? | Beschreibung |
|---|---|---|---|---|
type | string | Ja | Nie | Codes für den Bedeckungsgrad |
base | integer | Ja | Nie | Hunderte Fuß AGL |
repr | string | Ja | Nie | Rohes Token, z. B. BKN050CB |
Codes für das aktuelle Wetter
JSON-Pfad: parsed.wx_codes[]. Immer ein Array (möglicherweise leer). Wird aktuelles Wetter gemeldet, hat jedes Element beide Schlüssel:
| Feld | Typ | Erforderlich | Null? | Beschreibung |
|---|---|---|---|---|
repr | string | Ja | Nie | Rohes Token, z. B. -RA, TSRA |
value | string | Ja | Nie | Ausgeschriebener Text, z. B. Light Rain, Thunderstorm Rain |
Beispiel aus der Live-API (KORD):
"wx_codes": [{ "repr": "-RA", "value": "Light Rain" }]Client-Typen
Kopieren Sie diese in Ihr Projekt. Die Nullbarkeit entspricht den oben beschriebenen Objektschemas und Nullbarkeit.
"""METAR response and summary types - matches weather-metar field tables."""from __future__ import annotationsfrom dataclasses import dataclassfrom typing import LiteralFlightRules = Literal["VFR", "MVFR", "IFR", "LIFR"]@dataclassclass MetarRequest: """Path/query input for GET /weather/metar/{icao}.""" icao: str parsed: bool = False@dataclassclass MetarWind: direction: int speed: int gust: int | None variable: list[int]@dataclassclass MetarVisibility: value: float | None repr: str@dataclassclass MetarCloudLayer: type: str base: int repr: str@dataclassclass MetarWxCode: repr: str value: str@dataclassclass MetarParsed: time: str wind: MetarWind visibility: MetarVisibility clouds: list[MetarCloudLayer] temperature: float dewpoint: float altimeter: float flight_rules: FlightRules wx_codes: list[MetarWxCode] remarks: str density_altitude: int pressure_altitude: int relative_humidity: float@dataclassclass MetarResponse: raw: str icao: str airport_name: str timestamp: str parsed: MetarParsed | None = None@dataclassclass MetarSummary: """Shape returned by metar_summary() in the fetch example.""" icao: str category: FlightRules wind_kt: int gust_kt: int | None visibility_display: str age_min: float stale: boolDie Wire-Typen (MetarResponse, MetarParsed) bilden das JSON von parsed=true ab. MetarSummary ist jeweils oben in jedem Tab des Codebeispiels definiert.
Integration
Beobachtungen abrufen, im Cache speichern und zusammenfassen — der nächste Schritt, nachdem Sie eine erfolgreiche Antwort geparst haben.
Das Beispiel speichert jedes METAR fünf Minuten im Cache (Beobachtungen werden höchstens alle 30–60 Minuten aktualisiert), verwendet Connect-/Read-Timeouts von 10 s / 15 s und erstellt eine Zusammenfassung auf Basis von parsed.time (Beobachtungszeit), nicht von timestamp (Abrufzeit der API).
import osimport timefrom dataclasses import dataclassfrom datetime import datetime, timezonefrom typing import Literalimport requests# MetarSummary - helper return type. Full wire types (MetarResponse, MetarParsed, …)# are in the Client types section on the METAR docs page.FlightRules = Literal["VFR", "MVFR", "IFR", "LIFR"]@dataclassclass MetarSummary: icao: str category: FlightRules wind_kt: int gust_kt: int | None visibility_display: str age_min: float stale: boolHEADERS = { "x-api-key": os.getenv("SKYLINK_API_KEY", "YOUR_API_KEY")}BASE = "https://data.skylinkapi.com/v3.1"CACHE: dict[str, tuple[dict, float]] = {}METAR_TTL = 300 # 5 min - safe inside the 30–60 min observation cycledef parse_observation_time(iso: str) -> datetime: """Parse parsed.time - API returns ISO 8601 with timezone offset.""" return datetime.fromisoformat(iso.replace("Z", "+00:00"))def fetch_metar(icao: str) -> dict | None: cache_key = f"metar:{icao}:parsed" cached = CACHE.get(cache_key) if cached and time.time() < cached[1]: return cached[0] try: r = requests.get( f"{BASE}/weather/metar/{icao}", headers=HEADERS, params={"parsed": "true"}, timeout=(10, 15), ) except requests.Timeout as exc: raise RuntimeError(f"SkyLink timeout fetching METAR for {icao}") from exc if r.status_code == 404: return None r.raise_for_status() data = r.json() CACHE[cache_key] = (data, time.time() + METAR_TTL) return datadef metar_summary(icao: str) -> MetarSummary | None: metar = fetch_metar(icao) if not metar: return None p = metar["parsed"] obs = parse_observation_time(p["time"]) age_min = (datetime.now(timezone.utc) - obs).total_seconds() / 60 vis = p["visibility"]["value"] return MetarSummary( icao=icao, category=p["flight_rules"], wind_kt=p["wind"]["speed"], gust_kt=p["wind"]["gust"], visibility_display=f"{vis} SM" if vis is not None else "> 6 SM", age_min=round(age_min, 1), stale=age_min > 90, )if __name__ == "__main__": import json from dataclasses import asdict summary = metar_summary("KJFK") print(json.dumps(asdict(summary), indent=2) if summary else "METAR not available")Weitere Beispiele: Wetter-Anwendungsfälle.
Hinweise zur Implementierung
timestamp vs. parsed.time. timestamp ändert sich bei jeder Anfrage. parsed.time ist die Beobachtungszeit aus dem METAR-Kopf — verwenden Sie sie für Angaben wie „Daten sind X Minuten alt“.
visibility.value ist null. Meldet die Station P6SM, ist value gleich null und repr gleich "P6". Behandeln Sie null als „> 6 SM“, nicht als fehlende Daten.
Verfügbarkeit von Stationen. Nicht jeder ICAO-Code hat eine METAR-Station. Ein 404 bedeutet, dass keine Beobachtung verfügbar ist — der Flughafen kann trotzdem existieren. Zeigen Sie einen leeren Zustand an, kein Fehlerbanner.
Caching. Ein Client-Cache von 3–5 Minuten reduziert doppelte Aufrufe, ohne neue Beobachtungen zu verpassen.
Fehlerantworten
Hier stehen nur METAR-spezifische Fehler. Fehler bei Authentifizierung, Validierung, Rate Limits und Serverfehler finden Sie unter Fehlerbehandlung. Muster für den Fallback zwischen METAR und TAF finden Sie unter Wenn Wetterdaten fehlen.
404 — kein METAR für diesen ICAO-Code
{
"detail": "Airport not found for ICAO code: KXYZ"
}Der Flughafen existiert möglicherweise nicht, oder er existiert, hat aber keine METAR-Station. Die Meldung unterscheidet diese Fälle nicht — behandeln Sie jeden METAR-404 als keine Beobachtung verfügbar.
Your SkyLink licence key, for keys bought direct from skylinkapi.com.
In: header
Path Parameters
4-letter ICAO airport code
4 <= length <= 4Query Parameters
Include parsed/decoded METAR fields alongside raw text
falseResponse Body
application/json
application/json
curl -X GET "https://data.skylinkapi.com/v3.1/weather/metar/KJFK"{
"raw": "METAR KJFK 271851Z 16013KT 10SM FEW024 15/09 A3020 RMK AO2 SLP216 T01500089",
"icao": "KJFK",
"airport_name": "John F Kennedy International Airport",
"timestamp": "2025-09-27T12:00:00Z"
}{
"detail": [
{
"loc": [
"string"
],
"msg": "string",
"type": "string",
"input": null,
"ctx": {}
}
]
}Siehe auch: TAF · Anwendungsfälle · Fehler · Produktivbetrieb
Wetter
Wetter-API von SkyLink — METAR, TAF, Höhenwinde, PIREPs und AIRMET/SIGMET. Wählen Sie den passenden Endpoint für Flughafen, Route oder Gebiet.
TAF
Flugplatzvorhersagen (TAF) für jeden ICAO-Flughafen abrufen. Die optionale dekodierte Ausgabe enthält Vorhersageperioden und die erwartete Flugwetterkategorie.