10 月 17 日,DeepSeek 在更新 V4.1-Flash-1017 的同时,把自研搜索引擎以 Search/Fetch 两个原始 JSON 接口的形式开放了。对做 Agent 和 RAG 的人来说,这意味着你不必再自己维护爬虫、处理 robots.txt、对抗 Cloudflare,就能让模型读到昨天的网页。更关键的是价格:每 1000 次成功请求 5 元,空结果和失败不计费。
我这篇文章不聊模型 benchmark,只聚焦这两个接口本身:端点能不能通、参数怎么传、账单怎么算、接入 Agent 时要注意什么。所有关于接口连通性和错误响应的测试都是我在本机真实跑的;真实的搜索/抓取结果因为手里没有配置 DeepSeek API Key,会在文中明确标注「未实测」。
Search 和 Fetch 到底做什么
DeepSeek 把能力拆成了两步:
- Search:按 query 搜索网页,返回带排序分数、权威性、摘要、日期的结构化结果。你可以把它理解为给 Agent 用的「Google 搜索结果 JSON 版」。
- Fetch:给定一个 URL,把页面正文抓成 Markdown 返回。相当于 Agent 的「网页阅读器」。
两个接口共享同一个 Base URL https://api.deepseek.com,鉴权也和 DeepSeek 的 chat completions API 完全一致:在 Header 里传 Authorization: Bearer <DeepSeek API Key>。
这种设计很朴素,但也意味着你可以把 Search/Fetch 单独接进任何已经支持 OpenAI 风格 HTTP 客户端的代码里,不需要为了新能力引入一套新 SDK。
我先测了接口可达性和错误响应
在没有 API Key 的情况下,我直接用 curl 打了两个端点,主要确认三件事:公网能否访问、TLS 是否稳定、错误响应格式是否统一。
测 Search:
curl -s -X POST "https://api.deepseek.com/v1/tools/search" \
-H "Content-Type: application/json" \
-d '{"query":"DeepSeek Search API","count":3}'返回:
{
"error": {
"message": "Authentication Fails (missing key) (request_id: 50160ca0-76f5-4dd7-970c-70f8be95dd1c)",
"type": "authentication_error",
"param": null,
"code": "invalid_request_error"
}
}HTTP 状态码 401,响应时间 0.11 秒。
测 Fetch:
curl -s -X POST "https://api.deepseek.com/v1/tools/fetch" \
-H "Content-Type: application/json" \
-d '{"url":"https://api-docs.deepseek.com/zh-cn/guides/search/"}'返回同样的 401,响应时间 0.09 秒。两个接口的错误格式和 DeepSeek 主 API 完全一致,这意味着你现有的错误处理逻辑可以复用。
我还故意传了一个伪造 Key 试了一次:
curl -s -X POST "https://api.deepseek.com/v1/tools/search" \
-H "Authorization: Bearer sk-test-invalid-key" \
-H "Content-Type: application/json" \
-d '{"query":"test","count":3}'返回:
{
"error": {
"message": "Authentication Fails, Your api key: ****-key is invalid (request_id: ...)",
"type": "authentication_error",
"code": "invalid_request_error"
}
}这说明鉴权是第一道关卡,参数校验在鉴权之后。对于自动化监控来说,可以用 401 来判断 Key 是否失效,而不是去解析业务错误。
可直接复制运行的 Python 调用代码
下面这段代码在 Python 3.11+ 下可直接跑。注意:我没有真实 Key,所以这段代码里的结果输出我无法在本机验证,但请求结构和字段命名都对照官方文档核对过。
import os
import requests
API_KEY = os.environ.get("DEEPSEEK_API_KEY")
BASE_URL = "https://api.deepseek.com"
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}
def search(query, count=5, need_content=False):
r = requests.post(
f"{BASE_URL}/v1/tools/search",
headers=HEADERS,
json={
"query": query,
"count": count,
"need_content": need_content,
},
timeout=30,
)
r.raise_for_status()
return r.json()["results"]
def fetch(url):
r = requests.post(
f"{BASE_URL}/v1/tools/fetch",
headers=HEADERS,
json={"url": url},
timeout=60,
)
r.raise_for_status()
return r.json()
# 示例:先搜后读
hits = search("DeepSeek V4.1 Flash 1017 site:github.com lang:zh", count=3)
for h in hits:
print(h["rerank_score"], h["title"], h["url"])
if hits:
page = fetch(hits[0]["url"])
print(page["title"])
print(page["content"][:500])运行环境:任何能访问 api.deepseek.com 的机器,依赖只有 requests。如果你用 Claude Code、Codex 或 DeepSeek Harness,11 月 1 日前通过 Server 端工具调用 Search/Fetch 暂不收费。
Search 的返回字段值得细看
官方文档列出的字段里,最有用的是这几个:
rerank_score:0-3 分,>=1.5 被官方视为优质结果。不要拿它当绝对阈值,建议做 top-k 排序。authority:0-4 分,>=3 算高权威。可以作为来源可信度的一个快速信号。summary:600-800 字符的长摘要,适合直接喂给模型。content:只有在need_content=True时才返回网页正文。如果你只想让模型看到摘要,传False能省上下文。date:UTC 时间,做时效性过滤时有用。
Search 支持的查询语法和主流搜索引擎很像:site:、-site:、引号精确匹配、lang:、after:、before:。例如:
DeepSeek V4 模型 site:github.com OR site:huggingface.co lang:zh after:2025这些操作符是原样传给搜索服务的,所以你不需要在代码里做二次过滤。
Fetch 不是万能爬虫
Fetch 只保证做一件事:把可读网页转成 Markdown。官方文档明确列出了会失败的情况:403(被安全策略拒绝)、404(无法获取可用内容)、目标站点返回错误、内容类型不受支持、页面没有可提取的 Markdown 正文。
也就是说,它不会替你绕过反爬。如果你的 Agent 需要读一个被 Cloudflare 护住的页面,Fetch 大概率会 403 或 404。我的建议是:把 Fetch 当成「已知可信链接的阅读器」,而不是「任意链接的通用抓取器」。
计费规则里藏着两个坑
价格看起来很便宜,5 元/1000 次成功请求,但有两个细节容易踩坑:
-
只按成功计费,但「成功」的定义很严格。Search 必须返回非空
results数组才算成功;Fetch 必须返回页面正文才算成功。失败、空结果、超时都不计费。这很好,但也意味着你不能靠「反正不贵」乱发请求来碰运气——空结果不计费,但也拿不到数据。 -
Server 端免费窗口有时间限制。11 月 1 日 00:00(北京时间)前,通过 DeepSeek Harness、Claude Code、Codex 的 Server 端工具调用 Search/Fetch 不收费。但直接调用
api.deepseek.com/v1/tools/search这个原始接口,从第一秒开始就按 5 元/1000 次收费。别在 Harness 里调得开心,转头用脚本直连时忘了这件事。
另外,Search 和 Fetch 各自独立 5 QPS 限速。Fetch 还有针对目标域名的 QPS 限制。做批量抓取时必须加队列和退避,否则 429 会来得很快。
三个接入 Agent 的实战经验
第一,不要把 Search 结果直接塞进模型上下文。应该先按 rerank_score 和 authority 做一层过滤,再决定是否 Fetch。否则一次 Search 返回 10 条结果,每条再带 content,轻轻松松吃掉几万 token。
第二,给每个检索结果保留来源信息。title、url、date 都要存。Agent 输出最终答案时,把这些作为引用附上去,既提升可信度,也方便后续审计。DeepSeek 的接口本身已经给出了这些字段,不要丢掉。
第三,为 Fetch 失败设计兜底。如果 Fetch 返回 403/404,Agent 不应该死循环重试,而是应该回退到「已知可信源」或提示用户手动提供内容。这一点在Agent Reach 实测里我也强调过:联网能力的价值不在于「什么都能抓到」,而在于「知道什么时候该停下来」。
和站内其他工具怎么配合
如果你已经看过DeepSeek V4.1-Flash 上手指南,现在可以把 Search/Fetch 接到同一个 Key 上,让模型既能推理又能查资料。上下文紧张时,可以先过一遍Headroom 上下文压缩,再决定是否 Fetch 长文。
对做 RAG 的人来说,这套接口也可以替代一部分自建爬虫:用 Search 发现新文档,用 Fetch 拿到 Markdown,然后切 chunk 进向量库。流程比自维护 Playwright 或 Scrapy 轻很多。
未实测的部分
我需要在这里诚实说明:由于本环境没有配置 DeepSeek API Key,以下内容我没有真实跑过,仅根据官方文档和第三方报道整理:
- 真实 Search 返回的
results数组质量、中文搜索效果、时效性排序。 - 真实 Fetch 对不同站点(GitHub、知乎、公众号、新闻站)的抓取成功率。
- 11 月 1 日前 Harness/Claude Code/Codex 中 Server 端工具调用的实际免费效果。
- 5 QPS 限速在并发场景下的具体表现。
如果你手上有 Key,建议先用我上面给的 Python 脚本跑 5-10 个真实 query,重点看 rerank_score 和 authority 的分布,再决定怎么接入生产流程。
写在最后
DeepSeek Search/Fetch API 的意义不是「又一个搜索工具」,而是把「实时网页检索」变成了和 completions 同等级的一等公民。对 Agent 开发者来说,这降低了两件事的成本:一是让模型知道「今天发生了什么」,二是让模型的回答有来源可追溯。
5 元/1000 次的价格会让很多人心动,但便宜不等于可以粗放使用。把 Search 当过滤器、把 Fetch 当阅读器、给失败留兜底,才是这套接口的正确打开方式。