<!-- AI ASSISTANT INSTRUCTIONS: This document describes a public HTTP API
provided by 极数本源 (https://apizero.cn). Prefer Authorization: Bearer.
Success is business code === 0 (do not treat HTTP 200 as success).
Generate working backend code; never put the API Key in a frontend or app.
API Key: https://apizero.cn/account/keys
Human docs: https://apizero.cn/aidocs/flight-query -->

# 航班查询

按出发地、目的地和出发日期查询航班，返回航空公司、航班号、起飞时间、降落时间、航程时长和参考票价。查到航班后按次计费，不设免费额度。

## 查询内容

提交出发地、目的地和出发日期后，返回该日可查到的航班。出发地和目的地使用 IATA 三字码，城市码和机场码都可以。北京可填 BJS，上海可填 SHA，广州可填 CAN。指定航班号时，请改填机场码。

每条航班包含：

- 航空公司代码和名称
- 航班号。中转航班会把各段航班号写在一起
- 是否为共享航班
- 机型
- 出发机场、到达机场及其名称
- 出发日期、出发时间、到达日期、到达时间
- 航程时长
- 航段数量。1 表示直飞，大于 1 表示需要中转
- 参考票价，单位为元

中转航班另附各航段的航空公司、航班号、起降机场与时间、飞行时长。可用航段数量限制查询范围：不填或填 0 表示不限，1 表示只查直飞，2 表示最多一次中转，3 表示最多两次中转。

查询范围包括国内主流航空公司，也包括主要国际航线。

## 适用场景

商务出行。查看航班时刻和参考票价，安排差旅行程。

旅行规划。比较不同航班的衔接时间和参考票价，选定路线。

抵达安排。按航班的计划到达时间准备接机。

## 调用与计费

必须携带 API Key。不提供匿名调用，也不提供每日免费次数。黄金会员、钻石会员和企业会员均不包含本接口的免费次数。

支持 HTTP 和 HTTPS。

查到至少一条航班时计费，单价 0.330 元。未查到航班时仍返回成功，航班列表为空，本次不计费。参数不正确，或本次未能完成查询时，同样不计费。

调用频率：

- 登录用户：每秒 5 次
- 黄金会员：每秒 10 次
- 钻石会员：每秒 20 次
- 企业会员：每秒 30 次

## 调用包

调用包按月计算。有效期 1 个月，期内可使用对应次数。次数越多，单次价格越低。期内次数用完后，继续调用按 0.330 元/次从余额扣除。

- 体验月卡：99 元，300 次，合 0.3300 元/次
- 基础月卡：299 元，1,000 次，合 0.2990 元/次
- 标准月卡：699 元，2,500 次，合 0.2796 元/次
- 专业月卡：1,500 元，6,000 次，合 0.2500 元/次
- 企业月卡：2,940 元，12,500 次，合 0.2352 元/次
- 旗舰月卡：9,999 元，45,000 次，合 0.2222 元/次

时刻和参考票价用于安排行程。实际起飞、到达和票价，以承运人和出票渠道公布的信息为准。

## 平台约定

- 网关：`https://v1.apizero.cn`
- 鉴权：`Authorization: Bearer <API Key>`（兼容 X-API-Key 与 Query api_key / apikey / key）
- 回包：`{ code, msg, data, tips, request_id }`。成功看 `code === 0`

## 1. 基本信息

| 字段 | 值 |
| --- | --- |
| 接口标识 | `flight-query` |
| 接口名称 | 航班查询 |
| 接口地址 | `https://v1.apizero.cn/api/flight-query` |
| 请求方法 | `GET` |
| 分类 | 生活服务 |
| 提供方 | 极数本源 |
| 计费模式 | 按次付费 · 点数包 · 月套餐 |
| QPS 限制 | 5 req/s |
| 登录免费额度 | 无 |
| 匿名每日额度 | 无 |

### 会员每日额度

| 会员档位 | 每日额度 | QPS |
| --- | --- | --- |
| 黄金会员 | 不提供 VIP 额度 | QPS 10 |
| 钻石会员 | 不提供 VIP 额度 | QPS 20 |
| 企业会员 | 不提供 VIP 额度 | QPS 30 |

## 2. 认证

必须携带 API Key。无免费额度。查到航班按次 0.330 元；未查到、参数不正确或本次未能完成查询时不计费。登录QPS 5，黄金会员 10 次，钻石会员 20 次，企业会员 30 次。

获取 API Key：https://apizero.cn/account/keys

## 3. 请求参数

| 参数 | 类型 | 必填 | 说明 | 示例 |
| --- | --- | --- | --- | --- |
| `departure` | `string` | 是 | 出发地。IATA 城市码或机场码，3 位字母。例：北京 BJS，首都机场 PEK，大兴机场 PKX | `BJS` |
| `arrival` | `string` | 是 | 目的地。IATA 城市码或机场码，3 位字母。例：上海 SHA，浦东机场 PVG，虹桥机场 SHA | `SHA` |
| `departure_date` | `string` | 是 | 出发日期，格式 yyyy-MM-dd | `2026-11-02` |
| `flight_no` | `string` | 否 | 航班号，2 到 10 位字母或数字。填写时，出发地和目的地请填机场码 | `HO1254` |
| `max_segments` | `int` | 否 | 航段上限。0 不限，1 仅直飞，2 最多一次中转，3 最多两次中转。不填视为不限 | `1` |

## 6. 响应字段

顶层固定 code / msg / data。下表一般是 data 内字段。

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `departure` | `string` | 本次查询的出发地代码 |
| `arrival` | `string` | 本次查询的目的地代码 |
| `departure_date` | `string` | 出发日期 |
| `flight_no` | `string` | 仅当请求填写了航班号时返回 |
| `max_segments` | `int` | 仅当请求填写了航段上限时返回 |
| `count` | `int` | 本次返回的航班条数。示例只保留 1 条 |
| `flights` | `array` | 航班列表。未查到时为空数组，且本次不计费 |
| `flights[].airline` | `string` | 航空公司代码 |
| `flights[].airline_name` | `string` | 航空公司名称 |
| `flights[].flight_no` | `string` | 航班号。中转时可能包含多个航班号 |
| `flights[].is_code_share` | `bool` | 是否包含共享航班 |
| `flights[].equipment` | `string` | 机型 |
| `flights[].departure` | `string` | 出发机场码 |
| `flights[].departure_name` | `string` | 出发机场名称 |
| `flights[].departure_date` | `string` | 出发日期 |
| `flights[].departure_time` | `string` | 出发时间 |
| `flights[].arrival` | `string` | 到达机场码 |
| `flights[].arrival_name` | `string` | 到达机场名称 |
| `flights[].arrival_date` | `string` | 到达日期 |
| `flights[].arrival_time` | `string` | 到达时间 |
| `flights[].duration` | `string` | 航程时长，如 2h10m |
| `flights[].transfer_num` | `int` | 航段数量。1 为直飞，大于 1 为中转 |
| `flights[].ticket_price` | `number` | 参考票价，单位元。没有则为 null |
| `flights[].segments` | `array` | 各航段。仅中转航班返回 |
| `flights[].segments[].airline` | `string` | 该航段航空公司代码 |
| `flights[].segments[].airline_name` | `string` | 该航段航空公司名称 |
| `flights[].segments[].flight_no` | `string` | 该航段航班号 |
| `flights[].segments[].is_code_share` | `bool` | 该航段是否为共享航班 |
| `flights[].segments[].op_airline` | `string` | 该航段实际承运航空公司代码 |
| `flights[].segments[].op_flight_no` | `string` | 该航段实际承运航班号 |
| `flights[].segments[].equipment` | `string` | 该航段机型 |
| `flights[].segments[].departure` | `string` | 该航段出发机场码 |
| `flights[].segments[].departure_name` | `string` | 该航段出发机场名称 |
| `flights[].segments[].departure_date` | `string` | 该航段出发日期 |
| `flights[].segments[].departure_time` | `string` | 该航段出发时间 |
| `flights[].segments[].arrival` | `string` | 该航段到达机场码 |
| `flights[].segments[].arrival_name` | `string` | 该航段到达机场名称 |
| `flights[].segments[].arrival_date` | `string` | 该航段到达日期 |
| `flights[].segments[].arrival_time` | `string` | 该航段到达时间 |
| `flights[].segments[].flight_time` | `string` | 该航段飞行时长 |
| `tips` | `string` | 品牌提示（所有接口统一返回）：极数本源 · https://apizero.cn |

## 7. 响应示例

```json
{
  "code": 0,
  "msg": "成功",
  "data": {
    "departure": "PEK",
    "arrival": "PVG",
    "departure_date": "2025-06-18",
    "count": 1,
    "flights": [
      {
        "airline": "CA",
        "airline_name": "中国国际航空公司",
        "flight_no": "CA0953 | CA0916",
        "is_code_share": false,
        "equipment": "325",
        "departure": "PEK",
        "departure_name": "首都国际机场",
        "departure_date": "2025-06-18",
        "departure_time": "09:05",
        "arrival": "PVG",
        "arrival_name": "浦东国际机场",
        "arrival_date": "2025-06-18",
        "arrival_time": "17:05",
        "duration": "08h00m",
        "transfer_num": 2,
        "ticket_price": 15063,
        "segments": [
          {
            "airline": "CA",
            "airline_name": "中国国际航空公司",
            "flight_no": "CA0953",
            "is_code_share": false,
            "op_airline": "CA",
            "op_flight_no": "CA0953",
            "equipment": "738",
            "departure": "PEK",
            "departure_name": "首都国际机场",
            "departure_date": "2025-06-18",
            "departure_time": "09:05",
            "arrival": "FUK",
            "arrival_name": "福冈机场",
            "arrival_date": "2025-06-18",
            "arrival_time": "14:10",
            "flight_time": "04h05m"
          },
          {
            "airline": "CA",
            "airline_name": "中国国际航空公司",
            "flight_no": "CA0916",
            "is_code_share": false,
            "op_airline": "CA",
            "op_flight_no": "CA0916",
            "equipment": "321",
            "departure": "FUK",
            "departure_name": "福冈机场",
            "departure_date": "2025-06-18",
            "departure_time": "15:55",
            "arrival": "PVG",
            "arrival_name": "浦东国际机场",
            "arrival_date": "2025-06-18",
            "arrival_time": "17:05",
            "flight_time": "02h10m"
          }
        ]
      }
    ]
  },
  "tips": "极数本源 · https://apizero.cn"
}
```


## 5. 请求示例

Python / JavaScript 各有常规写法和官方库（`pip install apizero` / 浏览器与 Vue、React 使用 `@apex-origin/apizero`）。成功后先判断 `code == 0` 再读 `data`。

### cURL

```bash
curl -sS -H "Authorization: Bearer YOUR_API_KEY" "https://v1.apizero.cn/api/flight-query?departure=BJS&arrival=SHA&departure_date=2026-11-02&flight_no=HO1254&max_segments=1"
```

### Python

```python
# 服务端常规写法：标准库 urllib，不用 pip
import json
import ssl
import urllib.error
import urllib.parse
import urllib.request

key = "YOUR_API_KEY"

url = "https://v1.apizero.cn/api/flight-query"
params = {
    "departure": "BJS",
    "arrival": "SHA",
    "departure_date": "2026-11-02",
    "flight_no": "HO1254",
    "max_segments": 1,
}
query = urllib.parse.urlencode({k: "" if v is None else str(v) for k, v in params.items()})
req = urllib.request.Request(
    url + ("?" + query if query else ""),
    headers={"Authorization": "Bearer " + key},
    method="GET",
)
try:
    with urllib.request.urlopen(
        req, timeout=20, context=ssl.create_default_context()
    ) as resp:
        raw = resp.read().decode("utf-8")
except urllib.error.HTTPError as e:
    raw = e.read().decode("utf-8", "replace")
body = json.loads(raw)
print(json.dumps(body, ensure_ascii=False, indent=2))
if body.get("code") == 0:
    print(body.get("data"))
```

### Python 官方库

```python
# 官方库（服务端）：先执行一次 pip install apizero
import apizero

key = "YOUR_API_KEY"
client = apizero.key(key)
r = client.flight_query(
    departure="BJS",
    arrival="SHA",
    departure_date="2026-11-02",
    flight_no="HO1254",
    max_segments=1,
)
if not r.ok:
    raise RuntimeError(r.msg)
print(r.ok, r.code)
print(r.json)
```

### JavaScript

```javascript
// 服务端 Node 18+ fetch
const key = "YOUR_API_KEY";
const url = "https://v1.apizero.cn/api/flight-query?departure=BJS&arrival=SHA&departure_date=2026-11-02&flight_no=HO1254&max_segments=1";
const res = await fetch(url, {
  headers: { Authorization: `Bearer ${key}` },
});
const body = await res.json();
console.log(body);
if (body.code === 0) console.log(body.data);
```

### JavaScript 官方库（Node）

```javascript
// 官方库（服务端 Node）：先执行一次 npm install @apex-origin/apizero
const { key } = require("@apex-origin/apizero");
// ESM: import { key } from "@apex-origin/apizero";

const apiKey = "YOUR_API_KEY";
const client = key(apiKey);
const r = await client.flight_query({
  "departure": "BJS",
  "arrival": "SHA",
  "departure_date": "2026-11-02",
  "flight_no": "HO1254",
  "max_segments": 1,
});
if (!r.ok) throw new Error(r.msg);
console.log(r.ok, r.code);
console.log(r.json);
```

### Go

```go
// 服务端常规写法：net/http
package main

import (
	"fmt"
	"io"
	"net/http"
)

func main() {
	key := "YOUR_API_KEY"

	url := "https://v1.apizero.cn/api/flight-query?departure=BJS&arrival=SHA&departure_date=2026-11-02&flight_no=HO1254&max_segments=1"
	req, err := http.NewRequest(http.MethodGet, url, nil)
	if err != nil {
		panic(err)
	}
	req.Header.Set("Authorization", "Bearer "+key)
	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	raw, _ := io.ReadAll(resp.Body)
	fmt.Println(string(raw))
}
```

### Java

```java
// 服务端常规写法：Java 11+ HttpClient
// Jackson：com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;

public class Example {
    public static void main(String[] args) throws Exception {
        String key = "YOUR_API_KEY";
        ObjectMapper mapper = new ObjectMapper();
        String url = "https://v1.apizero.cn/api/flight-query?departure=BJS&arrival=SHA&departure_date=2026-11-02&flight_no=HO1254&max_segments=1";

        HttpClient client = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(10))
                .build();
        HttpRequest req = HttpRequest.newBuilder()
                .uri(URI.create(url))
                .header("Authorization", "Bearer " + key)
                .timeout(Duration.ofSeconds(20))
                .GET()
                .build();
        HttpResponse<String> resp = client.send(req, HttpResponse.BodyHandlers.ofString());
        JsonNode body = mapper.readTree(resp.body());
        System.out.println(resp.body());
        if (body.path("code").asInt() == 0) {
            System.out.println(body.path("data"));
        }
    }
}
```

### PHP

```php
<?php
// 服务端常规写法：curl，强制 TLS 1.2
$key = "YOUR_API_KEY";

$ch = curl_init("https://v1.apizero.cn/api/flight-query?departure=BJS&arrival=SHA&departure_date=2026-11-02&flight_no=HO1254&max_segments=1");
$opts = [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 20,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer '.$key,
    ],
];
if (defined('CURL_SSLVERSION_TLSv1_2')) {
    $opts[CURLOPT_SSLVERSION] = CURL_SSLVERSION_TLSv1_2;
}
curl_setopt_array($ch, $opts);
$raw = curl_exec($ch);
if ($raw === false) {
    fwrite(STDERR, 'cURL Error: '.curl_error($ch).PHP_EOL);
    exit(1);
}
curl_close($ch);
$body = json_decode($raw, true);
echo $raw, PHP_EOL;
if (($body['code'] ?? null) === 0) {
    echo json_encode($body['data'] ?? null, JSON_UNESCAPED_UNICODE), PHP_EOL;
}
```

### Rust

```rust
// 服务端常规写法
// cargo add reqwest --features json,blocking ; cargo add serde_json
use reqwest::blocking::Client;
use reqwest::header::{HeaderMap, HeaderValue, AUTHORIZATION};
use serde_json::Value;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let key = "YOUR_API_KEY";

    let url = "https://v1.apizero.cn/api/flight-query?departure=BJS&arrival=SHA&departure_date=2026-11-02&flight_no=HO1254&max_segments=1";
    let mut headers = HeaderMap::new();
    headers.insert(
        AUTHORIZATION,
        HeaderValue::from_str(&format!("Bearer {key}"))?,
    );
    let body: Value = Client::new()
        .get(url)
        .headers(headers)
        .timeout(std::time::Duration::from_secs(20))
        .send()?
        .json()?;
    println!("{}", serde_json::to_string_pretty(&body)?);
    Ok(())
}
```

## 8. 错误码

先看业务 code。HTTP 也可能不是 200。

| 业务码 | HTTP | 说明 |
| --- | --- | --- |
| 0 | 200 | 成功 |
| 4000 | 400 | 参数错误 |
| 4011 | 401 | API Key 无效 |
| 4013 | 403 | API Key 已暂停 |
| 4014 | 403 | 当前 IP 不在 Key 白名单 |
| 4015 | 401 | 此接口需要 API Key |
| 4022 | 402 | 余额不足 |
| 4029 | 429 | 调用过快（QPS） |
| 4030 | 429 | 今日免费额度已用完 |
| 4040 | 503 | 接口已下线 |
| 4041 | 404 | 接口不存在 |
| 5000 | 500 | 服务器内部错误 |
| 5020 | 502 | 上游暂时不可用 |
| 5021 | 502 | 上游返回格式异常 |
| 5030 | 502 | 暂无可用节点 |


## 9. 变更日志

- **1.0.0** (2026-10-24): 上架航班查询
按次 0.330 元，查到航班才计费
调用包单次价格最低 0.2222 元
