跳转至

机场快报

机场快报为专线接口产品,提供中国境内 225+ 机场 METAR/SPECI 报文的低延迟快速查询与 WebSocket 推送服务。

与标准接口的区别

标准接口 METAR 机场快报
时效性 支持历史回溯,约 5 分钟延迟 仅最新一批数据,约 1 分钟延迟
数据范围 支持历史数据查询 不支持历史数据,仅可获取当前最新报文
协议 仅 HTTP REST HTTP REST + WebSocket 推送
SLA 99.9% 可用性保障
计费 按次扣资源点 按时长订阅

Base URL

https://special.data-api.skyviewor.host/fast-metar

鉴权

机场快报沿用开发者 API 通用鉴权方式,支持 API Key 直接鉴权Token 鉴权两种模式,两种模式最终效果相同,调用同一个数据接口。

API Key 直接鉴权

与标准接口一致,在 Authorization Header 中携带 Bearer <API Key> 即可直接调用数据接口:

Authorization: Bearer sk-d5d0542bef7e42e2b8909cb7f42af5fb

Token 鉴权

Token 鉴权通过"先换取临时令牌再调用"的方式,进一步降低 API Key 在网络传输中的泄露风险。流程如下:

  1. 用 API Key 换取临时数据令牌(有效期 5 分钟)
  2. 用令牌调用数据接口或建立 WebSocket 连接

WebSocket 场景建议使用 Token 鉴权(浏览器端 WebSocket API 不支持自定义 Header)。

获取令牌

# 更换为您的以 sk- 开头的 API Key 字符串
curl -s \
  -H "Authorization: Bearer sk-d5d0542bef7e42e2b8909cb7f42af5fb" \
  -X POST "https://special.data-api.skyviewor.host/fast-metar/auth/token"
import json, urllib.request

API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"  # 更换为您的以 sk- 开头的 API Key 字符串

req = urllib.request.Request(
    "https://special.data-api.skyviewor.host/fast-metar/auth/token",
    method="POST",
    headers={"Authorization": f"Bearer {API_KEY}"},
)
with urllib.request.urlopen(req, timeout=30) as resp:
    token_data = json.loads(resp.read().decode())
print(token_data["token"])  # ft-...
const API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

const resp = await fetch("https://special.data-api.skyviewor.host/fast-metar/auth/token", {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { token } = await resp.json();
console.log(token); // ft-...
const API_KEY: string = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

const resp = await fetch("https://special.data-api.skyviewor.host/fast-metar/auth/token", {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { token }: { token: string } = await resp.json();
console.log(token); // ft-...
apiKey := "sk-d5d0542bef7e42e2b8909cb7f42af5fb" // 更换为您的以 sk- 开头的 API Key 字符串

req, _ := http.NewRequest("POST", "https://special.data-api.skyviewor.host/fast-metar/auth/token", nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var tokenData map[string]interface{}
json.Unmarshal(body, &tokenData)
fmt.Println(tokenData["token"])
String API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/auth/token"))
    .header("Authorization", "Bearer " + API_KEY)
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
var apiKey = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
var json = await client.PostAsync("https://special.data-api.skyviewor.host/fast-metar/auth/token", null);
Console.WriteLine(await json.Content.ReadAsStringAsync());
$API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

$ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/auth/token");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer {$API_KEY}"]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
echo $result['token'] . "\n";

令牌返回格式:

{
  "token": "ft-a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  "expires_at": "2026-06-22T03:05:00+00:00"
}

RESTful 接口

原始 METAR 查询

查询指定机场的最新 METAR/SPECI 原始报文。

项目 内容
方法 GET
路径 https://special.data-api.skyviewor.host/fast-metar/rest/raw

请求参数

参数 类型 必填 说明
icaos string ICAO 机场代码,逗号分隔,如 ZBAA,ZSPD

响应示例

{
  "data": [
    {
      "icao": "ZBAA",
      "raw_metar": "METAR ZBAA 220230Z VRB02MPS CAVOK 27/17 Q1007 NOSIG=",
      "obs_time": "2026-06-22T10:30:00+08:00",
      "report_type": "METAR",
      "arrived_at": "2026-06-22T02:30:58+00:00"
    }
  ]
}

代码示例

# 更换为您的以 sk- 开头的 API Key 字符串

# 方式一:API Key 直接鉴权
curl -s \
  -H "Authorization: Bearer sk-d5d0542bef7e42e2b8909cb7f42af5fb" \
  "https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG"

# 方式二:Token 鉴权
# 步骤1:获取数据令牌(返回 JSON,其中 "token" 字段即为令牌值)
curl -s -X POST \
  -H "Authorization: Bearer sk-d5d0542bef7e42e2b8909cb7f42af5fb" \
  "https://special.data-api.skyviewor.host/fast-metar/auth/token"

# 步骤2:用令牌调用数据接口(将 <TOKEN> 替换为上一步返回的 token 值)
curl -s "https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG&token=<TOKEN>"
import json, urllib.request

API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"  # 更换为您的以 sk- 开头的 API Key 字符串

# 方式一:API Key 直接鉴权
url = "https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG"
req = urllib.request.Request(url, headers={"Authorization": f"Bearer {API_KEY}"})
with urllib.request.urlopen(req, timeout=30) as resp:
    result = json.loads(resp.read().decode())

# 方式二:Token 鉴权
def get_token():
    req = urllib.request.Request(
        "https://special.data-api.skyviewor.host/fast-metar/auth/token",
        method="POST",
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    with urllib.request.urlopen(req, timeout=30) as resp:
        return json.loads(resp.read().decode())["token"]

token = get_token()
url = f"https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG&token={token}"
req = urllib.request.Request(url)
with urllib.request.urlopen(req, timeout=30) as resp:
    result = json.loads(resp.read().decode())

for item in result["data"]:
    print(f"{item['icao']}: {item['raw_metar']}")
const API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
let url = "https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG";
let resp = await fetch(url, {
  headers: { Authorization: `Bearer ${API_KEY}` },
});
let result = await resp.json();

// 方式二:Token 鉴权
const tokenResp = await fetch("https://special.data-api.skyviewor.host/fast-metar/auth/token", {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { token } = await tokenResp.json();
url = `https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG&token=${token}`;
resp = await fetch(url);
result = await resp.json();

for (const item of result.data) {
  console.log(`${item.icao}: ${item.raw_metar}`);
}
const API_KEY: string = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
let url = "https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG";
let resp = await fetch(url, {
  headers: { Authorization: `Bearer ${API_KEY}` },
});
let result: any = await resp.json();

// 方式二:Token 鉴权
const tokenResp = await fetch("https://special.data-api.skyviewor.host/fast-metar/auth/token", {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { token }: { token: string } = await tokenResp.json();
url = `https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG&token=${token}`;
resp = await fetch(url);
result = await resp.json();

for (const item of result.data) {
  console.log(`${item.icao}: ${item.raw_metar}`);
}
apiKey := "sk-d5d0542bef7e42e2b8909cb7f42af5fb" // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
req, _ := http.NewRequest("GET",
    "https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG", nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)

// 方式二:Token 鉴权
tokenReq, _ := http.NewRequest("POST", "https://special.data-api.skyviewor.host/fast-metar/auth/token", nil)
tokenReq.Header.Set("Authorization", "Bearer "+apiKey)
tokenResp, _ := http.DefaultClient.Do(tokenReq)
tokenBody, _ := io.ReadAll(tokenResp.Body)
tokenResp.Body.Close()
var tokenData map[string]interface{}
json.Unmarshal(tokenBody, &tokenData)
token := tokenData["token"].(string)

req, _ = http.NewRequest("GET",
    "https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG&token="+token, nil)
resp, _ = http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ = io.ReadAll(resp.Body)

var result map[string]interface{}
json.Unmarshal(body, &result)
for _, item := range result["data"].([]interface{}) {
    m := item.(map[string]interface{})
    fmt.Printf("%v: %v\n", m["icao"], m["raw_metar"])
}
String API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG"))
    .header("Authorization", "Bearer " + API_KEY)
    .GET().build();
HttpResponse<String> resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());

// 方式二:Token 鉴权
HttpRequest tokenReq = HttpRequest.newBuilder()
    .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/auth/token"))
    .header("Authorization", "Bearer " + API_KEY)
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> tokenResp = HttpClient.newHttpClient().send(tokenReq, HttpResponse.BodyHandlers.ofString());
String token = com.google.gson.JsonParser.parseString(tokenResp.body())
    .getAsJsonObject().get("token").getAsString();

req = HttpRequest.newBuilder()
    .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG&token=" + token))
    .GET().build();
resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());

System.out.println(resp.body());
var apiKey = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

using var client = new HttpClient();

// 方式一:API Key 直接鉴权
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
var json = await client.GetStringAsync("https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG");

// 方式二:Token 鉴权
var tokenJson = await client.PostAsync("https://special.data-api.skyviewor.host/fast-metar/auth/token", null);
using var doc = JsonDocument.Parse(await tokenJson.Content.ReadAsStringAsync());
var token = doc.RootElement.GetProperty("token").GetString();
client.DefaultRequestHeaders.Remove("Authorization");
json = await client.GetStringAsync($"https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG&token={token}");

using var resultDoc = JsonDocument.Parse(json);
foreach (var item in resultDoc.RootElement.GetProperty("data").EnumerateArray())
{
    Console.WriteLine($"{item.GetProperty("icao").GetString()}: {item.GetProperty("raw_metar").GetString()}");
}
$API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
$ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer {$API_KEY}"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);

// 方式二:Token 鉴权
$ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/auth/token");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer {$API_KEY}"]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$tokenData = json_decode(curl_exec($ch), true);
curl_close($ch);
$token = $tokenData["token"];

$ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/rest/raw?icaos=ZBAA,ZSPD,ZGGG&token={$token}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);

foreach ($result["data"] as $item) {
    echo "{$item["icao"]}: {$item["raw_metar"]}\n";
}

结构化 METAR 查询

查询指定机场的最新 METAR/SPECI 结构化数据。

项目 内容
方法 GET
路径 https://special.data-api.skyviewor.host/fast-metar/rest/parsed

请求参数

参数 类型 必填 说明
icaos string ICAO 机场代码,逗号分隔

响应示例

{
  "data": [
    {
      "icao": "ZBAA",
      "raw_metar": "METAR ZBAA 220230Z VRB02MPS CAVOK 27/17 Q1007 NOSIG=",
      "obs_time": "2026-06-22T10:30:00+08:00",
      "report_type": "METAR",
      "arrived_at": "2026-06-22T02:30:58+00:00",
      "parsed": {
        "kind": "METAR",
        "icao": "ZBAA",
        "datetime": "2026-06-22T02:30:00+00:00",
        "temperature": 27,
        "dew_temperature": 17,
        "temperature_units": "degree C",
        "wind_speed": 2,
        "wind_speed_units": "m/s",
        "qnh": 1007,
        "qnh_units": "hPa",
        "cavok": true
      }
    }
  ]
}

代码示例

# 更换为您的以 sk- 开头的 API Key 字符串

# 方式一:API Key 直接鉴权
curl -s \
  -H "Authorization: Bearer sk-d5d0542bef7e42e2b8909cb7f42af5fb" \
  "https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG"

# 方式二:Token 鉴权
# 步骤1:获取数据令牌(返回 JSON,其中 "token" 字段即为令牌值)
curl -s -X POST \
  -H "Authorization: Bearer sk-d5d0542bef7e42e2b8909cb7f42af5fb" \
  "https://special.data-api.skyviewor.host/fast-metar/auth/token"

# 步骤2:用令牌调用数据接口(将 <TOKEN> 替换为上一步返回的 token 值)
curl -s "https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG&token=<TOKEN>"
import json, urllib.request

API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"  # 更换为您的以 sk- 开头的 API Key 字符串

# 方式一:API Key 直接鉴权
url = "https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG"
req = urllib.request.Request(url, headers={"Authorization": f"Bearer {API_KEY}"})
with urllib.request.urlopen(req, timeout=30) as resp:
    result = json.loads(resp.read().decode())

# 方式二:Token 鉴权
def get_token():
    req = urllib.request.Request(
        "https://special.data-api.skyviewor.host/fast-metar/auth/token",
        method="POST",
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    with urllib.request.urlopen(req, timeout=30) as resp:
        return json.loads(resp.read().decode())["token"]

token = get_token()
url = f"https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG&token={token}"
req = urllib.request.Request(url)
with urllib.request.urlopen(req, timeout=30) as resp:
    result = json.loads(resp.read().decode())

for item in result["data"]:
    print(f"{item['icao']}: {item['parsed']['temperature']}°C")
const API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
let url = "https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG";
let resp = await fetch(url, {
  headers: { Authorization: `Bearer ${API_KEY}` },
});
let result = await resp.json();

// 方式二:Token 鉴权
const tokenResp = await fetch("https://special.data-api.skyviewor.host/fast-metar/auth/token", {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { token } = await tokenResp.json();
url = `https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG&token=${token}`;
resp = await fetch(url);
result = await resp.json();

for (const item of result.data) {
  console.log(`${item.icao}: ${item.parsed.temperature}°C`);
}
const API_KEY: string = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
let url = "https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG";
let resp = await fetch(url, {
  headers: { Authorization: `Bearer ${API_KEY}` },
});
let result: any = await resp.json();

// 方式二:Token 鉴权
const tokenResp = await fetch("https://special.data-api.skyviewor.host/fast-metar/auth/token", {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { token }: { token: string } = await tokenResp.json();
url = `https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG&token=${token}`;
resp = await fetch(url);
result = await resp.json();

for (const item of result.data) {
  console.log(`${item.icao}: ${item.parsed.temperature}°C`);
}
apiKey := "sk-d5d0542bef7e42e2b8909cb7f42af5fb" // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
req, _ := http.NewRequest("GET",
    "https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG", nil)
req.Header.Set("Authorization", "Bearer "+apiKey)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)

// 方式二:Token 鉴权
tokenReq, _ := http.NewRequest("POST", "https://special.data-api.skyviewor.host/fast-metar/auth/token", nil)
tokenReq.Header.Set("Authorization", "Bearer "+apiKey)
tokenResp, _ := http.DefaultClient.Do(tokenReq)
tokenBody, _ := io.ReadAll(tokenResp.Body)
tokenResp.Body.Close()
var tokenData map[string]interface{}
json.Unmarshal(tokenBody, &tokenData)
token := tokenData["token"].(string)

req, _ = http.NewRequest("GET",
    "https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG&token="+token, nil)
resp, _ = http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ = io.ReadAll(resp.Body)

var result map[string]interface{}
json.Unmarshal(body, &result)
for _, item := range result["data"].([]interface{}) {
    m := item.(map[string]interface{})
    p := m["parsed"].(map[string]interface{})
    fmt.Printf("%v: %v°C\n", m["icao"], p["temperature"])
}
String API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG"))
    .header("Authorization", "Bearer " + API_KEY)
    .GET().build();
HttpResponse<String> resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());

// 方式二:Token 鉴权
HttpRequest tokenReq = HttpRequest.newBuilder()
    .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/auth/token"))
    .header("Authorization", "Bearer " + API_KEY)
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();
HttpResponse<String> tokenResp = HttpClient.newHttpClient().send(tokenReq, HttpResponse.BodyHandlers.ofString());
String token = com.google.gson.JsonParser.parseString(tokenResp.body())
    .getAsJsonObject().get("token").getAsString();

req = HttpRequest.newBuilder()
    .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG&token=" + token))
    .GET().build();
resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());

System.out.println(resp.body());
var apiKey = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

using var client = new HttpClient();

// 方式一:API Key 直接鉴权
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
var json = await client.GetStringAsync("https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG");

// 方式二:Token 鉴权
var tokenJson = await client.PostAsync("https://special.data-api.skyviewor.host/fast-metar/auth/token", null);
using var doc = JsonDocument.Parse(await tokenJson.Content.ReadAsStringAsync());
var token = doc.RootElement.GetProperty("token").GetString();
client.DefaultRequestHeaders.Remove("Authorization");
json = await client.GetStringAsync($"https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG&token={token}");

using var resultDoc = JsonDocument.Parse(json);
foreach (var item in resultDoc.RootElement.GetProperty("data").EnumerateArray())
{
    var t = item.GetProperty("parsed").GetProperty("temperature").GetDouble();
    Console.WriteLine($"{item.GetProperty("icao").GetString()}: {t}°C");
}
$API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直接鉴权
$ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer {$API_KEY}"]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);

// 方式二:Token 鉴权
$ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/auth/token");
curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer {$API_KEY}"]);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$tokenData = json_decode(curl_exec($ch), true);
curl_close($ch);
$token = $tokenData["token"];

$ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/rest/parsed?icaos=ZBAA,ZSPD,ZGGG&token={$token}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);

foreach ($result["data"] as $item) {
    echo "{$item["icao"]}: {$item["parsed"]["temperature"]}°C\n";
}

全量机场查询

在以上路径后追加 /all 即可查询全部机场(如 https://special.data-api.skyviewor.host/fast-metar/rest/raw/all),无需 icaos 参数。

传输延时统计

查询指定机场从观测时间到服务端接收时间的平均延时。

项目 内容
方法 GET
路径 https://special.data-api.skyviewor.host/fast-metar/rest/latency
鉴权 无需鉴权(IP 限流 QPS=2)

请求参数

参数 类型 必填 说明
icaos string ICAO 机场代码,逗号分隔,如 ZBAA,ZSPD

也可使用 https://special.data-api.skyviewor.host/fast-metar/rest/latency/all 查询全部机场。

响应示例

{
  "data": [
    {"icao": "ZBAA", "avg_latency_seconds": 62.5, "sample_count": 45}
  ]
}

代码示例

curl -s "https://special.data-api.skyviewor.host/fast-metar/rest/latency?icaos=ZBAA,ZSPD,ZGGG"
import json, urllib.request

url = "https://special.data-api.skyviewor.host/fast-metar/rest/latency?icaos=ZBAA,ZSPD,ZGGG"
with urllib.request.urlopen(url, timeout=30) as resp:
    result = json.loads(resp.read().decode())

for item in result["data"]:
    print(f"{item['icao']}: 平均延时 {item['avg_latency_seconds']}s({item['sample_count']} 样本)")
const url = "https://special.data-api.skyviewor.host/fast-metar/rest/latency?icaos=ZBAA,ZSPD,ZGGG";
const resp = await fetch(url);
const result = await resp.json();
for (const item of result.data) {
  console.log(`${item.icao}: 平均延时 ${item.avg_latency_seconds}s(${item.sample_count} 样本)`);
}
const url = "https://special.data-api.skyviewor.host/fast-metar/rest/latency?icaos=ZBAA,ZSPD,ZGGG";
const resp = await fetch(url);
const result: any = await resp.json();
for (const item of result.data) {
  console.log(`${item.icao}: 平均延时 ${item.avg_latency_seconds}s(${item.sample_count} 样本)`);
}
resp, _ := http.Get("https://special.data-api.skyviewor.host/fast-metar/rest/latency?icaos=ZBAA,ZSPD,ZGGG")
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)

var result map[string]interface{}
json.Unmarshal(body, &result)
for _, item := range result["data"].([]interface{}) {
    m := item.(map[string]interface{})
    fmt.Printf("%v: 平均延时 %vs(%v 样本)\n", m["icao"], m["avg_latency_seconds"], m["sample_count"])
}
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/rest/latency?icaos=ZBAA,ZSPD,ZGGG"))
    .GET().build();
HttpResponse<String> resp = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.body());
using var client = new HttpClient();
var json = await client.GetStringAsync("https://special.data-api.skyviewor.host/fast-metar/rest/latency?icaos=ZBAA,ZSPD,ZGGG");
using var doc = JsonDocument.Parse(json);
foreach (var item in doc.RootElement.GetProperty("data").EnumerateArray())
{
    Console.WriteLine($"{item.GetProperty("icao").GetString()}: 平均延时 {item.GetProperty("avg_latency_seconds").GetDouble()}s");
}
$ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/rest/latency?icaos=ZBAA,ZSPD,ZGGG");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
foreach ($result["data"] as $item) {
    echo "{$item["icao"]}: 平均延时 {$item["avg_latency_seconds"]}s({$item["sample_count"]} 样本)\n";
}

WebSocket 推送

机场快报支持实时推送,连接建立后无需轮询,新报文到达时自动下发。

鉴权方式

端点 说明 Token 鉴权 API Key 直传
wss://special.data-api.skyviewor.host/fast-metar/ws/raw 推送原始 METAR 报文 先换取 Token(见鉴权章节),再通过 URL Query ?token=ft-xxx 传入 WS 握手 Header Authorization: Bearer sk-xxx
wss://special.data-api.skyviewor.host/fast-metar/ws/parsed 推送结构化 METAR 同上 同上

浏览器 WebSocket API 不支持自定义 Header,仅可用 Token 鉴权。

订阅与取消

客户端发送 JSON 消息控制订阅范围:

// 订阅指定机场
{"action": "subscribe", "icaos": ["ZBAA", "ZGGG"]}

// 订阅全部机场
{"action": "subscribe", "icaos": ["*"]}

// 取消订阅
{"action": "unsubscribe", "icaos": ["ZBAA"]}

推送消息格式

{
  "type": "new_metar_arrived",
  "data": [
    {
      "icao": "ZBAA",
      "raw_metar": "METAR ZBAA 220230Z VRB02MPS CAVOK 27/17 Q1007 NOSIG=",
      "obs_time": "2026-06-22T10:30:00+08:00",
      "report_type": "METAR",
      "arrived_at": "2026-06-22T02:30:58+00:00"
    }
  ]
}

心跳与连接管理

// 心跳(每 5 分钟)
{"type": "ping"}

// 连接即将到期(24 小时到期前 5 分钟通知)
{"type": "server_notice", "message": "连接将在 300 秒后关闭", "remaining_seconds": 300}

客户端收到 ping 后可回复 {"action": "pong"} 维持连接。

代码示例

import asyncio, json, urllib.request
import websockets

API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"  # 更换为您的以 sk- 开头的 API Key 字符串

# 方式一:API Key 直传(通过 WS 握手 Header)
async def listen_direct():
    url = "wss://special.data-api.skyviewor.host/fast-metar/ws/parsed"
    async with websockets.connect(
        url,
        extra_headers={"Authorization": f"Bearer {API_KEY}"},
    ) as ws:
        await ws.send(json.dumps({"action": "subscribe", "icaos": ["ZBAA", "ZGGG"]}))
        async for raw in ws:
            msg = json.loads(raw)
            if msg["type"] == "new_metar_arrived":
                for item in msg["data"]:
                    t = item.get("parsed", {}).get("temperature")
                    print(f"{item['icao']}: {t}°C")
            elif msg["type"] == "ping":
                await ws.send(json.dumps({"action": "pong"}))

# 方式二:Token 鉴权(先换 Token,再通过 URL query param 连接)
def get_token():
    req = urllib.request.Request(
        "https://special.data-api.skyviewor.host/fast-metar/auth/token",
        method="POST",
        headers={"Authorization": f"Bearer {API_KEY}"},
    )
    with urllib.request.urlopen(req, timeout=30) as resp:
        return json.loads(resp.read().decode())["token"]

async def listen_with_token():
    TOKEN = get_token()
    url = f"wss://special.data-api.skyviewor.host/fast-metar/ws/parsed?token={TOKEN}"
    async with websockets.connect(url) as ws:
        await ws.send(json.dumps({"action": "subscribe", "icaos": ["ZBAA", "ZGGG"]}))
        async for raw in ws:
            msg = json.loads(raw)
            if msg["type"] == "new_metar_arrived":
                for item in msg["data"]:
                    t = item.get("parsed", {}).get("temperature")
                    print(f"{item['icao']}: {t}°C")
            elif msg["type"] == "ping":
                await ws.send(json.dumps({"action": "pong"}))

asyncio.run(listen_direct())  # 或 asyncio.run(listen_with_token())
// 浏览器端 WebSocket API 不支持自定义 Header,请使用 Token 鉴权。
// Node.js 服务端可用 ws 库实现 API Key 直传(见下方注释)。

const API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:Token 鉴权(推荐,兼容浏览器与服务端)
const tokenResp = await fetch("https://special.data-api.skyviewor.host/fast-metar/auth/token", {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { token } = await tokenResp.json();

const ws = new WebSocket(`wss://special.data-api.skyviewor.host/fast-metar/ws/parsed?token=${token}`);

ws.onopen = () => {
  ws.send(JSON.stringify({ action: "subscribe", icaos: ["ZBAA", "ZGGG"] }));
};

ws.onmessage = (event) => {
  const msg = JSON.parse(event.data);
  if (msg.type === "new_metar_arrived") {
    for (const item of msg.data) {
      const t = item.parsed?.temperature;
      console.log(`${item.icao}: ${t}°C`);
    }
  } else if (msg.type === "ping") {
    ws.send(JSON.stringify({ action: "pong" }));
  }
};

// 方式二:API Key 直传(仅 Node.js,通过 ws 库的 headers 选项)
// const WebSocket = require("ws");
// const ws2 = new WebSocket("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed", {
//   headers: { Authorization: `Bearer ${API_KEY}` },
// });
// 浏览器端 WebSocket API 不支持自定义 Header,请使用 Token 鉴权。
// Node.js 服务端可用 ws 库实现 API Key 直传(见下方注释)。

const API_KEY: string = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:Token 鉴权(推荐,兼容浏览器与服务端)
const tokenResp = await fetch("https://special.data-api.skyviewor.host/fast-metar/auth/token", {
  method: "POST",
  headers: { Authorization: `Bearer ${API_KEY}` },
});
const { token }: { token: string } = await tokenResp.json();

const ws = new WebSocket(`wss://special.data-api.skyviewor.host/fast-metar/ws/parsed?token=${token}`);

ws.onopen = () => {
  ws.send(JSON.stringify({ action: "subscribe", icaos: ["ZBAA", "ZGGG"] }));
};

ws.onmessage = (event: MessageEvent) => {
  const msg = JSON.parse(event.data);
  if (msg.type === "new_metar_arrived") {
    for (const item of msg.data) {
      const t: number | null = item.parsed?.temperature;
      console.log(`${item.icao}: ${t}°C`);
    }
  } else if (msg.type === "ping") {
    ws.send(JSON.stringify({ action: "pong" }));
  }
};

// 方式二:API Key 直传(仅 Node.js,通过 ws 库的 headers 选项)
// import WebSocket from "ws";
// const ws2 = new WebSocket("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed", {
//   headers: { Authorization: `Bearer ${API_KEY}` },
// });
apiKey := "sk-d5d0542bef7e42e2b8909cb7f42af5fb" // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直传(通过 WS 握手 Header)
dialer := websocket.DefaultDialer
reqHeader := http.Header{}
reqHeader.Set("Authorization", "Bearer "+apiKey)
conn, _, _ := dialer.Dial("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed", reqHeader)
defer conn.Close()

conn.WriteJSON(map[string]interface{}{
    "action": "subscribe", "icaos": []string{"ZBAA", "ZGGG"},
})

for {
    var msg map[string]interface{}
    conn.ReadJSON(&msg)
    if msg["type"] == "new_metar_arrived" {
        for _, item := range msg["data"].([]interface{}) {
            m := item.(map[string]interface{})
            fmt.Printf("%v: %v°C\n", m["icao"], m["parsed"].(map[string]interface{})["temperature"])
        }
    } else if msg["type"] == "ping" {
        conn.WriteJSON(map[string]interface{}{"action": "pong"})
    }
}

// 方式二:Token 鉴权
// 获取数据令牌
// tokenReq, _ := http.NewRequest("POST", "https://special.data-api.skyviewor.host/fast-metar/auth/token", nil)
// tokenReq.Header.Set("Authorization", "Bearer "+apiKey)
// tokenResp, _ := http.DefaultClient.Do(tokenReq)
// tokenBody, _ := io.ReadAll(tokenResp.Body)
// tokenResp.Body.Close()
// var tokenData map[string]interface{}
// json.Unmarshal(tokenBody, &tokenData)
// token := tokenData["token"].(string)
//
// // 连接 WebSocket
// u, _ := url.Parse("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed?token=" + token)
// conn, _, _ := websocket.DefaultDialer.Dial(u.String(), nil)
// defer conn.Close()
// // ... 后续逻辑同上
String API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直传(通过 WS 握手 Header)
HttpClient client = HttpClient.newHttpClient();
WebSocket ws = client.newWebSocketBuilder()
    .header("Authorization", "Bearer " + API_KEY)
    .buildAsync(URI.create("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed"),
        new WebSocket.Listener() {
            public void onOpen(WebSocket webSocket) {
                webSocket.sendText("{\"action\":\"subscribe\",\"icaos\":[\"ZBAA\",\"ZGGG\"]}", true);
                WebSocket.Listener.super.onOpen(webSocket);
            }
            public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
                return WebSocket.Listener.super.onText(webSocket, data, last);
            }
        }).join();

// 方式二:Token 鉴权
// HttpRequest tokenReq = HttpRequest.newBuilder()
//     .uri(URI.create("https://special.data-api.skyviewor.host/fast-metar/auth/token"))
//     .header("Authorization", "Bearer " + API_KEY)
//     .POST(HttpRequest.BodyPublishers.noBody())
//     .build();
// HttpResponse<String> tokenResp = HttpClient.newHttpClient().send(tokenReq, HttpResponse.BodyHandlers.ofString());
// String token = com.google.gson.JsonParser.parseString(tokenResp.body())
//     .getAsJsonObject().get("token").getAsString();
//
// WebSocket ws = client.newWebSocketBuilder()
//     .buildAsync(URI.create("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed?token=" + token),
//         new WebSocket.Listener() { ... }).join();
var apiKey = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直传(通过 WS 握手 Header)
using var ws = new ClientWebSocket();
ws.Options.SetRequestHeader("Authorization", $"Bearer {apiKey}");
await ws.ConnectAsync(new Uri("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed"), CancellationToken.None);
await ws.SendAsync(Encoding.UTF8.GetBytes("{\"action\":\"subscribe\",\"icaos\":[\"ZBAA\",\"ZGGG\"]}"),
    WebSocketMessageType.Text, true, CancellationToken.None);

var buffer = new byte[4096];
while (ws.State == WebSocketState.Open)
{
    var result = await ws.ReceiveAsync(buffer, CancellationToken.None);
    var text = Encoding.UTF8.GetString(buffer, 0, result.Count);
    Console.WriteLine(text);
}

// 方式二:Token 鉴权
// using var client = new HttpClient();
// client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
// var tokenJson = await client.PostAsync("https://special.data-api.skyviewor.host/fast-metar/auth/token", null);
// using var doc = JsonDocument.Parse(await tokenJson.Content.ReadAsStringAsync());
// var token = doc.RootElement.GetProperty("token").GetString();
//
// using var ws = new ClientWebSocket();
// await ws.ConnectAsync(new Uri($"wss://special.data-api.skyviewor.host/fast-metar/ws/parsed?token={token}"), CancellationToken.None);
// // ... 后续逻辑同上
$API_KEY = "sk-d5d0542bef7e42e2b8909cb7f42af5fb"; // 更换为您的以 sk- 开头的 API Key 字符串

// 方式一:API Key 直传(通过 WS 握手 Header,使用 textalk/websocket)
// composer require textalk/websocket
$client = new WebSocket\Client("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed", [
    "headers" => ["Authorization" => "Bearer {$API_KEY}"],
]);
$client->text(json_encode(["action" => "subscribe", "icaos" => ["ZBAA", "ZGGG"]]));
while (true) {
    $msg = json_decode($client->receive(), true);
    if ($msg["type"] === "new_metar_arrived") {
        foreach ($msg["data"] as $item) {
            $t = $item["parsed"]["temperature"] ?? null;
            echo "{$item["icao"]}: {$t}°C\n";
        }
    } elseif ($msg["type"] === "ping") {
        $client->text(json_encode(["action" => "pong"]));
    }
}

// 方式二:Token 鉴权
// $ch = curl_init("https://special.data-api.skyviewor.host/fast-metar/auth/token");
// curl_setopt($ch, CURLOPT_HTTPHEADER, ["Authorization: Bearer {$API_KEY}"]);
// curl_setopt($ch, CURLOPT_POST, true);
// curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// $tokenData = json_decode(curl_exec($ch), true);
// curl_close($ch);
// $token = $tokenData["token"];
//
// $client = new WebSocket\Client("wss://special.data-api.skyviewor.host/fast-metar/ws/parsed?token={$token}");
// // ... 后续逻辑同上

连接限制

项目 限制
单连接最长时长 24 小时
每个应用同时连接数 3
连接数超限关闭码 4009
认证失败关闭码 4001

当连接数已满时,尝试建立新连接会被服务端立即关闭,关闭码为 4009。客户端应根据此关闭码判断是否需要等待已有连接释放后重试。


配额与限流

项目 限制
HTTP QPS(每个应用) 2
WebSocket 同时连接数(每个应用) 3
数据令牌有效期 5 分钟
延时接口 IP 限流 QPS=2