机场快报
机场快报为专线接口产品,提供中国境内 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 在网络传输中的泄露风险。流程如下:
- 用 API Key 换取临时数据令牌(有效期 5 分钟)
- 用令牌调用数据接口或建立 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 |