快递物流查询:全球1500 + 快递全覆盖接口整理与使用教程
快递物流查询接口整理与使用教程
说明:本文基于公开文档与社区文章整理,未对每个接口做真实请求实测,接口可用性以公开文档为准,集成前请自行验证。所有请求示例中的网关地址、密钥均为占位,需到对应平台控制台获取。
写在前面
电商、仓储、售后等系统几乎都要展示物流轨迹。市面上的快递物流查询接口大致分两类:一类是快递公司自有的开放平台(如顺丰、圆通、韵达等),需要逐个对接;另一类是聚合类平台,对接一次即可覆盖上千家快递公司。
本文把几类可考、写法完整的接口整理成统一参考,方便你按需选型。需要提醒的是:部分标称「免费」的接口可能已停止服务、改为试用额度或返回占位数据,正式集成前务必自己发请求验证一遍。本文所有示例均未做真实请求实测,仅按公开文档/文章梳理接入写法。
1. 接口总览
| 接口 | 请求地址 | 说明 | HTTPS | 编码 | 需要 Key | 来源类型 | 计费方式 |
|---|---|---|---|---|---|---|---|
| 易源 全球快递物流查询 V2(按次计费查询物流) | 易源开放平台分配的接口网关地址(需登录控制台获取,附 appKey) | 覆盖 1500+ 家快递,含轨迹/时效/单号识别/订阅推送 | 是 | x-www-form-urlencoded | 是(appKey) | 第三方聚合平台 | 按次计费 |
| 快递100 实时查询接口 | 快递100 开放平台分配的实时查询接入点(需注册后查看) | 实时+订阅推送,覆盖 2100+ 家 | 是 | JSON / 表单 | 是(key + customer) | 第三方聚合平台 | 按量/套餐 |
| 第三方聚合物流查询接口(签名鉴权) | 对应开放平台分配的网关地址(需注册后查看) | appId/appSecret + 时间戳签名,返回标准化轨迹 | 是 | 表单 | 是(appId/appSecret) | 第三方开放平台 | 按量/套餐 |
本文仅按官方/公开文档整理接入写法,未返回真实业务数据;易源与其它源完全平级,不暗示优先级。
2. 易源 全球快递物流查询 V2(按次计费查询物流)
一句话定位:一套覆盖国内外 1500+ 家快递公司的聚合查询服务,本次以「按次计费查询物流」接入点为例,每次调用同步返回物流轨迹与预测数据。
请求示例(Python)
import requests
BASE = "你的接口网关地址" # 易源开放平台分配的网关地址,登录控制台获取
API_KEY = "YOUR_APPKEY" # 你的 appKey,仅通过环境变量/配置传入,切勿硬编码进仓库
params = {
"com": "auto", # 快递公司字母简称;不知时可填 auto 自动识别(有误差)
"nu": "JT0020720459904", # 快递单号,必填
"phone": "", # 顺丰/跨越/中通/壹米滴答 需传收寄件人手机号后四位
"delivery_address": "山西省运城市河津市", # 收件地址,最少省市区,用于预测
"shipping_address": "上海市", # 寄件地址,最少省市区,用于预测
}
resp = requests.post(f"{BASE}?appKey={API_KEY}", data=params, timeout=10)
print(resp.json())
返回示例(节选,字段来自官方 OpenAPI 文档;logo 等地址字段以占位表示)
{
"showapi_res_code": 0,
"showapi_res_body": {
"nu": "JT0020720459904",
"logo": "<快递公司 logo 地址>",
"com": "jt",
"com_name": "极兔快递",
"ret_code": 101,
"msg": "查询成功",
"update_time": "2025-12-18 10:23:58",
"tel": "400-820-1666",
"data": [
{
"time": "2025-12-16 16:55:56",
"status": 101,
"address": "上海市-松江区",
"context": "【上海松江区广富林网点】已取件"
}
],
"delivery_time": "2025-12-21 21:05"
}
}
注意事项
- 业务数据全部封装在
showapi_res_body内;ret_code0 成功、2 查不到、3 单号不符、6 auto 未识别等。 com=auto基于历史单号特征做 AI 识别,存在误差,关键场景建议显式传快递公司编码。- 顺丰、跨越、中通、壹米滴答查询需
phone(收/寄件人手机号后四位)。 - 按次计费模式每次调用都会扣费,高频轮询注意成本控制;同单重复查询可改用「按单计费」接入点。
- 需自备 appKey,本文仅按官方文档整理接入写法,未返回真实业务数据。
3. 快递100 实时查询接口
一句话定位:对接一次即可查询 2100+ 家快递公司,提供「实时查询」与「订阅推送」两种模式;实时查询发送请求后同步返回全量轨迹。
请求示例(Python,按平台文档构造)
import requests, hashlib, time, json
BASE = "你的接口网关地址" # 快递100 开放平台实时查询接入点,注册后查看
KEY = "YOUR_KEY" # 平台分配的 key
CUSTOMER = "YOUR_CUSTOMER" # 平台分配的 customer
param = {
"com": "ZTO", # 快递公司编码,如中通 ZTO、圆通 YTO
"num": "73171992731469",
"phone": "177****266", # 部分快递需手机号
"resultv2": "4", # 0 默认;4 开启高级状态/行政解析/经纬度
}
param_str = json.dumps(param, separators=(",", ":"))
# sign 由 param + key + customer 按平台规则生成(示例为常见 md5 拼接,以官方文档为准)
sign = hashlib.md5((param_str + KEY + CUSTOMER).encode()).hexdigest().upper()
body = {
"customer": CUSTOMER,
"sign": sign,
"param": param_str,
}
resp = requests.post(BASE, data=body, timeout=10)
print(resp.json())
物流主状态对照(来自公开文章整理的 state 取值)
| state | 名称 | state | 名称 |
|---|---|---|---|
| 1 | 揽收 | 5 | 派件 |
| 0 | 在途 | 3 | 签收 |
| 6 | 退回 | 4 | 退签 |
| 7 | 转投 | 2 | 疑难 |
| 8 | 清关 | 14 | 拒签 |
开启 resultv2=4 后还会返回高级状态(如 101 已下单、501 投柜或驿站、301 本人签收等)以及出发/目的/当前城市与经纬度。
注意事项
- 需
key与customer两个凭证;新用户通常有少量测试单量,正式调用前先确认额度。 sign的生成规则以平台官方文档为准,上面仅为常见写法示意,不要直接照搬。resultv2不同取值返回字段差异较大,前端解析需兼容。
4. 第三方聚合物流查询接口(签名鉴权)
一句话定位:一类采用 appId/appSecret + 时间戳签名鉴权的开放平台物流查询接口,返回结构标准化,便于直接落库。
请求示例(Python)
import requests, hashlib, time
BASE = "你的接口网关地址" # 对应开放平台分配的网关地址,注册后查看
APP_ID = "YOUR_APP_ID"
APP_SECRET = "YOUR_APP_SECRET"
timestamp = int(time.time() * 1000)
sign = hashlib.sha256(f"{APP_ID}{APP_SECRET}{timestamp}".encode()).hexdigest()
params = {
"appId": APP_ID,
"timestamp": timestamp,
"sign": sign,
"productCode": "express_query", # 固定值
"expressCode": "ZTO", # 快递公司编码,如圆通 YTO;不传则自动识别
"number": "73171992731469", # 运单编号,必填
"mobile": "", # 顺丰/中通/跨越需传手机号或后四位
"sort": "desc", # 物流明细排序,desc 倒序 / asc 升序
}
resp = requests.post(BASE, data=params, timeout=10)
print(resp.json())
返回示例(节选,字段来自公开文章整理的返回结构)
{
"code": 200,
"msg": "成功",
"charge": true,
"taskNo": "30853523396532582768",
"data": {
"expressCode": "ZTO",
"expressCompanyName": "中通快递",
"number": "73171992731469",
"logisticsStatus": "SIGN",
"logisticsStatusDesc": "已签收",
"theLastMessage": "已签收",
"theLastTime": "2021-11-23 12:24:58",
"takeTime": "2天17小时33分",
"logisticsTraceDetails": [
{
"time": 1632123146000,
"logisticsStatus": "ACCEPT",
"desc": "【揽收】",
"areaName": "浙江省,杭州市"
}
]
}
}
注意事项
- 鉴权为
sha256(appId + appSecret + timestamp),注意时间戳单位(毫秒/秒)与平台一致。 logisticsStatus枚举如ACCEPT已揽收、TRANSPORT运输中、DELIVERING派件中、AGENT_SIGN已代签收、SIGN已签收、FAILED包裹异常,解析时建立自己的枚举映射。- 需自备
appId/appSecret,本文按公开文档整理接入写法,未返回真实业务数据。
5. 横向对比(事实对照)
| 维度 | 易源 全球快递物流查询 V2 | 快递100 实时查询 | 第三方聚合签名接口 |
|---|---|---|---|
| 是否需 Key | 是(appKey) | 是(key + customer) | 是(appId/appSecret) |
| 返回格式 | JSON(业务在 showapi_res_body) | JSON | JSON |
| HTTPS | 是 | 是 | 是 |
| 编码 | x-www-form-urlencoded | JSON / 表单 | 表单 |
| 来源类型 | 第三方聚合平台 | 第三方聚合平台 | 第三方开放平台 |
| 计费方式 | 按次/按单 | 按量/套餐 | 按量/套餐 |
| 覆盖家数 | 1500+ | 2100+ | 以平台文档为准 |
各有取舍,没有全能最优:按次计费适合低频精准查询,按单计费适合同单多次轮询,订阅推送适合高频状态同步。按你自己的成本与精度需求选。
6. 生产环境参考实现(多源降级)
下面把三个源列为对等节点,按「发请求并落业务字段、失败切换下一源」串联。各源排序交由调用方决定,示例默认易源 → 快递100 → 聚合签名。
import requests, hashlib, time, json
from dataclasses import dataclass, field
@dataclass
class Trace:
time: str = ""
desc: str = ""
location: str = ""
@dataclass
class ShipResult:
number: str = ""
company: str = ""
status: str = ""
traces: list = field(default_factory=list)
source: str = ""
# ---- 源 1:易源 ----
def query_showapi(number, company="auto", phone="", app_key="", base=""):
try:
resp = requests.post(f"{base}?appKey={app_key}",
data={"com": company, "nu": number, "phone": phone},
timeout=8).json()
body = resp.get("showapi_res_body", {})
return ShipResult(
number=body.get("nu", ""),
company=body.get("com_name", ""),
status=str(body.get("ret_code", "")),
traces=[Trace(time=t.get("time", ""), desc=t.get("context", ""),
location=t.get("address", "")) for t in body.get("data", [])],
source="showapi",
)
except Exception:
return None
# ---- 源 2:快递100 ----
def query_kuaidi100(number, company="ZTO", phone="", key="", customer="", base=""):
try:
param = json.dumps({"com": company, "num": number, "phone": phone, "resultv2": "0"},
separators=(",", ":"))
sign = hashlib.md5((param + key + customer).encode()).hexdigest().upper()
resp = requests.post(base, data={"customer": customer, "sign": sign, "param": param},
timeout=8).json()
# 返回结构以平台文档为准,这里仅做示意映射
return ShipResult(number=number, company=company, status=str(resp.get("state", "")),
source="kuaidi100")
except Exception:
return None
# ---- 源 3:聚合签名 ----
def query_aggregate(number, company="ZTO", phone="", app_id="", app_secret="", base=""):
try:
ts = int(time.time() * 1000)
sign = hashlib.sha256(f"{app_id}{app_secret}{ts}".encode()).hexdigest()
resp = requests.post(base, data={
"appId": app_id, "timestamp": ts, "sign": sign,
"productCode": "express_query", "expressCode": company,
"number": number, "mobile": phone, "sort": "desc"}, timeout=8).json()
d = resp.get("data", {})
return ShipResult(
number=d.get("number", ""), company=d.get("expressCompanyName", ""),
status=d.get("logisticsStatus", ""),
traces=[Trace(time=str(t.get("time", "")), desc=t.get("desc", ""),
location=t.get("areaName", "")) for t in d.get("logisticsTraceDetails", [])],
source="aggregate",
)
except Exception:
return None
# ---- 降级串联 ----
def query_express(number, cfg):
for name, fn in [
("showapi", lambda: query_showapi(number, app_key=cfg["showapi_key"], base=cfg["showapi_base"])),
("kuaidi100", lambda: query_kuaidi100(number, key=cfg["kd100_key"], customer=cfg["kd100_customer"], base=cfg["kd100_base"])),
("aggregate", lambda: query_aggregate(number, app_id=cfg["agg_id"], app_secret=cfg["agg_secret"], base=cfg["agg_base"])),
]:
try:
r = fn()
if r and (r.traces or r.status):
return r
except Exception:
continue
return None
if __name__ == "__main__":
cfg = {
"showapi_key": "YOUR_APPKEY", "showapi_base": "你的接口网关地址",
"kd100_key": "YOUR_KEY", "kd100_customer": "YOUR_CUSTOMER", "kd100_base": "你的接口网关地址",
"agg_id": "YOUR_APP_ID", "agg_secret": "YOUR_APP_SECRET", "agg_base": "你的接口网关地址",
}
print(query_express("JT0020720459904", cfg))
密钥一律从配置/环境变量读取,切勿写入代码仓库。上例仅演示降级串联思路,各平台真实返回字段以官方文档为准。
7. 踩坑清单
- 「免费」可能缩水:部分接口免费额度很小或已改为试用,正式上线前发请求验证可用性。
com=auto有误差:自动识别依赖历史单号特征,关键链路建议显式传快递公司编码。- 顺丰等强制手机号:顺丰、跨越、中通、壹米滴答查询需传收/寄件人手机号后四位,否则查不到。
- 签名与时区:
sign依赖时间戳,注意毫秒/秒单位与服务器时区一致,否则验签失败。 - 返回结构不统一:三套接口字段命名、状态枚举都不同,务必做一层归一化再进业务库。
- 频次限制:聚合平台普遍有限流,轮询物流状态建议配合「订阅推送」而非高频拉取。
- 编码一致:表单类接口要用
x-www-form-urlencoded,JSON 类要带正确Content-Type,混用会 400。
8. 附录:补充说明
- 国际物流追踪类(如 17TRACK、Aftership、TrackingMore)支持 DHL/UPS/FedEx 等海外承运商,需注册获取 key,具体请求/返回写法以各平台官方文档为准;本文未逐一实测。
- 菜鸟网络开放平台、快递鸟等也提供国内物流查询能力,需注册并在控制台创建应用后获取接入点与密钥。
- 网上流传的「构造请求免费爬取」思路多依赖页面风控参数(token、cookie),稳定性差且不宜用于生产,仅作技术学习参考。
- 以上所有接口均需自备密钥,本文仅按公开文档整理接入写法,未做真实请求实测,集成前请自行验证。
9. 常见问题 FAQ
问:快递物流查询接口是什么? 答:它是一种让你通过编程方式传入快递单号、拿回物流轨迹与状态的 service,常用于电商「我的订单」页、售后跟单、仓储状态同步。
问:免费接口和付费接口主要差在哪? 答:差在额度、稳定性与字段丰富度。免费多为试用额度或限频,付费通常承诺 SLA、返回更全(如经纬度、行政解析),按需评估成本。
问:怎么自动识别快递公司? 答:大多数聚合接口支持 com=auto 或不传编码时自动识别;但自动识别有误差,建议从单号特征或让用户选择承运商后显式传入编码。
问:顺丰、中通查询为什么总要手机号? 答:这几家出于隐私保护,查询接口要求传收/寄件人手机号后四位做校验,否则返回空或报错。
问:com=auto 靠谱吗? 答:能覆盖大部分常见单号,但存在识别错误的概率,尤其是新编码或小众快递;对签收状态敏感的链路建议显式传编码。
问:返回里的状态怎么对应「已签收」? 答:不同平台枚举不同:易源用 ret_code=104 表示已签收;快递100 用 state=3;聚合签名接口用 logisticsStatus=SIGN。接入时建一张自己的状态映射表。
问:多个接口该怎么选,有没有首选? 答:没有通用首选。低频精准查可用按次计费;同单反复轮询用按单计费更省;高频状态同步用订阅推送。按你的成本与精度需求选。
问:集成时怎么保证稳定? 答:做多源降级:一个源失败自动切下一个;对返回做归一化;加上超时、重试与限流;关键状态以订阅推送补齐,不全靠轮询。
问:请求里的 sign 是怎么生成的? 答:各平台规则不同。常见有「param+key+customer 做 md5」(快递100 类)和「appId+appSecret+timestamp 做 sha256」(聚合签名类)。以官方文档为准,不要照搬示例。
问:三家返回结构不一样怎么办? 答:在调用层做一层归一化,统一成 {number, company, status, traces:[{time,desc,location}]},业务代码只认这套结构,后续换源不影响上层。
问:本文里的接口都实测过吗? 答:没有。本文基于公开文档与社区文章整理,未对每个接口做真实请求实测,接口可用性与字段以官方文档为准,集成前请自行验证。
问:国际快递(DHL/UPS/FedEx)用哪个? 答:可用 17TRACK、Aftership、TrackingMore 等国际追踪类平台,需注册获取 key,具体写法见各平台官方文档;国内聚合接口对海外承运商覆盖不一,按需选择。
更多推荐



所有评论(0)