PHP cURL请求被拒主因是User-Agent未正确发送:CURLOPT_HTTPHEADER必须用字符串数组且首字母大写(如'User-Agent: Chrome/128'),不可用关联数组;文生图接口还需同步校验Sec-Ch-Ua等客户端提示头,版本号须与UA严格一致,并轮换多套合规UA防风控。

PHP cURL 请求被拒,先确认 User-Agent 是否真正发出
很多 PHP 爬虫或文生图调用失败,根本不是服务器不认你的密钥,而是 User-Agent 根本没发出去。cURL 的 CURLOPT_HTTPHEADER 不接受关联数组,写成 ['user-agent' => 'xxx'] 会被完全忽略——你看到的请求头里压根没有 User-Agent 字段,服务器直接当非法请求打回(常见返回 403 或 503)。
必须用字符串格式,且字段名首字母大写:
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36',
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8',
'Accept-Encoding: gzip, deflate',
]);- 别写
user-agent或USER-AGENT,必须是User-Agent - 冒号后必须有一个空格,
'User-Agent:Chrome/128'是错的,要写成'User-Agent: Chrome/128' - 用浏览器 DevTools 的 Network → Copy as cURL 功能,粘贴后人工转成 PHP 数组,最稳妥
只设 UA 不够,文生图接口通常校验 Sec-Ch-* 头字段
像 Dashengfenshen.cn 这类生图 API,已不再只看 User-Agent。它们会验证 Chromium 系列客户端提示头是否与 UA 版本一致。比如 UA 里写着 Chrome/128,但没带 Sec-Ch-Ua,或版本对不上,就会返回 400 或静默丢弃请求。
补全这三组是底线:
立即学习“PHP免费学习笔记(深入)”;
'Sec-Ch-Ua: "Chromium";v="128", "Google Chrome";v="128", "Not-A.Brand";v="99"', 'Sec-Ch-Ua-Mobile: ?0', 'Sec-Ch-Ua-Platform: "Windows"'
-
Sec-Ch-Ua中的版本号必须和 UA 字符串里的 Chrome 版本严格一致(不能硬写死,需正则提取) -
Sec-Ch-Ua-Mobile: ?0表示非移动端;若伪装 iOS Safari,应为?1 -
Sec-Ch-Ua-Platform要匹配 UA 中的操作系统描述,比如 UA 含Mac OS X就得写"macOS"
UA 字符串本身过时或格式异常,也会触发风控
有些开发者从网上抄一段老 UA(比如含 Edge/12 或 IE),或者自己拼接出不合规的字符串(如漏括号、多空格、乱加引号),接口会直接拒绝——不是 403,而是无响应或超时,因为网关层就拦截了。
建议直接复用当前主流浏览器真实 UA,例如:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36'
- 避免使用
fake-useragent类库生成的 UA:它不校验有效性,JSON 文件早已过期,返回 IE11 或 Edge 12 的概率不低 - 不要手动拼接 UA,尤其别混用不同浏览器的内核标识(比如
Firefox/128 AppleWebKit/537.36) - 如果调用的是移动端专属模型(如某些画风仅限手机端),UA 必须含
Mobile关键字,否则返回空数据
并发高但 UA 单一,IP+UA 组合被标记为爬虫
文生图任务常批量提交,若所有请求都用同一个 User-Agent,哪怕 IP 是代理池轮换,风控系统仍可能把 UA + IP 当作一个“设备指纹”来限流。现象是前几条成功,后续持续返回 429 或 403,且重试无效。
简单轮换策略即可缓解:
- 准备 3–5 条不同来源的 UA(Chrome Windows/macOS、Safari macOS/iOS、Edge Win10)
- 每次请求前用
array_rand()随机选一条,再动态生成配套的Sec-Ch-Ua等字段 - 避免在
for循环里重复 new 一个 cURL 句柄,复用句柄 +curl_setopt_array()更高效
真正容易被忽略的点是:Sec-Ch-Ua 和 UA 版本号必须同步更新,否则看似轮换了 UA,实际每条请求的指纹仍是“自相矛盾”的。



















