如何修复 SearXNG 搜索引擎 CAPTCHA 错误
VPS 更容易触发搜索引擎 CAPTCHA,且可能以 HTTP 200 返回验证页。了解如何区分上游拒绝与本地 429,并选择重启后仍有效的修复方案。
SearXNG CAPTCHA 错误的含义
SearXNG CAPTCHA 错误来自实例查询的搜索引擎。您的服务器向某个搜索引擎请求结果,但该搜索引擎返回的是验证页面,而不是结果。由于响应中没有可解析的内容,SearXNG 将该搜索引擎记录为错误。您的实例运行正常。您无法控制的系统判定该请求不像是由用户发起的。
这一点决定了下面所有修复方法。该判定是在搜索引擎自己的服务器上作出的,因此您的 settings.yml 无法覆盖它。您可以更改请求发出的地址、要查询的搜索引擎,以及某个搜索引擎开始拒绝请求后实例的行为。
看起来相同的两种故障,以及如何区分
第一种故障是您自己的实例向您自己的浏览器返回 HTTP 429(请求过多)。这是 SearXNG 限流器的行为。限流器位于搜索端点前方,负责检测机器人请求。它运行在您的服务器上,也由您配置。向您自己的用户返回 429 的限流器是另一个独立问题,使用不同的设置。以下建议均不适用于该问题。
第二种故障发生在上游。结果页面正常加载,但结果中缺少一个或多个引擎,或者引擎显示错误提示。您的实例没有拒绝任何请求。是某个引擎拒绝了您的服务器。
- 页面无法加载,或搜索端点返回 429:检查您的限流器。
- 页面可以加载,但结果很少,或某个引擎标记为错误:检查上游,并继续阅读。
同一实例可能同时出现这两种故障。两者还会相互影响,因为限流器设置过宽松时,会放行更多流量,从而提高您的出站查询速率。请分别诊断这两种故障。
为什么 SearXNG 在 VPS 上返回 CAPTCHA 错误,而在我的笔记本电脑上不会?
原因是请求来源地址不同。您的家庭网络使用的是消费级 ISP(互联网服务提供商)地址段中的地址,这些地址会被许多普通用户共享。您的 VPS 使用的是数据中心地址段中的地址,这些地址段是公开的:任何人都可以查询哪些地址属于托管服务提供商。希望阻止抓取程序的搜索引擎,通常会先将来自托管服务地址段的请求视为可疑请求,因为这些地址中的请求很少来自使用浏览器的真实用户。
除了地址之外,还有其他因素会叠加影响结果。您的实例会针对每次用户搜索向每个搜索引擎发送一个请求,因此即使用户数量很少,单个地址产生的请求速率也可能超过普通个人用户的行为。SearXNG 按设计不会与搜索引擎保持会话,也不会携带长期 Cookie,因此每个请求到达时都没有历史记录。该地址还可能带有并非由您造成的历史记录,因为服务提供商会回收地址,而之前的租户可能已经使用该地址抓取了数月。
搜索引擎的拒绝不一定会表现为明显的失败。搜索引擎可能返回 403、429,也可能返回 HTTP 200,但在响应正文中包含验证页面。最后一种情况最容易造成误判,因为状态码检查会显示搜索引擎正常,而 SearXNG 却从响应中找不到任何结果。因此,应查看您自己实例的错误报告,而不是使用 curl 请求搜索引擎后只查看状态行。
先读取实例报告的内容,再进行任何更改
下面的每项修复都从发生故障的引擎名称,以及实例为该引擎记录的原因开始。SearXNG 会提供这两项信息。/stats 页面会列出引擎、错误计数和可靠性;/stats/errors 则以 JSON 返回错误详情,更便于保存并在下周进行比较。请在平时用于访问该实例的浏览器中打开它们。
容器日志会实时记录相同的事件。这里使用的服务名称来自容器文档附带的 compose 文件;如果您的名称不同,请使用您自己的服务名称。
docker compose logs -f core在日志持续输出时执行一次会失败的搜索。搜索执行期间,您应能看到失败引擎的日志条目。记下引擎名称和实例输出的确切原因字符串。不要从博客文章中复制引擎名称,包括本文。会阻止数据中心地址的引擎列表每月都会变化;对您失败的引擎,本文作者使用时可能完全正常。
如果结果页面完全没有显示错误,但结果数量很少,请检查该引擎的 display_error_messages。它默认为 true;如果实例已将其关闭,就会隐藏您需要的那条消息。
SearXNG 如何重试并暂停失败的引擎
SearXNG 不会持续重试拒绝请求的引擎。失败的引擎会被暂停。暂停期间会完全跳过该引擎,因此故障引擎会变成无提示地缺失的引擎。
有两层配置控制此行为,两者都位于 settings.yml 下的 search: 中。在粘贴任何内容前,请根据实际运行的版本,在 searx/settings.yml 中确认这些键名和值。因为它们在不同版本之间发生过变化,而且设置文档页面中的示例仍显示比 SearXNG 实际加载的文件更长的暂停时间。SearXNG 于 17 October 2026 发布的 searx/settings.yml 中,默认值如下:
search:
ban_time_on_fail: 5
max_ban_time_on_fail: 120
suspended_times:
SearxEngineAccessDenied: 180
SearxEngineCaptcha: 3600
SearxEngineTooManyRequests: 180
cf_SearxEngineCaptcha: 1296000
cf_SearxEngineAccessDenied: 86400
recaptcha_SearxEngineCaptcha: 604800第一层处理超时等普通故障。暂停从 ban_time_on_fail 秒开始,并随连续失败次数增加,最长达到 max_ban_time_on_fail。默认上限为 two minutes,因此引擎出现短暂故障后,通常会在几分钟内自动恢复。
第二层处理本指南所讨论的故障。当 SearXNG 将响应识别为挑战或拒绝,而不是一般错误时,它会应用 suspended_times 中对应的条目,其中大多数数值都大得多。180 seconds 是 three minutes,适用于普通拒绝或 429。3600 是 one hour,适用于一般 CAPTCHA。86400 是 one full day。604800 是 one week。1296000 是 fifteen days。以 cf_ 开头的键适用于识别为 Cloudflare 挑战的情况,以 recaptcha_ 开头的键适用于识别为 reCAPTCHA 的情况。
这解释了最浪费时间的现象。你找到原因并修复问题,但引擎仍然在 one hour 内没有返回任何结果,或者在 Cloudflare 挑战后数天内仍无结果。因为它仍处于暂停状态。暂停状态保存在运行中的进程内,因此重启容器即可清除该状态,下一次搜索会再次尝试该引擎。在这里,直接重启即可。开始无故重建镜像前,应先了解何时重启就足够,以及何时需要重新创建容器。如果引擎在重启后立即再次失败,说明你的修复没有生效。
有一个按引擎设置需要特别注意。retry_on_http_error 会在引擎返回你列出的状态码时重试请求。对于正在阻断你的引擎,重试会向已经判定你的服务器是 bot 的系统发送更多流量。除非你是在处理确实不稳定的引擎,否则应保持该设置不变。
SSH 隧道文档说明及其无法修复的问题
截至 17 October 2026,SearXNG 管理文档通过手动建立隧道来解决此问题。您可以通过服务器建立 SOCKS 代理,让桌面浏览器使用该代理,然后手动完成验证,同时让引擎看到服务器的地址。
ssh -q -N -D 8080 user@example.org-D 8080 会在本地 8080 端口上启动 SOCKS 服务器,并通过 SSH 连接转发流量。-N 不执行远程命令,-q 使其保持安静,因此隧道正常时不会输出任何内容,也不会退出。请在第二个终端中检查:
curl -x socks://127.0.0.1:8080 http://ipecho.net/plain
curl http://ipecho.net/plain第一条命令应输出服务器的地址,第二条命令应输出桌面设备的地址。如果两条命令输出相同的地址,说明请求没有通过隧道。然后将浏览器的网络设置为 SOCKS5 代理,地址为 127.0.0.1,端口为 8080。在浏览器中打开同一个地址检查服务,确认其报告的是服务器地址,然后访问触发验证的引擎,并在那里完成验证。
现在说明这种方法的限制。共有 4 个问题。引擎下发的 cookie 会保存在桌面浏览器中,而 SearXNG 无法访问浏览器的 cookie。因此,唯一能帮助您的实例的,是引擎针对该地址本身记录的信息。该记录会过期,过期时间由引擎决定,且不会公开。整个过程没有任何自动化机制,因此下次仍需手动操作。如果该实例供其他人使用,触发验证的查询速率仍在持续,验证还会再次出现。
可以用这种方法让一个实例在今天下午恢复工作。但不要以此为基础构建实例。
持久修复:移除或降低阻塞您的引擎权重
最经济且持久的做法,是停止查询无法为您的服务器提供结果的引擎。您的 settings.yml 在容器镜像中以 use_default_settings: true 开始,这意味着,在 engines: 下添加与 name 匹配的条目后,只会覆盖您列出的键,其余默认定义保持不变。
use_default_settings: true
engines:
- name: <engine name from your stats page>
disabled: true
- name: <another engine name>
weight: 0.3disabled: true 默认关闭该引擎,但仍将其保留在偏好设置页面中,因此需要使用该引擎的用户可以为自己的搜索重新启用它。inactive: true 会将该引擎从用户设置中完全移除。如果某个引擎永远无法从您的地址使用,这正是您需要的设置。weight 的作用不同:它会调整该引擎的结果在 SearXNG 合并和排序结果时所占的比重,因此将权重设为低于 1 可以保留性能有限的引擎,同时避免它占据首页结果。
编辑后重启容器,执行几次搜索,然后再次检查 /stats。包含 6 个可用引擎且没有错误的统计页面,比包含 20 个引擎但错误满页更有价值。
持久解决方案:通过代理发送出站请求
SearXNG 可以通过代理发送出站引擎请求,从而改变引擎看到的地址。您可以在 outgoing: 下全局设置代理;如果只有一个引擎存在问题,也可以单独为该引擎设置。
outgoing:
request_timeout: 3.0
extra_proxy_timeout: 10
proxies:
all://:
- socks5h://user:password@proxy:1080engines:
- name: <engine name>
proxies:
http: socks5h://user:password@proxy:1080
https: socks5h://user:password@proxy:1080如果希望由代理解析主机名,应优先使用 socks5h://,而不是 socks5://,因为 h 表示将名称发送给代理,而不是在服务器上解析。请同时增加超时时间预算。request_timeout 默认为 3.0 秒,代理会为每个请求增加一次往返通信,因此原本能及时响应的引擎可能会改为因超时而失败。extra_proxy_timeout 正是为此而存在:使用代理时,它会增加额外的秒数。请将其写成整数,例如 10。不同于接受小数的 request_timeout,extra_proxy_timeout 在设置架构中是整数,因此 10.0 这样的值会被拒绝为无效的 settings.yml,即使出站设置文档页面中的注释示例就是这样写的。
使用代理的代价:
- 代理运营者可以看到您的实例查询了哪些引擎,以及查询时间。TLS(传输层安全)会将搜索词排除在其日志之外,因为查询位于加密请求中;但您的流量特征和时间信息仍由对方掌握。
- 共享出口地址也会与其他付费用户共享。如果这些用户进行抓取,您会继承他们的信誉问题,有时甚至会比您试图绕过的封禁更快受到影响。
- 廉价的住宅代理池通常由消费者设备组成,而设备所有者并未明确同意承载流量。请了解您购买的服务。
using_tor_proxy: true会通过 Tor 路由,但出口节点地址会完整公开;对于通常会限制数据中心地址段的引擎,出口节点通常也会受到同样严格甚至更严格的限制。- 搜索现在依赖服务器之外的服务。该服务可能按照自己的时间表发生故障,并使您的搜索结果一并不可用。
代理只是转移了封禁,并未消除封禁;同时,实例的隐私边界也纳入了第三方。如果您自行托管的原因是希望获得简洁明确的隐私边界,请在注册任何服务之前,权衡这一点与自行托管的实例究竟隐藏了什么,以及没有隐藏什么之间的差异。
有针对性的持久方案:主动使用更少的引擎
大多数人会忽略的选项是接受更少的引擎。SearXNG 的价值在于合并结果。6 个每次都能返回结果的引擎,优于20 个但其中一半会连续暂停数小时或数天。连续一周监控 /stats,保留从您的地址访问记录良好的引擎。
使用 API key 进行身份验证的引擎行为不同,因为引擎知道您的身份,会执行配额限制,而不是猜测您是否为真人。代价是需要一个账户、将 key 保存在设置文件中,而且通常还会产生费用。对于您真正需要的1或2个引擎,这通常是最省事的方案。
结合其他工具一起决定。任何通过 API 读取结果的工具都无法看到已暂停的引擎,因为 Open WebUI 和类似工具查询的 JSON API 只会返回更少的结果,不会返回工具能够识别的错误。如果有自动化任务依赖您的实例,请按计划轮询 /stats/errors,不要等到有人发现结果质量下降后再处理。
是否值得继续解决这个问题?
可以根据用户数量判断。单人实例每天从一个地址发出少量搜索请求,许多搜索引擎不会对此发起验证。如果某个引擎要求验证,解决方法也很简单:移除该引擎,通常几乎不会察觉它已不可用。这就是在小型 VPS 上自行运行 SearXNG的常见情况,不需要隧道或代理。
公共实例或共享实例使用相同的软件,但运行在不同的服务器上。触发验证的因素是查询速率,而且用户越多,查询速率越高,因此验证请求的到来速度会超过任何配置的处理能力。从一开始就规划较小的搜索引擎集合,并记住:现在添加的任何代理,都会让其他用户的搜索请求使用您的账户。
自动化客户端处于两者之间,但更接近复杂情况。一个代理为了回答一个问题而执行多次搜索,会产生人类用户不会产生的突发请求。因此,供编码代理和研究工具使用的实例会比手动操作的相同实例更早遇到验证。如果您的用途属于这种情况,应根据可靠性而不是覆盖范围选择搜索引擎集合,并让代理使用实际能够获取的结果。
通用原则是:如果某个搜索引擎是您自行托管的原因,就解决与它相关的问题;如果不是,就移除它。
FAQ
修复问题后,为什么 SearXNG 引擎仍然不返回结果?
因为它仍处于暂停状态。SearXNG 识别到引擎发出的挑战或拒绝后,会在 search.suspended_times 设置的时间内停止查询该引擎。根据拒绝类型,默认暂停时间从三分钟到十五天不等。暂停状态保存在运行中的进程内,因此重启容器即可清除该状态,下一次搜索会再次尝试使用该引擎。如果引擎在重启后立即再次失败,说明修复未生效。
引擎返回的 CAPTCHA 错误与实例返回的 429 是同一种问题吗?
不是,它们的方向相反。实例向浏览器返回 429,表示 SearXNG 自身的限制器判断请求看起来像自动化请求;该限制由您配置。CAPTCHA 或阻止错误表示上游引擎拒绝您的服务器请求,决定权在您无法控制的设备上。如果结果页面可以加载,但只有部分引擎缺失,那么遇到的是后一种情况。
在服务器上使用 VPN 或代理能解决引擎的 CAPTCHA 吗?
有时可以,但需要付出代价。通过 outgoing.proxies 路由出站请求会改变引擎看到的地址,因此可能解除针对您所在数据中心地址段的封锁。但代理运营者会看到您查询了哪些引擎以及查询时间;共享出口地址还可能继承其他客户的信誉问题;额外延迟也会导致超时,除非提高 request_timeout 和 extra_proxy_timeout。Tor 可通过 using_tor_proxy 使用,但其出口地址是公开的,也经常受到挑战。
可以让 SearXNG 自动解决 CAPTCHA 吗?
没有相关设置。项目文档记录的方法是手动处理:使用 SSH SOCKS 隧道、您自己的浏览器,并由您亲自完成挑战。您构建的任何自动应答机制都违背引擎声明的策略,而且每次挑战变化后都会静默失效。这样您维护的将是一个抓取器,而不是运行搜索实例。移除会阻止您地址的引擎,才是能够持续有效的解决方案。