TAF
TAF (прогнозы по аэродрому) — это структурированные прогнозы для конкретного аэропорта и его ближайших окрестностей, обычно охватывающие примерно пять морских миль вокруг аэродрома. Стандартные TAF выпускаются четыре раза в сутки — в 00Z, 06Z, 12Z и 18Z — и действуют 24 или 30 часов в зависимости от станции. Каждый TAF описывает ожидаемые ветер, видимость, слои облачности, погодные явления и категории полётных условий в рамках прогнозных групп с привязкой ко времени, таких как FROM, TEMPO и BECMG. Пилоты, диспетчеры по обеспечению полётов и специалисты по планированию полётов используют эти прогнозы, чтобы оценить ожидаемые условия в аэропортах вылета, назначения и запасных при составлении оперативных планов. Многие небольшие аэропорты публикуют только METAR — ответ 404 для TAF встречается часто и не означает, что аэропорт неизвестен.
Запрос
Требования
x-api-key в каждом запросе (прямая подписка). Подробнее →Отправьте запрос GET с кодом ICAO аэропорта в пути. Необязательные query-флаги управляют декодированием.
https://data.skylinkapi.com/v3.1/weather/taf/{icao}| Параметр | Тип | Обязательный | По умолчанию | Описание |
|---|---|---|---|---|
icao | string | Да | - | Четырёхбуквенный код ICAO — поиск, например KJFK |
parsed | boolean | Нет | false | Добавить декодированные периоды прогноза под ключом parsed |
Ответ
Исходный ответ (по умолчанию)
{
"raw": "TAF KJFK 072334Z 0800/0906 35014G20KT P6SM FEW050 SCT100 FM080600 03011KT P6SM SCT025 ...",
"icao": "KJFK",
"airport_name": "John F. Kennedy International Airport",
"timestamp": "2026-06-08T23:45:12Z"
}| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
raw | string | Да | Полная строка TAF в исходном виде |
icao | string | Да | Код ICAO |
airport_name | string | Да | Название аэропорта |
timestamp | string (ISO 8601) | Да | Время получения данных API — не время выпуска прогноза |
Декодированный ответ (parsed=true)
{
"raw": "TAF KJFK 061933Z 0620/0724 ...",
"icao": "KJFK",
"airport_name": "John F. Kennedy International Airport",
"timestamp": "2026-06-06T23:09:48Z",
"parsed": {
"start_time": "2026-06-06T22:00:00+02:00",
"end_time": "2026-06-08T02:00:00+02:00",
"forecast": [
{
"type": "FROM",
"start_time": "2026-06-06T22:00:00+02:00",
"end_time": "2026-06-07T01:00:00+02:00",
"wind": { "direction": 200, "speed": 14, "gust": null, "variable": [] },
"visibility": { "value": null, "repr": "P6" },
"clouds": [
{ "type": "SCT", "base": 70, "repr": "SCT070" },
{ "type": "BKN", "base": 250, "repr": "BKN250" }
],
"wx_codes": [],
"flight_rules": "VFR",
"probability": null,
"turbulence": [],
"icing": []
},
{
"type": "TEMPO",
"start_time": "2026-06-07T01:00:00+02:00",
"end_time": "2026-06-07T05:00:00+02:00",
"wind": { "direction": 290, "speed": 25, "gust": 45, "variable": [] },
"visibility": { "value": 3, "repr": "3" },
"clouds": [
{ "type": "SCT", "base": 25, "repr": "SCT025" },
{ "type": "BKN", "base": 50, "repr": "BKN050CB" }
],
"wx_codes": [
{ "repr": "TSRA", "value": "Thunderstorm Rain" },
{ "repr": "BR", "value": "Mist" }
],
"flight_rules": "MVFR",
"probability": null,
"turbulence": [],
"icing": []
}
]
}
}| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
parsed | object | Да (при parsed=true) | Отсутствует при parsed=false — не null |
parsed.start_time | string (ISO 8601) | Да | Начало периода действия TAF (DDHH/DDHH в исходной строке) |
parsed.end_time | string (ISO 8601) | Да | Конец периода действия TAF |
parsed.forecast | array | Да | Периоды прогноза в хронологическом порядке — см. Типы периодов прогноза |
parsed.forecast[].type | string | Да (для каждого элемента) | FROM, TEMPO или BECMG |
parsed.forecast[].start_time | string (ISO 8601) | Да (для каждого элемента) | Когда эта группа начинает действовать |
parsed.forecast[].end_time | string (ISO 8601) | Да (для каждого элемента) | Когда эта группа заканчивается |
parsed.forecast[].wind | object | Да (для каждого элемента) | Та же структура, что у METAR parsed.wind |
parsed.forecast[].visibility | object | Да (для каждого элемента) | Та же структура, что у METAR parsed.visibility |
parsed.forecast[].clouds | array | Да (для каждого элемента) | Та же структура, что у METAR parsed.clouds, — коды облачности |
parsed.forecast[].wx_codes | array | Да (для каждого элемента) | Ожидаемые погодные явления — { repr, value }[] |
parsed.forecast[].flight_rules | string | Да (для каждого элемента) | Ожидаемая категория полётных условий для этой группы |
parsed.forecast[].probability | object | null | Да (ключ присутствует всегда) | Заполняется в группах PROB30/PROB40 — см. ниже |
parsed.forecast[].turbulence | array | Да (для каждого элемента) | Интенсивность атмосферной турбулентности, если она указана в прогнозе, — [], если её нет |
parsed.forecast[].icing | array | Да (для каждого элемента) | Интенсивность обледенения ВС, если оно указано в прогнозе, — [], если его нет |
Схемы объектов и допустимость null
Каждый объект в parsed.forecast[] содержит одинаковый набор ключей во всех периодах — для wind, visibility, clouds и wx_codes действуют те же правила, что и для допустимости null в METAR.
| Поле | Тип | Обязательный | Null / пусто | Примечания |
|---|---|---|---|---|
parsed.forecast[].wind | object | Да | Присутствует всегда | Та же форма, что у METAR parsed.wind |
parsed.forecast[].visibility | object | Да | Присутствует всегда | value: null часто встречается при P6SM (repr: "P6") |
parsed.forecast[].clouds | array | Да | Возможно [] | Та же форма элементов, что в METAR |
parsed.forecast[].wx_codes | array | Да | [], если явлений нет | Та же форма элементов { repr, value }, что в METAR |
parsed.forecast[].probability | object | null | Да | null в большинстве групп | Объект в группах PROB30/PROB40 — см. ниже |
parsed.forecast[].turbulence | array | Да | [], если не указана | Никогда не null |
parsed.forecast[].icing | array | Да | [], если не указано | Никогда не null |
При parsed=false ключ parsed полностью отсутствует.
Вероятность в группах PROB
В исходном TAF группы PROB30 и PROB40 обозначают вероятностные подпериоды (вероятность явления 30 % или 40 %). В рабочем JSON они представлены записью FROM или TEMPO с заполненным объектом probability — отдельного type: "PROB" нет (проверено на KORD, EGLL, EDDF).
"probability": {
"repr": "30",
"value": 30,
"spoken": "three zero"
}| Поле | Тип | Обязательный | Описание |
|---|---|---|---|
repr | string | Да | Исходный токен: "30" или "40" |
value | integer | Да | 30 или 40 |
spoken | string | Да | Устная форма из бюллетеня |
Если группа не вероятностная, probability равно null.
Турбулентность, обледенение и типы периодов прогнозаРазвернуть раздел
Группы турбулентности и обледенения
Большинство периодов прогноза возвращают "turbulence": [] и "icing": []. Если исходный TAF содержит группы TURB или ICE, каждый массив содержит один или несколько объектов как минимум с полями repr (исходный токен) и value (интенсивность в удобочитаемом виде) — тот же шаблон { repr, value }, что и у wx_codes. Если в бюллетене указан вертикальный слой, могут появиться дополнительные ключи высоты; относитесь к неизвестным ключам как к расширениям, совместимым с будущими версиями.
"turbulence": [{ "repr": "MOD", "value": "Moderate" }],
"icing": []Типы периодов прогноза
Проходите по parsed.forecast[] в хронологическом порядке: сначала действующая базовая группа FROM, затем перекрывающие её модификаторы.
| Токен TAF | type в JSON | Поля времени | Что это значит |
|---|---|---|---|
Начальная группа / FM | FROM | start_time → end_time | Базовые условия. Каждая группа FM заменяет всё, что было до неё, начиная с start_time |
TEMPO | TEMPO | start_time → end_time | Временные колебания в рамках базовых условий — показывайте как оговорку, а не как замену |
BECMG | BECMG | start_time → end_time | Постепенное изменение к значениям этой группы к моменту end_time |
PROB30 / PROB40 | FROM или TEMPO + probability | как у родительского типа | Вероятностный подпериод — непустой probability в строке |
Чтение периодов для времени вылета
- Отфильтруйте
parsed.forecast[]по условиюtype == "FROM"иstart_time <= departure <= end_time— это базовые условия. - Соберите перекрывающиеся строки
TEMPO,BECMGи вероятностные строки — это модификаторы. - Выводите базовое значение flight_rules на видном месте; модификаторы перечисляйте отдельно.
- Наихудший сценарий по всему TAF: наивысший ранг flight_rules среди всех групп
FROM.
Пример для KORD: базовая группа FROM может давать VFR, а перекрывающая её TEMPO — MVFR с -SHRA; показывайте оба значения.
Клиентские типы
Скопируйте в свой проект. Допустимость null соответствует разделам Схемы объектов и допустимость null и допустимость null в METAR для общих вложенных объектов.
"""TAF response and departure-summary types - matches weather-taf field tables."""from __future__ import annotationsfrom dataclasses import dataclassfrom typing import LiteralFlightRules = Literal["VFR", "MVFR", "IFR", "LIFR"]TafPeriodType = Literal["FROM", "TEMPO", "BECMG"]@dataclassclass TafRequest: """Path/query input for GET /weather/taf/{icao}.""" icao: str parsed: bool = False@dataclassclass TafWind: direction: int speed: int gust: int | None variable: list[int]@dataclassclass TafVisibility: value: float | None repr: str@dataclassclass TafCloudLayer: type: str base: int repr: str@dataclassclass TafWxCode: repr: str value: str@dataclassclass TafProbability: repr: str value: Literal[30, 40] spoken: str@dataclassclass TafPeriod: type: TafPeriodType start_time: str end_time: str wind: TafWind visibility: TafVisibility clouds: list[TafCloudLayer] wx_codes: list[TafWxCode] flight_rules: FlightRules probability: TafProbability | None turbulence: list[object] icing: list[object]@dataclassclass TafParsed: start_time: str end_time: str forecast: list[TafPeriod]@dataclassclass TafResponse: raw: str icao: str airport_name: str timestamp: str parsed: TafParsed | None = None@dataclassclass TafModifierSummary: type: TafPeriodType category: FlightRules probability: int | None wx: list[str]@dataclassclass TafDepartureSummary: """Shape returned by taf_at_departure() in the fetch example.""" icao: str valid_to: str baseline_category: FlightRules | None modifiers: list[TafModifierSummary] worst_from_category: FlightRules | NoneTafResponse / TafParsed / TafPeriod соответствуют JSON API. TafDepartureSummary определён в начале каждой вкладки примера кода.
Интеграция
Получение, кэширование и интерпретация периодов прогноза на время вылета.
Пример кэширует каждый TAF на пятнадцать минут (TAF переиздаются четыре раза в сутки), использует тайм-ауты подключения/чтения 10 с / 15 с, выбирает действующую группу FROM на время вылета и перечисляет перекрывающиеся модификаторы TEMPO/BECMG.
import osimport timefrom dataclasses import dataclassfrom datetime import datetime, timezonefrom typing import Literalimport requests# TafDepartureSummary - helper return type. Full wire types (TafResponse, TafPeriod, …)# are in the Client types section on the TAF docs page.FlightRules = Literal["VFR", "MVFR", "IFR", "LIFR"]TafPeriodType = Literal["FROM", "TEMPO", "BECMG"]@dataclassclass TafModifierSummary: type: TafPeriodType category: FlightRules probability: int | None wx: list[str]@dataclassclass TafDepartureSummary: icao: str valid_to: str baseline_category: FlightRules | None modifiers: list[TafModifierSummary] worst_from_category: FlightRules | NoneHEADERS = { "x-api-key": os.getenv("SKYLINK_API_KEY", "YOUR_API_KEY")}BASE = "https://data.skylinkapi.com/v3.1"CACHE: dict[str, tuple[dict, float]] = {}TAF_TTL = 900CATEGORY_RANK = {"VFR": 0, "MVFR": 1, "IFR": 2, "LIFR": 3}def parse_time(iso: str) -> datetime: return datetime.fromisoformat(iso.replace("Z", "+00:00"))def fetch_taf(icao: str) -> dict | None: cache_key = f"taf:{icao}:parsed" cached = CACHE.get(cache_key) if cached and time.time() < cached[1]: return cached[0] try: r = requests.get( f"{BASE}/weather/taf/{icao}", headers=HEADERS, params={"parsed": "true"}, timeout=(10, 15), ) except requests.Timeout as exc: raise RuntimeError(f"SkyLink timeout fetching TAF for {icao}") from exc if r.status_code == 404: return None r.raise_for_status() data = r.json() CACHE[cache_key] = (data, time.time() + TAF_TTL) return datadef taf_at_departure(icao: str, departure: datetime | None = None) -> TafDepartureSummary | None: taf = fetch_taf(icao) if not taf: return None at = departure or datetime.now(timezone.utc) forecast = taf["parsed"]["forecast"] baseline = next( ( p for p in forecast if p["type"] == "FROM" and parse_time(p["start_time"]) <= at <= parse_time(p["end_time"]) ), None, ) modifiers = [ TafModifierSummary( type=p["type"], category=p["flight_rules"], probability=(p["probability"] or {}).get("value"), wx=[w["repr"] for w in p["wx_codes"]], ) for p in forecast if p is not baseline and parse_time(p["start_time"]) <= at <= parse_time(p["end_time"]) ] from_groups = [p for p in forecast if p["type"] == "FROM"] worst = ( max(from_groups, key=lambda p: CATEGORY_RANK.get(p["flight_rules"], -1))["flight_rules"] if from_groups else None ) return TafDepartureSummary( icao=icao, valid_to=taf["parsed"]["end_time"], baseline_category=baseline["flight_rules"] if baseline else None, modifiers=modifiers, worst_from_category=worst, )if __name__ == "__main__": import json from dataclasses import asdict summary = taf_at_departure("KJFK") print(json.dumps(asdict(summary), indent=2) if summary else "TAF not available")Пошаговый разбор наложения периодов: Наложение периодов TAF.
Примечания по реализации
Чтение групп TEMPO и вероятностных групп. TEMPO накладывается на действующую базовую группу FROM. PROB30/PROB40 представлены строками с непустым probability — проверяйте probability.value, а не отдельный type. См. Типы периодов прогноза.
TAF обновляются четыре раза в сутки — в 00Z, 06Z, 12Z и 18Z. Кэширование на 15–30 минут вполне уместно.
404 при отсутствии TAF. Многие аэродромы авиации общего назначения публикуют только METAR. Воспринимайте 404 для TAF как отсутствие прогнозных данных, а не как неудачный запрос.
Совместное использование с METAR. Запрашивайте оба параллельно. Используйте flight_rules из METAR для текущих условий, а наихудшее значение flight_rules среди групп FROM по всему TAF — как наихудшие ожидаемые.
Ответы с ошибками
Здесь описаны только ошибки, специфичные для TAF. Общие ошибки: Обработка ошибок. 404 для METAR и для TAF в продакшне: Когда погодные данные отсутствуют.
404 — нет TAF для этого кода ICAO
{
"detail": "No current TAF forecast available for KOXB. Weather station may not issue TAF reports or may be temporarily offline."
}Типичный случай: у аэропорта есть METAR, но нет TAF. Запрашивайте METAR как обычно; пропустите TAF и выведите в интерфейсе Прогноз недоступен.
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 TAF fields alongside raw text
falseResponse Body
application/json
application/json
curl -X GET "https://data.skylinkapi.com/v3.1/weather/taf/KJFK"{
"raw": "TAF KJFK 271720Z 2718/2824 16012KT P6SM FEW025 SCT250 FM272100 18010KT P6SM SCT025 BKN250",
"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": {}
}
]
}См. также: METAR · Сценарии использования · Ошибки · Продакшн
METAR
Текущая сводка METAR о приземной погоде для любого аэропорта ICAO. Опциональный декодированный вывод: ветер, видимость, облачность, категория полётных условий.
Ветер на высотах
Ветер на высотах (FB) для маршрутов в США: направление и скорость ветра и температура на стандартных высотах в пределах bbox.