DeepSeek Search 与 Fetch API:用法、计费与限速
已有 DeepSeek API Key,就能给 Agent 和 RAG 接上实时网页搜索:两个接口的 curl 用法、rerank_score 筛选、错误重试规则、每千次 5 元的计费,以及和自建 SearXNG 怎么选。
DeepSeek Search 和 Fetch API 是什么
DeepSeek Search 和 Fetch API 是 DeepSeek 开放平台的两个联网接口。Search 按关键词返回实时网页结果,Fetch 把一个网址的正文转成 Markdown 返回。你已有的 DeepSeek API Key 可以直接调用这两个接口,不需要海外信用卡,也不需要另外申请 Google 或 Bing 的搜索 API。截至 2026 年 10 月 22 日,两个接口都按每 1,000 次成功请求 5 元计费,失败、空结果和超时的请求不收费。
下面的内容都来自 DeepSeek 官方指南 api-docs.deepseek.com/zh-cn/guides/search(2026-10-22 阅读)。读者对象是这样的开发者:自己写 Agent,或者搭 RAG(检索增强生成)流程,或者在 n8n 里搭工作流,想让模型拿到当天的网页内容。下面先给两个能直接运行的 curl 命令,再讲返回字段怎么用、出错后怎么重试、费用怎么算,最后对比自建 SearXNG 和通过 LiteLLM 接入这两种做法。
先准备好 API Key 和工具
两个接口都用 Bearer 认证,请求头要带 Authorization: Bearer <你的 Key> 和 Content-Type: application/json。在 Ubuntu 上先装好 curl 和 jq,jq 用来筛选返回的 JSON。
sudo apt update && sudo apt install -y curl jq
read -rs DEEPSEEK_API_KEY && export DEEPSEEK_API_KEY用 read -rs 粘贴 Key 时,屏幕上不会显示内容,Key 也不会写进 shell 历史记录。下面所有命令都从这个环境变量读取 Key。
如何调用 Search 接口
Search 的地址是 POST https://api.deepseek.com/v1/tools/search。最小的请求只需要 query:
curl -s https://api.deepseek.com/v1/tools/search \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "DeepSeek V4 模型 发布", "count": 5, "need_content": true}'请求成功时,你会收到 HTTP 200 和一个 results 数组。没有任何匹配时,接口同样返回 200,只是数组为空。空结果不计费,但你的代码要能处理这种情况,不要直接读取 results[0]。
请求参数一共五个。指南写明,未知字段会被忽略。
query:必填。长度 1 到 128 个 Unicode 字符,不能全是空白。支持下一节讲的搜索运算符。count:可选,表示返回多少条结果。范围 1 到 50,默认 10。ori_question:可选,填用户的原始问题,长度 1 到 128 个字符。接口用它推断搜索意图。localization:可选,默认是空字符串。填一个 IP 地址后,接口会优先返回这个地区的本地化结果。need_content:可选,默认false。为false时,每条结果的content都是空字符串。
query 和 ori_question 的区别要分清。Agent 生成的搜索词通常很短,比如 nftables masquerade 不生效。用户的原话可能是“我的 VPS 开了 WireGuard,客户端连上了但上不了网,是不是 NAT 规则写错了”。把用户原话放进 ori_question,接口排序时就知道用户真正要解决的问题。
localization 要填 IP 地址。如果你的服务替终端用户搜索,可以填用户的公网 IP,例如 "localization": "203.0.113.10"。不填就不做本地化偏好。
搜索运算符:site:、lang:、after:
运算符直接写在 query 里,可以组合使用:
site:只搜某个站点,-site:排除某个站点。-关键词排除包含这个词的结果。"..."要求精确匹配短语,-"..."排除这个精确短语。lang:限定语言,多个语言用逗号分隔,例如lang:zh,en。after:和before:按发布时间过滤,可以写年份,也可以写完整日期。
下面是一个组合运算符的例子:只要 2026 年之后、来自 nftables 官方 wiki 的中文和英文结果。
curl -s https://api.deepseek.com/v1/tools/search \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "masquerade site:wiki.nftables.org lang:zh,en after:2026", "count": 10}' \
| jq '.results[] | {rerank_score, authority, title, url}'注意,运算符本身也算在 128 个字符的上限里。运算符写得越多,留给关键词的字数就越少。超出上限会返回 400。这类错误重试没有用,要把 query 改短。
rerank_score 和 authority 有什么用
每条结果都有 title、url、site_name 和 site_icon 字段。除此之外,还有三组字段对 Agent 特别有用。
第一组是两种长度的摘要。snippet 大约 100 到 200 个字符,适合展示给用户看。summary 大约 600 到 800 个字符,指南说它是给模型用的。很多场景下,把几条 summary 拼进提示词就够了,不必再调用 Fetch 读全文,每次能省一次请求的费用。
第二组是 rerank_score,范围 0 到 3,综合了相关性、权威性和时效性。指南的原话是:大于等于 1.5 分为优质结果。
第三组是 authority,范围 0 到 4,表示网页的权威性。-1 表示未知,大于等于 3 为极权威结果。
这两个分数的作用,是在结果交给模型之前先过滤一遍。模型读到一条低质量的结果,可能把里面的错误内容当成事实写进回答。下面用 jq 统计优质结果的数量:
curl -s https://api.deepseek.com/v1/tools/search \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "Ubuntu 26.04 发布说明", "count": 20}' \
| jq '[.results[] | select(.rerank_score >= 1.5)] | length'命令输出一个整数,表示这 20 条结果中有几条达到 1.5 分。authority 等于 -1 的结果要单独处理,因为它的意思是“不知道”,不是“很低”。如果你写 select(.authority >= 3),权威性未知的页面会全部被过滤掉,其中可能有小众但内容准确的技术博客。另外,date 字段是 UTC 的 RFC 3339 时间,也可能是 null,按时间排序之前要先判断一下。
如何调用 Fetch 接口
Fetch 的地址是 POST https://api.deepseek.com/v1/tools/fetch。请求体只有一个必填字段 url:
curl -s https://api.deepseek.com/v1/tools/fetch \
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com/article"}' \
| jq -r '.title, .content'返回体有两个字段:title 和 content。页面没有标题时,title 是空字符串。content 是 Markdown 格式的正文。url 有三条限制:最长 8192 个字符;必须是带主机名的 HTTP 或 HTTPS 地址;地址里不能包含用户名和密码,所以 https://user:pass@host/ 这样的写法会被拒绝。
指南特别说明,Fetch 的结果取决于目标网站是否可用,也取决于它的访问策略。目标站点拦截了抓取,接口就拿不到正文。这时你会收到 403 或 404,下一节讲两者的区别。
错误码和重试规则
出错时,返回体使用 OpenAI 兼容的格式,包含 error.message、error.type、error.param 和 error.code 四个字段,其中 param 永远是 null。各 HTTP 状态码的含义如下:
400:请求头或请求体无效,包括 JSON 格式错误和参数值不合法。401:缺少 API Key,或者 Key 无效。402:账户余额不足。403:Fetch 请求被安全策略拒绝。404:Fetch 没有拿到可用内容。可能的原因有:网址打不开、被拦截、目标站点出错、文件类型不支持,或者页面里没有能提取成 Markdown 的内容。408:读取请求体超时。413:请求体太大。429:超过了 Search 或 Fetch 的 QPS 限制。500:服务端内部错误。504:下游请求超时。
403 和 404 只会出现在 Fetch 上。两个接口都是只读的,重复调用不会产生副作用,所以指南给的重试规则很简单:
- 遇到 408、429 或 5xx 错误,等待一段时间后重试。
- 遇到 402 错误,先充值,再重试。
- 遇到其它 4xx 错误,如果不修改请求,就不要重试。
第 3 条最容易被忽略。很多通用的 HTTP 客户端库会对所有错误自动重试几次。但 400 和 401 重试后只会得到同样的错误,还会占用你的 QPS 额度。
下面这个脚本只用 Python 标准库。它按上面的规则重试:先搜索,再从优质结果里找到第一条能抓到正文的页面并读取。保存为 ds_search.py:
#!/usr/bin/env python3
import json
import os
import sys
import time
import urllib.error
import urllib.request
API = "https://api.deepseek.com/v1/tools/"
KEY = os.environ["DEEPSEEK_API_KEY"]
def call(tool, payload, tries=4):
body = json.dumps(payload).encode()
for i in range(tries):
req = urllib.request.Request(
API + tool,
data=body,
method="POST",
headers={
"Authorization": "Bearer " + KEY,
"Content-Type": "application/json",
},
)
try:
with urllib.request.urlopen(req, timeout=30) as r:
return json.load(r)
except urllib.error.HTTPError as e:
retry = e.code in (408, 429) or e.code >= 500
if retry and i < tries - 1:
time.sleep(2 ** i)
continue
raise
def main():
question = sys.argv[1]
res = call("search", {"query": question, "count": 10, "ori_question": question})
good = [r for r in res["results"] if r["rerank_score"] >= 1.5]
if not good:
print("没有达到 1.5 分的结果")
return
for r in good:
print(r["rerank_score"], r["authority"], r["url"])
for r in good:
try:
page = call("fetch", {"url": r["url"]})
except urllib.error.HTTPError as e:
if e.code in (403, 404):
continue
raise
print(page["title"])
print(page["content"][:800])
return
if __name__ == "__main__":
main()运行:
python3 ds_search.py "Ubuntu 26.04 发布说明"正常的输出先是几行“分数、权威性、网址”,然后是一个页面标题和正文的前 800 个字符。脚本以 HTTPError: HTTP Error 401 退出,说明环境变量里的 Key 不对。以 HTTP Error 402 退出,说明余额不足。Fetch 遇到 403 或 404 时,脚本会跳到下一条结果,因为这两个状态码表示这个网址本身抓不到,对同一个网址重试不会得到不同的结果。传入的问题不能超过 128 个字符,因为脚本把它同时作为 query 和 ori_question 发送。
DeepSeek 联网搜索怎么收费
指南里的计费规则写得很直接(2026-10-22 阅读):
- Search 和 Fetch 按请求次数计费,不按 token 计费,也不按返回结果的条数计费。
- 两个接口的价格都是每 1,000 次成功请求 5 元。
count只控制返回多少条结果,不影响单次请求的价格。所以count: 50和count: 1的费用相同。- 只有产生了结果的 HTTP 200 响应才计费:Search 返回了非空的
results,或者 Fetch 返回了正文。失败的请求、空结果和超时都不计费。
还有一条带日期的说明。指南写道:在 DeepSeek Harness、Claude Code、Codex 中通过 DeepSeek API 使用时发起的 Search/Fetch 调用,目前不计费,将于北京时间 2026 年 11 月 1 日 00:00 起按次收费。这条说明只针对这几个工具里的调用。你自己的代码直接请求 /v1/tools/search,现在就按上面的价格计费。11 月 1 日之后的情况,以官方页面届时的内容为准。如果你还不清楚 Harness 指什么,可以先读 Agent harness 是什么,它和模型有什么区别。
下图把单价换算成每月费用。计算前提:每月按 30 天算,所有请求都成功并且有结果,每“读一个页面”就是一次 Fetch。这些数字是按单价算出来的,不是实测账单。
此图表背后的数据
[
{
"label": "\u6bcf\u5929 100 \u6b21\u641c\u7d22",
"monthly_requests": "3,000",
"cost_yuan": 15
},
{
"label": "\u6bcf\u5929 100 \u6b21\u641c\u7d22\uff0c\u6bcf\u6b21\u8bfb 3 \u9875",
"monthly_requests": "12,000",
"cost_yuan": 60
},
{
"label": "\u6bcf\u5929 1,000 \u6b21\u641c\u7d22\uff0c\u6bcf\u6b21\u8bfb 3 \u9875",
"monthly_requests": "120,000",
"cost_yuan": 600
}
]一个只搜索、不读全文的个人助手,每天搜索 100 次,每月是 3,000 次请求,约 15 元。如果 Agent 每次搜索后再读 3 个页面,请求数会变成原来的 4 倍。同样每天搜索 100 次,每月约 60 元。到了每天搜索 1,000 次的规模,每月是 120,000 次请求,约 600 元。
从图里可以看出,费用主要取决于 Fetch 的次数,而不是搜索的次数。最直接的省钱办法有两个:先用 rerank_score 过滤,只抓真正需要的页面;能用 summary 回答的问题,就不调用 Fetch。还要记住,这只是联网工具本身的费用,模型读取这些网页内容消耗的 token 另外计费。给 Agent 设置每日预算和调用上限的方法,可以参考 在 VPS 上控制 AI Agent 的花费。
限速:Search 100 QPS,Fetch 25 QPS
截至 2026-10-22,指南写明的限速按账号计算。Search 和 Fetch 各自独立计算,互不占用额度:
- Search:每个账号 100 QPS。
- Fetch:每个账号 25 QPS。另外,Fetch 对每个目标域名还有单独的 QPS 限制,指南没有给出具体数字。
这个限制和你用哪个 API Key 无关,也和模型接口的并发限制无关。同一个账号下建 10 个 Key,总额度仍然是 100 和 25。超过其中任何一个限制,都会返回 429。网上一些较早的第三方文章给出的数字和这里不同,请以官方指南为准。
实际使用中,按域名的限制更容易碰到。假设你的 RAG 流程要抓同一个文档站的 30 个页面,并且一次全部并发发出。这 30 个请求在一秒内发出,本身就超过了账号级的 25 QPS。即使你把总速率压到 25 QPS 以下,它们都指向同一个域名,仍然可能因为按域名的限制收到 429。解决办法是按域名排队:同一个域名的请求串行发送,遇到 429 时按上面的规则等待后重试。
和自建 SearXNG 比,选哪个
SearXNG 是一个开源的元搜索引擎。它把你的查询转发给多个搜索引擎,再把结果合并返回。部署在自己的 VPS 上以后,每次搜索都没有按次费用。具体部署步骤见 在 VPS 上自建 SearXNG 搜索。让 Agent 调用它的方法,见 给编程 Agent 加一个基于 SearXNG 的搜索技能。
自建的代价有两部分。第一,服务器、更新和故障都要你自己负责。第二,上游搜索引擎看到的是你服务器的 IP。一个 IP 短时间内发出大量自动化查询,搜索引擎可能会弹出验证码,这时 SearXNG 就拿不到这个引擎的结果了。SearXNG 官方文档有专门的一页“Answer CAPTCHA from server's IP”,讲的就是这种情况。文档给出的办法是:用 SSH 建一个 SOCKS 代理,让本地浏览器的请求从服务器的 IP 发出,然后在浏览器里手动完成验证码。文档没有说小型 VPS 多久会遇到一次验证码,这取决于你的查询量和启用的引擎。
另一个区别在返回的内容上。SearXNG 返回的是各个引擎的结果列表,没有 rerank_score 和 authority 这样的统一评分。要把网页正文转成 Markdown,你需要自己写抓取程序。DeepSeek 把评分和正文抓取都做好了,代价是按次付费。
可以按下面的情况来判断:
- 查询量小、预算有限、愿意维护服务器:自建 SearXNG。
- 需要稳定可用和正文抓取,不想处理验证码:用 DeepSeek Search 和 Fetch。
- 已经部署了 SearXNG:继续用它做搜索,只在需要全文时调用 DeepSeek Fetch,费用只花在 Fetch 上。
- 只在本地运行模型,想知道本地模型能否联网:先看 Ollama 能不能搜索网页。
国内还有其它网页搜索 API,例如博查和阿里云 IQS(信息检索服务)。阿里云的计费公告说明,IQS 正在和 CleverSee 合并,计费和计量会迁移到新的 CleverSee 控制台。这两家的价格请到各自官网查看。这里没有核实到它们当天的价格,所以不做数字对比。
通过 LiteLLM 接入:search_provider: deepseek
如果你的 Agent 或 n8n 流程已经通过 LiteLLM 网关调用模型,可以把 DeepSeek 搜索也接到同一个网关上。这样应用只需要配置一个地址和一个 Key。下面是 LiteLLM 文档里的 Python SDK 用法:
import os
from litellm import search
os.environ["DEEPSEEK_API_KEY"] = "sk-..."
response = search(
query="latest AI developments",
search_provider="deepseek",
max_results=5
)使用代理模式时,在 config.yaml 里加一个 search_tools 条目。下面是文档里的原样示例,model_list 部分换成你自己已有的模型配置即可:
model_list:
- model_name: gpt-6.1-sol
litellm_params:
model: gpt-6.1-sol
api_key: os.environ/OPENAI_API_KEY
search_tools:
- search_tool_name: deepseek-search
litellm_params:
search_provider: deepseek
api_key: os.environ/DEEPSEEK_API_KEY启动代理后,调用路径由 search_tool_name 决定:
litellm --config /path/to/config.yaml
curl http://0.0.0.0:4000/v1/search/deepseek-search \
-H "Authorization: Bearer $LITELLM_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "latest AI developments", "max_results": 5}'LiteLLM 会做几项参数转换。max_results 会转成 DeepSeek 的 count,并限制在 1 到 50 之间。search_domain_filter 会转成拼接在查询后面的 site: 运算符。country 和 max_tokens_per_page 在 DeepSeek 上没有对应参数,会被丢弃。DeepSeek 特有的 need_content、ori_question 和 localization 可以直接传入。有一点要注意:LiteLLM 文档示例里的 localization 写的是 "en-US",而 DeepSeek 官方指南说这个参数是一个 IP 地址。两者不一致时,以接口提供方 DeepSeek 的文档为准。
哪个 LiteLLM 版本支持 DeepSeek 搜索
这一点要特别注意。加入 DeepSeek 搜索的代码是 LiteLLM 仓库的提交 9bafafc2df3c8871bb30277f47d9fb6600e707e4,标题是 feat(search): add DeepSeek as a /v1/search provider (#47401),时间是 2026-10-19,已经合并进 main 分支。但截至 2026-10-22,最新正式版 v1.106.2(2026-10-21 发布)不包含这个提交,最新预发布版 v1.107.0-rc.2 也不包含。所以现在还没有可以固定的正式版本号。
pip install -U litellm 装到的版本可能还没有这个功能。安装后用下面的命令检查:
pip show litellm | grep -i '^version'
python3 -c "import litellm, os; print(os.path.isdir(os.path.join(os.path.dirname(litellm.__file__), 'llms', 'deepseek', 'search')))"第二条命令输出 True,说明当前安装的版本包含 DeepSeek 搜索的代码。输出 False,说明还不包含,这时 search_provider: deepseek 不会生效。最稳妥的做法是等 GitHub 上 BerriAI/litellm 的 Releases 页面出现包含 #47401 的正式版,再升级。如果必须现在就用,可以在虚拟环境里固定安装到这个提交:
python3 -m venv ~/litellm-venv
~/litellm-venv/bin/pip install "litellm[proxy] @ git+https://github.com/BerriAI/litellm.git@9bafafc2df3c8871bb30277f47d9fb6600e707e4"这样装的是 main 分支上的一个中间状态,没有经过正式发布的测试流程。用到生产环境之前,先在测试环境里把你自己的模型调用也跑一遍。
FAQ
DeepSeek Search API 怎么收费,count 设大一点会更贵吗?
截至 2026 年 10 月 22 日,Search 和 Fetch 都按每 1,000 次成功请求 5 元计费。计费按请求次数算,不按 token 或结果条数算。count 只决定返回多少条结果,count: 50 和 count: 1 的单次价格相同。只有返回了非空结果的 HTTP 200 响应才计费,失败、空结果和超时都不收费。
在 Claude Code 里用 DeepSeek 联网搜索要付费吗?
DeepSeek 官方指南写明,在 DeepSeek Harness、Claude Code、Codex 中通过 DeepSeek API 使用时发起的 Search/Fetch 调用,目前不计费,将于北京时间 2026 年 11 月 1 日 00:00 起按次收费。你自己的程序直接调用 /v1/tools/search 和 /v1/tools/fetch,现在就按正常价格计费。
为什么 DeepSeek Fetch 返回 404 或 403?
403 表示这个 Fetch 请求被安全策略拒绝。404 表示没有拿到可用内容,可能的原因有:网址打不开、目标站点拦截、站点出错、文件类型不支持,或者页面里没有能转成 Markdown 的正文。对同一个网址重试这两种错误没有用,应该换下一条搜索结果。另外,网址里带有用户名和密码,或者长度超过 8192 个字符,请求也会被拒绝。
收到 429 错误该怎么办?
429 表示超过了 QPS 限制。截至 2026-10-22,指南写的是每个账号 Search 100 QPS、Fetch 25 QPS,两者独立计算,和使用哪个 API Key 无关。Fetch 对每个目标域名还有单独的限制。按指南的规则,等待一段时间后重试即可。如果经常碰到 429,就把同一个域名的 Fetch 请求改成排队串行发送。
LiteLLM 从哪个版本开始支持 search_provider: deepseek?
截至 2026 年 10 月 22 日,还没有任何正式版包含这个功能。相关代码是 PR #47401,已于 2026-10-19 合并进 main 分支,但 v1.106.2 和 v1.107.0-rc.2 都不包含它。请到 BerriAI/litellm 的 Releases 页面确认,或者安装后检查 litellm/llms/deepseek/search 目录是否存在。