短链接、二维码链接、推广链接在业务里很常见,但它们也有一个共同问题:用户看到的是短链,开发者和运营同学真正关心的是它最终跳到哪里,中间经过了几跳,每一跳是什么状态码。
unshort 接口就是为这个场景准备的。它可以把一个短链或跳转链接完整展开,返回原始 URL、最终落地 URL、跳转次数、总耗时,以及每一跳的状态码、跳转方式和下一跳地址。对推广短链分析、二维码内容核对、链接巡检、落地页排查来说,这类结构化结果很方便。

这个接口适合做什么
unshort 是一个短链还原 API。它接收一个待展开的 URL,然后追踪跳转链路,最终返回完整的链路明细。
比较适合这些场景:
- 推广短链落地页核对
- 二维码背后真实链接检查
- 站内外链巡检和跳转耗时记录
- 营销活动上线前确认跳转链路
- 后台工具里给运营展示"短链最终会去哪里"
它的重点不是单纯告诉你最终 URL,而是把中间每一跳也列出来。比如第一跳是 302 Location,第二跳是最终页面,业务侧就能清楚看到链路是怎么走的。
基本接入信息
接口地址:
text
GET https://v1.apizero.cn/api/unshort
请求参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url |
string | 是 | 要展开的短链或跳转链接,必须以 http 或 https 开头 |
max_hops |
number | 否 | 最大跳转次数,范围 1 到 30,默认 10 |
key |
string | 否 | API Key;匿名也可调,登录用户可获得更高额度 |
最小请求示例:
bash
curl --get "https://v1.apizero.cn/api/unshort" \
--data-urlencode "url=https://httpbin.org/redirect-to?url=https://example.com/landing" \
--data-urlencode "max_hops=5"
如果要携带 API Key,可以增加:
bash
--data-urlencode "key=YOUR_API_KEY"
这里建议用 --data-urlencode,因为被解析的链接本身可能包含 ?、&、= 等字符,直接拼接 URL 很容易把参数切乱。

2026-05-30 实测返回
我用一个公开跳转地址做了匿名实测:
text
https://httpbin.org/redirect-to?url=https://example.com/landing
接口返回如下:
json
{
"code": 0,
"msg": "成功",
"data": {
"original_url": "https://httpbin.org/redirect-to?url=https://example.com/landing",
"final_url": "https://example.com/landing",
"hops": 2,
"total_time_ms": 4234,
"chain": [
{
"hop": 1,
"url": "https://httpbin.org/redirect-to?url=https://example.com/landing",
"status": 302,
"method": "Location",
"duration_ms": 3480,
"next": "https://example.com/landing"
},
{
"hop": 2,
"url": "https://example.com/landing",
"status": 404,
"method": "final",
"duration_ms": 754
}
],
"is_redirect": true
},
"request_id": "mps8wmxu350ae853"
}
这个结果里可以看出几件事:
- 原始 URL 是
original_url - 最终落地 URL 是
final_url - 一共经过 2 跳
- 第一跳状态码是
302,跳转方式是Location - 第二跳是最终页,状态码是
404
最后一点也很有价值:短链能展开,并不代表最终页面一定是正常的。业务侧可以根据最终状态码决定是否标记为异常链接。
返回字段怎么看
成功返回后,重点看 data 里的字段:
| 字段 | 类型 | 说明 |
|---|---|---|
original_url |
string | 输入的原始链接 |
final_url |
string | 最终落地链接 |
hops |
number | 跳转次数,含最终页 |
total_time_ms |
number | 总耗时,单位毫秒 |
chain |
array | 每一跳的明细 |
is_redirect |
boolean | 是否发生重定向 |
chain 数组里每一项通常包含:
| 字段 | 类型 | 说明 |
|---|---|---|
hop |
number | 第几跳 |
url |
string | 当前跳访问的 URL |
status |
number | HTTP 状态码 |
method |
string | 跳转方式,例如 Location、Meta-Refresh、final |
duration_ms |
number | 当前跳耗时 |
next |
string | 下一跳 URL,最终页通常没有这个字段 |
如果要做后台展示,我通常会把结果整理成两层:
javascript
const summary = {
originalUrl: data.data.original_url,
finalUrl: data.data.final_url,
hops: data.data.hops,
totalTimeMs: data.data.total_time_ms,
isRedirect: data.data.is_redirect,
};
const rows = data.data.chain.map((hop) => ({
hop: hop.hop,
url: hop.url,
status: hop.status,
method: hop.method,
durationMs: hop.duration_ms,
next: hop.next || "",
}));
摘要字段放在顶部卡片,chain 渲染成表格,运营或开发同学扫一眼就能看到链路是否符合预期。

Python 调用示例
后端里可以这样封装:
python
import requests
def unshort_url(
url: str,
max_hops: int = 10,
api_key: str | None = None,
) -> dict:
params = {
"url": url,
"max_hops": max_hops,
}
if api_key:
params["key"] = api_key
resp = requests.get(
"https://v1.apizero.cn/api/unshort",
params=params,
timeout=20,
)
resp.raise_for_status()
result = resp.json()
if result.get("code") != 0:
raise RuntimeError(result.get("msg") or result.get("message") or "还原失败")
return result["data"]
result = unshort_url(
"https://httpbin.org/redirect-to?url=https://example.com/landing",
max_hops=5,
)
print("最终地址:", result["final_url"])
print("跳转次数:", result["hops"])
for item in result["chain"]:
print(item["hop"], item["status"], item["method"], item["url"])
如果是生产环境使用,建议把超时时间、最大跳数和异常处理都放在后端统一封装里。这样前端只需要传入待检测 URL,不直接接触 API Key,也不会因为单个链接解析慢拖住页面。
JavaScript 调用示例
Node.js 18+ 可以这样写:
javascript
async function unshortUrl({ url, maxHops = 10, apiKey }) {
const params = new URLSearchParams({
url,
max_hops: String(maxHops),
});
if (apiKey) {
params.set("key", apiKey);
}
const res = await fetch(`https://v1.apizero.cn/api/unshort?${params}`);
if (!res.ok) {
throw new Error(`HTTP ${res.status}`);
}
const data = await res.json();
if (data.code !== 0) {
throw new Error(data.msg || data.message || "还原失败");
}
return data.data;
}
const result = await unshortUrl({
url: "https://httpbin.org/redirect-to?url=https://example.com/landing",
maxHops: 5,
});
console.log("final:", result.final_url);
console.table(result.chain);
如果要接到前端页面,可以把 chain 做成一个跳转链路表:
| 跳数 | 状态码 | 方式 | 当前 URL | 下一跳 |
|---|---|---|---|---|
| 1 | 302 | Location | 原始短链 | 落地页 |
| 2 | 404 | final | 落地页 | - |
这样比只显示一个最终地址更清楚。
接到业务里的几个小建议
第一,输入前先做 URL 格式校验。官方错误码里说明,url 为空或不以 http/https 开头会返回 4000。前端可以先挡掉明显无效的输入。
第二,合理设置 max_hops。默认 10 已经够大多数短链使用,如果是内部工具,可以允许用户调整,但最好不要直接给到最大值 30。
第三,记录最终状态码。短链展开成功不等于落地页可用,最终跳的 status 是 404、500 或超时,都应该在业务侧标出来。
第四,展示每跳耗时。duration_ms 和 total_time_ms 可以帮助排查到底是哪一跳慢,尤其适合推广链路、活动落地页和二维码跳转排查。
第五,注意使用边界。这个接口适合做自有业务链接核对、公开推广短链分析、二维码内容检查和安全巡检,不适合对无关目标做高频扫描。业务侧要加缓存、频率控制和日志记录。