Save up to 17% with yearly billing

See pricing

TAF

TAF (прогнозы по аэродрому) — это структурированные прогнозы для конкретного аэропорта и его ближайших окрестностей, обычно охватывающие примерно пять морских миль вокруг аэродрома. Стандартные TAF выпускаются четыре раза в сутки — в 00Z, 06Z, 12Z и 18Z — и действуют 24 или 30 часов в зависимости от станции. Каждый TAF описывает ожидаемые ветер, видимость, слои облачности, погодные явления и категории полётных условий в рамках прогнозных групп с привязкой ко времени, таких как FROM, TEMPO и BECMG. Пилоты, диспетчеры по обеспечению полётов и специалисты по планированию полётов используют эти прогнозы, чтобы оценить ожидаемые условия в аэропортах вылета, назначения и запасных при составлении оперативных планов. Многие небольшие аэропорты публикуют только METAR — ответ 404 для TAF встречается часто и не означает, что аэропорт неизвестен.

Запрос

Требования

Авторизация
x-api-key в каждом запросе (прямая подписка). Подробнее →
ICAO
4-буквенный код аэропорта (например, KJFK). Коды аэропортов США обычно начинаются с K. Подробнее →

Отправьте запрос GET с кодом ICAO аэропорта в пути. Необязательные query-флаги управляют декодированием.

GEThttps://data.skylinkapi.com/v3.1/weather/taf/{icao}
ПараметрТипОбязательныйПо умолчаниюОписание
icaostringДа-Четырёхбуквенный код ICAO — поиск, например KJFK
parsedbooleanНет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"
}
ПолеТипОбязательныйОписание
rawstringДаПолная строка TAF в исходном виде
icaostringДаКод ICAO
airport_namestringДаНазвание аэропорта
timestampstring (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": []
      }
    ]
  }
}
ПолеТипОбязательныйОписание
parsedobjectДа (при parsed=true)Отсутствует при parsed=false — не null
parsed.start_timestring (ISO 8601)ДаНачало периода действия TAF (DDHH/DDHH в исходной строке)
parsed.end_timestring (ISO 8601)ДаКонец периода действия TAF
parsed.forecastarrayДаПериоды прогноза в хронологическом порядке — см. Типы периодов прогноза
parsed.forecast[].typestringДа (для каждого элемента)FROM, TEMPO или BECMG
parsed.forecast[].start_timestring (ISO 8601)Да (для каждого элемента)Когда эта группа начинает действовать
parsed.forecast[].end_timestring (ISO 8601)Да (для каждого элемента)Когда эта группа заканчивается
parsed.forecast[].windobjectДа (для каждого элемента)Та же структура, что у METAR parsed.wind
parsed.forecast[].visibilityobjectДа (для каждого элемента)Та же структура, что у METAR parsed.visibility
parsed.forecast[].cloudsarrayДа (для каждого элемента)Та же структура, что у METAR parsed.clouds, — коды облачности
parsed.forecast[].wx_codesarrayДа (для каждого элемента)Ожидаемые погодные явления — { repr, value }[]
parsed.forecast[].flight_rulesstringДа (для каждого элемента)Ожидаемая категория полётных условий для этой группы
parsed.forecast[].probabilityobject | nullДа (ключ присутствует всегда)Заполняется в группах PROB30/PROB40 — см. ниже
parsed.forecast[].turbulencearrayДа (для каждого элемента)Интенсивность атмосферной турбулентности, если она указана в прогнозе, — [], если её нет
parsed.forecast[].icingarrayДа (для каждого элемента)Интенсивность обледенения ВС, если оно указано в прогнозе, — [], если его нет

Схемы объектов и допустимость null

Каждый объект в parsed.forecast[] содержит одинаковый набор ключей во всех периодах — для wind, visibility, clouds и wx_codes действуют те же правила, что и для допустимости null в METAR.

ПолеТипОбязательныйNull / пустоПримечания
parsed.forecast[].windobjectДаПрисутствует всегдаТа же форма, что у METAR parsed.wind
parsed.forecast[].visibilityobjectДаПрисутствует всегдаvalue: null часто встречается при P6SM (repr: "P6")
parsed.forecast[].cloudsarrayДаВозможно []Та же форма элементов, что в METAR
parsed.forecast[].wx_codesarrayДа[], если явлений нетТа же форма элементов { repr, value }, что в METAR
parsed.forecast[].probabilityobject | nullДаnull в большинстве группОбъект в группах PROB30/PROB40 — см. ниже
parsed.forecast[].turbulencearrayДа[], если не указанаНикогда не null
parsed.forecast[].icingarrayДа[], если не указаноНикогда не 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"
}
ПолеТипОбязательныйОписание
reprstringДаИсходный токен: "30" или "40"
valueintegerДа30 или 40
spokenstringДаУстная форма из бюллетеня

Если группа не вероятностная, probability равно null.

Турбулентность, обледенение и типы периодов прогнозаРазвернуть раздел

Группы турбулентности и обледенения

Большинство периодов прогноза возвращают "turbulence": [] и "icing": []. Если исходный TAF содержит группы TURB или ICE, каждый массив содержит один или несколько объектов как минимум с полями repr (исходный токен) и value (интенсивность в удобочитаемом виде) — тот же шаблон { repr, value }, что и у wx_codes. Если в бюллетене указан вертикальный слой, могут появиться дополнительные ключи высоты; относитесь к неизвестным ключам как к расширениям, совместимым с будущими версиями.

"turbulence": [{ "repr": "MOD", "value": "Moderate" }],
"icing": []

Типы периодов прогноза

Проходите по parsed.forecast[] в хронологическом порядке: сначала действующая базовая группа FROM, затем перекрывающие её модификаторы.

Токен TAFtype в JSONПоля времениЧто это значит
Начальная группа / FMFROMstart_time → end_timeБазовые условия. Каждая группа FM заменяет всё, что было до неё, начиная с start_time
TEMPOTEMPOstart_time → end_timeВременные колебания в рамках базовых условий — показывайте как оговорку, а не как замену
BECMGBECMGstart_time → end_timeПостепенное изменение к значениям этой группы к моменту end_time
PROB30 / PROB40FROM или TEMPO + probabilityкак у родительского типаВероятностный подпериод — непустой probability в строке

Чтение периодов для времени вылета

  1. Отфильтруйте parsed.forecast[] по условию type == "FROM" и start_time <= departure <= end_time — это базовые условия.
  2. Соберите перекрывающиеся строки TEMPO, BECMG и вероятностные строки — это модификаторы.
  3. Выводите базовое значение flight_rules на видном месте; модификаторы перечисляйте отдельно.
  4. Наихудший сценарий по всему 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 | None

TafResponse / 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 и выведите в интерфейсе Прогноз недоступен.

GET
/weather/taf/{icao}
x-api-key<token>

Your SkyLink licence key, for keys bought direct from skylinkapi.com.

In: header

Path Parameters

icao*Icao

4-letter ICAO airport code

Length4 <= length <= 4

Query Parameters

parsed?Parsed

Include parsed/decoded TAF fields alongside raw text

Defaultfalse

Response 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 · Сценарии использования · Ошибки · Продакшн