百度搜索 API 报错怎么查:query 为空、appKey err、ret_code 各是什么
# 百度搜索 API 报错怎么查:query 为空、appKey err、ret_code 各是什么
> 接口:百度搜索(apiCode=3351,接入点 3351-1)· 官方自营 · 按次计费
> 请求方式:POST / GET · 适用人群:已接入、正在排查问题的开发者 · 阅读时间:约 6 分钟
> **最后实测核对:2026-09-15(含三种错误的真实响应原文)**
调用百度搜索 API 没拿到数据,先看 `showapi_res_code`。它是 0 之外的值时,`showapi_res_body` 基本是空的,你也不用往下看 `references` 了——问题出在网关层,跟检索没关系。
这篇把三类错误的真实响应贴出来对照,并说明为什么"返回 200"不代表调用成功。
## 错误分层:先看哪一层
百度搜索 API(apiCode=3351)的响应有三层状态信息,排查顺序从上往下:
| 层级 | 字段 | 位置 | 含义 |
|------|------|------|------|
| 网关层 | `showapi_res_code` | 响应最外层 | 0 表示请求被受理;非 0 表示参数/鉴权/额度问题 |
| 网关层描述 | `showapi_res_error` | 响应最外层 | 机器可读的英文错误描述,如 `appKey err` |
| 业务层 | `showapi_res_body.ret_code` | body 内 | 0 成功 / -1 失败(文档定义) |
| 业务层描述 | `showapi_res_body.remark` | body 内 | 返回描述,实测成功时为空字符串 |
| 扣费 | `showapi_fee_num` | 响应最外层 | 本次扣了几次,**失败时为 0** |
关键点:`showapi_res_code` 非 0 时,`showapi_res_body` 会是空对象 `{}`,或者这个键**整个不存在**。两种情况的差别在下面实测表里。
## 实测错误对照表
2026-09-15 实测三种场景,其中两种是失败、一种是成功对照(请求体固定):
| 场景 | HTTP | `showapi_res_code` | `showapi_res_error` | `showapi_res_body` | `showapi_fee_num` |
|------|------|-------------------|---------------------|--------------------|-------------------|
| `query` 未传或为空 | 200 | `-1` | `must input query field` | `{}`(空对象) | `0` |
| AppKey 错误 | 200 | `-1004` | `appKey err` | **该键不存在** | `0` |
| 正常调用 | 200 | `0` | `""` | 完整业务数据 | `1` |
三条结论:
1. **HTTP 状态码永远是 200。** 出错也是 200,所以判断成功只能靠 `showapi_res_code`,不能靠 `resp.status_code`。
2. **失败不扣费。** 两种错误场景下 `showapi_fee_num` 都是 0。参数写错不会白白消耗次数,你可以放心调试。
3. **错误响应的 body 结构不统一。** `query` 为空时 `showapi_res_body` 是 `{}`;AppKey 错误时这个键直接不存在。解析代码必须两种情况都能扛住。
第 3 点是文档没写的,也是实际最容易让程序崩的地方——直接写 `result["showapi_res_body"]["references"]` 会抛 `KeyError`。
## 真实响应长什么样
`query` 未传时的完整响应(原文照录,仅去掉缩进):
```json
{
"showapi_res_error": "must input query field",
"showapi_res_id": "6aa89f3afb638c2f69c82001",
"showapi_res_code": -1,
"showapi_fee_num": 0,
"showapi_res_body": {}
}
```
AppKey 错误时的完整响应:
```json
{
"showapi_res_error": "appKey err",
"showapi_res_id": "6aa89f55fb638c2f69cf03d7",
"showapi_res_code": -1004,
"showapi_fee_num": 0
}
```
注意第二段里没有 `showapi_res_body`。`showapi_res_id` 两种情况都有,出了问题拿这个 id 去找客服,比描述现象快得多。
## 排查路径
**第一步,确认 `showapi_res_code`。** 不是 0 就对照上表定位,别继续往下查。
**第二步,如果是 `must input query field`。** `query` 是唯一必填参数,且不能为空字符串。检查三件事:参数名是否拼成 `query`(不是 `q` 或 `keyword`);内容是否真的传进去了;是不是被空值覆盖了。实测中 `query=` 这种空值提交就会触发这个错误。
**第三步,如果是 `appKey err`。** 检查 AppKey 是否放在 URL 参数 `appKey` 上、有没有多余空格或换行、是否误复制了其他接口的 key。这个错误码是 `-1004`。
**第四步,如果 `showapi_res_code` 是 0 但结果不对。** 这属于"调用成功但结果不符合预期",常见原因是 `query` 的编码出了问题,见下一节。
## 看起来成功、其实错了的情况
这是排查里最费时间的一类:`showapi_res_code = 0`、`ret_code = 0`、`references` 也有 10 条,但内容跟查询毫无关系。
2026-09-15 实测复现过一次。在 Windows 的 Git Bash 里执行:
```bash
curl -X POST "https://route.showapi.com/3351-1?appKey=YOUR_APPKEY" \
-d "query=昆明天气"
```
返回的前几条是酷狗音乐的歌曲页和金山词霸的单词页,`url` 里出现 `w=??????` 这样的内容。根因不在接口,在于命令行把中文按 GBK 送了出去,真正被检索的是一串乱码。
正确写法:
```bash
# 方式一:让 curl 自己编码
curl -X POST "https://route.showapi.com/3351-1?appKey=YOUR_APPKEY" \
--data-urlencode "query=昆明天气"
# 方式二:参数写入 UTF-8 文件后提交(Windows 下更可靠)
curl -X POST "https://route.showapi.com/3351-1?appKey=YOUR_APPKEY" \
-H "content-type: application/x-www-form-urlencoded" \
--data-binary @params.txt
```
Python 和 Node.js 用 `requests` / `URLSearchParams` 传中文不会踩这个坑,它们默认 UTF-8。
**自检方法**:看返回的 `url` 和 `title` 里中文是否正常。中文正常说明编码没问题;出现 `????` 或乱码字符,先改编码,不要再调参数。
## 稳一点的解析代码
把三层判断和键存在性一起处理,这段可以照抄:
```python
import requests
def search(query: str, appkey: str, timeout: int = 10) -> list:
resp = requests.post(
"https://route.showapi.com/3351-1",
params={"appKey": appkey},
data={"query": query},
timeout=timeout,
)
resp.raise_for_status()
result = resp.json()
code = result.get("showapi_res_code")
if code != 0:
# 网关层失败:showapi_res_body 可能为空对象,也可能不存在
raise RuntimeError(
f"调用失败 code={code} error={result.get('showapi_res_error')} "
f"res_id={result.get('showapi_res_id')}"
)
body = result.get("showapi_res_body") or {}
if body.get("ret_code") != 0:
raise RuntimeError(
f"检索失败 ret_code={body.get('ret_code')} remark={body.get('remark')}"
)
refs = body.get("references")
if not isinstance(refs, list):
return [] # 正常返回但没结果,别让它抛异常
return refs
```
三个细节:`showapi_res_body` 用 `or {}` 兜底;`references` 判断是不是列表;错误信息里带上 `showapi_res_id`。
## 进阶与边界
**`ret_code = -1` 本次没测到。** 文档写的是"成功标志 0:成功 -1:失败",但 2026-09-15 的 18 次成功调用里,参数错误和鉴权错误都在网关层就被拦下了,`showapi_res_body` 是空的,业务层的 -1 没有复现。所以这条我标在这里:文档定义存在,触发条件未实测,不要凭猜测在代码里处理它——按上面对照表的实际行为写就够了。
**没有官方错误码全集。** 文档只给了 `ret_code` 的 0 / -1,网关层错误码(如 `-1004`)没有在接口文档里列出。实测遇到的就是上面两个值,其余情况以实际返回的 `showapi_res_error` 文本为准,代码里做字符串兜底比硬编码码表靠谱。
## FAQ
**Q1:接口返回 HTTP 200,是不是就成功了?**
不是。实测三种场景(正常、`query` 为空、AppKey 错误)HTTP 状态码都是 200,区别全在响应体的 `showapi_res_code` 上。
**Q2:参数写错会不会扣次数?**
不会。实测 `query` 为空和 AppKey 错误时 `showapi_fee_num` 都是 0。
**Q3:为什么我的代码报 `KeyError: 'showapi_res_body'`?**
AppKey 错误时这个键不存在。先判断 `showapi_res_code == 0` 再取 body,或者用 `result.get("showapi_res_body") or {}` 兜底。
**Q4:返回了结果但内容和查询无关,是接口坏了吗?**
大概率是 `query` 编码问题。检查返回的 `url` 里中文是否正常,出现乱码就改用 `--data-urlencode` 或 UTF-8 参数文件。
**Q5:拿不到结果时怎么找客服?**
带上响应里的 `showapi_res_id`。这个字段成功和失败时都会返回,用它定位比复述现象有效。
## 下一步阅读
- [百度搜索 API:用 Python 跑通第一次实时检索](https://www.showapi.com/guides/baidu-search-api-quickstart-3351) —— 三种语言的正确请求写法
- [百度搜索 API 返回字段:references 里 13 个字段逐个说清](https://www.showapi.com/guides/baidu-search-api-response-fields-3351) —— 分清成功响应里每个字段
- [百度搜索 API 域名过滤只需两个参数](https://www.showapi.com/guides/baidu-search-api-domain-filter-3351) —— 返回条数比预期少时的正常原因
---
- **本系列共 8 篇**:查看[百度搜索 API 指南总目录](https://www.showapi.com/guides/baidu-search-guides-3351)