PHP无法直接“解码”短链接,需禁用自动重定向并手动提取HTTP响应头中的Location字段;curl比file_get_contents更可控,但需处理JS跳转、反爬策略及非标准重定向等复杂情况。

短链接本身不是一种可逆编码,PHP 无法“解码”它——你真正需要的是 HTTP 301 或 302 重定向响应里的 Location 头。
为什么 file_get_contents 读不到真实 URL
直接用 file_get_contents('https://t.co/abc123') 得到的是跳转目标页面的 HTML 内容,不是原始长链接。因为 PHP 默认跟随重定向(allow_url_fopen + follow_location 开启时),根本收不到中间的 Location 响应头。
- 必须禁用自动跳转,手动抓取响应头
-
curl比file_get_contents更可控 - 部分短链服务(如
bit.ly)对未带User-Agent的请求会返回 403
用 curl 获取 Location 头的最小可行代码
核心是设置 CURLOPT_HEADER、CURLOPT_NOBODY 和 CURLOPT_FOLLOWLOCATION 为 false,再解析响应头。
$url = 'https://t.co/xyz789';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true); // 只要 header,不要 body
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; Linux x86_64)');
$response = curl_exec($ch);
$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
$headers = substr($response, 0, $header_size);
curl_close($ch);
if (preg_match('/^Location:\s*(.+)$/mi', $headers, $matches)) {
echo trim($matches[1]);
} else {
echo "No Location header found";
}
常见失败原因和绕过方式
不是所有短链都走标准 3xx 重定向;有些用 JS 跳转、meta refresh 或 iframe,这些 PHP 无法直接捕获。
-
tinyurl.com返回 301,可用上述方法 -
is.gd返回 301,但可能加了反爬 header 校验 -
weibo.cn/t/...返回 200 +,需额外解析 HTML -
微信内短链(
url.cn/...)常返回 200 + JS 跳转 + 验证逻辑,无法纯服务端还原
别忽略 HTTP 状态码差异
301 和 302 都带 Location,但语义不同:301 是永久重定向(可缓存),302 是临时重定向(不应缓存)。实际还原时无需区分,但要注意:
- 某些短链平台对高频请求返回 429(Too Many Requests)
- 没设
Timeout可能卡死,建议加CURLOPT_TIMEOUT => 5 - HTTPS 短链若证书异常(如自签名),需加
CURLOPT_SSL_VERIFYPEER => false(仅调试用)
真正难的不是写几行 curl,而是应对各种非标准跳转和风控策略——多数公开短链服务不承诺 API 支持,靠解析响应头只是权宜之计。











