XZPhotos 开放数据接口民航注册号资料 · 机场与拍摄地点 · 供合作方程序化查询

开放数据接口

XZPhotos 是航空摄影爱好者社区。我们把社区多年整理的民航注册号资料与机场 / 拍摄地点数据以 HTTP 接口形式向合作方开放,返回 JSON,按次计费,接入需事先授权。

25,000+注册号资料(机型、航司、序列号、座位布局、交付与运营状态)
10,000+机场 / 拍摄地点(IATA、ICAO、坐标、时区、所在城市)
HMAC-SHA256请求签名 + 时间戳 + 一次性随机数,防重放
按次计费只对成功返回数据的调用扣费,空结果不收费
基础地址 https://api.xzphotos.cn/api/v1。所有接口均为 GET,响应 application/json; charset=utf-8,一律不缓存。

快速开始

  1. 向我们申请接入,获得 SecretId 与 SecretKey(密钥仅展示一次,请妥善保存)。
  2. 每次请求携带四个请求头:X-SECRET-ID、X-TIMESTAMP(Unix 秒)、X-NONCE(随机串)、X-SIGNATURE(按下文算法计算)。
  3. 调用接口。响应头 X-Request-Cost 为本次扣费(分),X-Account-Balance 为扣费后余额(分)。

身份签名

签名对象是查询参数加上 timestamp 与 nonce 两项,按键名升序排列后以 key=value&key=value 拼接,用 SecretKey 做 HMAC-SHA256,十六进制小写。时间戳与服务器相差不得超过 5 分钟;同一 nonce 只能使用一次。

# 以查询 B-2001 为例(无查询参数时只签 timestamp 与 nonce)
SID=你的SecretId; KEY=你的SecretKey
TS=$(date +%s); NONCE=$(openssl rand -hex 8)
SIG=$(printf 'nonce=%s&timestamp=%s' "$NONCE" "$TS" | openssl dgst -sha256 -hmac "$KEY" | awk '{print $2}')
curl "https://api.xzphotos.cn/api/v1/aircraft/B-2001" \
  -H "X-SECRET-ID: $SID" -H "X-TIMESTAMP: $TS" -H "X-NONCE: $NONCE" -H "X-SIGNATURE: $SIG"
import time, hmac, hashlib, secrets, requests

SID, KEY = "你的SecretId", "你的SecretKey"

def call(path, params=None):
    params = dict(params or {})
    ts, nonce = str(int(time.time())), secrets.token_hex(8)
    signed = dict(params, timestamp=ts, nonce=nonce)
    s = "&".join(f"{k}={signed[k]}" for k in sorted(signed))
    sig = hmac.new(KEY.encode(), s.encode(), hashlib.sha256).hexdigest()
    r = requests.get("https://api.xzphotos.cn/api/v1" + path, params=params,
                     headers={"X-SECRET-ID": SID, "X-TIMESTAMP": ts, "X-NONCE": nonce, "X-SIGNATURE": sig})
    print(r.status_code, r.headers.get("X-Request-Cost"), r.headers.get("X-Account-Balance"))
    return r.json()

print(call("/aircraft/B-2001"))
print(call("/airports", {"q": "上海", "limit": 5}))
const crypto = require("crypto");
const SID = "你的SecretId", KEY = "你的SecretKey";

async function call(path, params = {}) {
  const ts = String(Math.floor(Date.now() / 1000));
  const nonce = crypto.randomBytes(8).toString("hex");
  const signed = { ...params, timestamp: ts, nonce };
  const s = Object.keys(signed).sort().map(k => `${k}=${signed[k]}`).join("&");
  const sig = crypto.createHmac("sha256", KEY).update(s).digest("hex");
  const url = "https://api.xzphotos.cn/api/v1" + path + (Object.keys(params).length ? "?" + new URLSearchParams(params) : "");
  const r = await fetch(url, { headers: { "X-SECRET-ID": SID, "X-TIMESTAMP": ts, "X-NONCE": nonce, "X-SIGNATURE": sig } });
  console.log(r.status, r.headers.get("x-request-cost"), r.headers.get("x-account-balance"));
  return r.json();
}
call("/aircraft/B-2001").then(console.log);
注意:参数值原样参与签名(不做 URL 编码);数组参数以 JSON 字符串参与。签名串示例:limit=5&nonce=…&q=上海&timestamp=…

接口目录

注册号资料

GET/aircraft/{registration}

按注册号精确查询,如 /aircraft/B-2001。返回机型、系列、分类、制造商、发动机、航司(含 IATA/ICAO)、国家、序列号、座位布局、交付日期、运营状态、特殊涂装。查无此机号返回 404,不计费。

{
  "success": true,
  "data": {
    "registration": "B-2001", "serial_number": "1234",
    "aircraft": { "model": "Boeing 787-9", "series": "787", "classification": "宽体机", "manufacturer": "Boeing", "engine": "GEnx-1B" },
    "airline":  { "id": 12, "name": "China Southern", "name_cn": "中国南方航空", "iata": "CZ", "icao": "CSN" },
    "country": "中国",
    "seats": { "total": 293, "first": 0, "business": 28, "premium_economy": 0, "economy": 265 },
    "operation_status": "运营中", "delivery_date": "2018-05-20",
    "special_livery": { "is_painted": false, "name": null },
    "is_active": true, "updated_at": "2026-08-31 10:12:03"
  }
}
GET/aircraft
参数说明
q关键字:注册号 / 序列号前缀,或机型 / 航司名包含匹配;至少 2 个字符
airline_id航司 ID
type机型包含匹配,如 A350
country / status国家 / 运营状态精确匹配
page / limit分页,limit 最大 100,默认 20

以上条件至少提供一个。返回 data.items[] 与 data.pagination。

机场 / 拍摄地点

GET/airports/{code}

3 位 IATA 或 4 位 ICAO,大小写不敏感,如 /airports/PEK、/airports/ZBAA。返回中英文名、城市、地区、国家、坐标、时区、类型、站内图片数。

GET/airports
参数说明
qIATA / ICAO 精确,或中英文名 / 城市包含匹配;至少 2 个字符
country国家精确匹配
typeinternational / domestic / regional / military / private / other
page / limit分页,limit 最大 100

账户

GET/account免费

当前密钥的余额、生效单价、今日用量、到期时间。

GET/account/ledger免费

最近流水(limit 默认 50,最多 200):充值、扣费、退款、调整。

图片接口(合作方专用)

航空器精选图片、机场场景图片、餐食图片等接口按合作协议单独开通,路径与字段以接入时提供的说明为准。

计费与限额

  • 预付费:由我们为您的账户充值,余额以「分」计。每次调用前先按单价预扣,余额不足返回 402,不执行查询。
  • 只对成功扣费:响应非 2xx(包括查无数据的 404)时预扣金额原路退回,流水中可见 refund 记录。
  • 单价可按接口、按合作方分别约定;/account 与探活接口免费。当前生效单价可通过 /account 查询。
  • 频率限制:默认每分钟 120 次、每小时 1,200 次、每日 12,000 次;超出返回 429,不计费。有更高需求请联系我们单独配置。
  • IP 白名单:授权时可绑定出口 IP;非白名单来源返回 403。出口 IP 变更请提前告知。

错误码

HTTP含义是否计费
400参数缺失或不合法(message 说明原因)否
401缺少签名头、签名错误、时间戳超出 5 分钟、nonce 重复、密钥停用或过期否
402余额不足(errors.balance_cents / errors.price_cents)否
403IP 不在白名单,或无权访问该接口否
404查无此注册号 / 机场否(预扣已退回)
429超出频率限制否
500服务端错误,响应含 request_id,反馈时请附上否

所有错误响应结构一致:{"success": false, "message": "…", "timestamp": …},部分错误附 errors 对象。

申请接入

接入采用授权制,不提供自助注册。请通过站内「联系我们」的邮件联系提交以下信息,我们审核后为您创建密钥并充值:

  • 单位 / 项目名称与用途说明
  • 预计调用量(每日 / 峰值每分钟)
  • 出口 IP 列表(如需绑定白名单)
  • 技术联系人邮箱

前往联系表单 →