Paano Ayusin ang SearXNG 429 at Rate Limits
Ang SearXNG 429 ay galing sa sariling limiter; ang engine blocking ay nag-aalis lang ng results. Basahin ang log para malaman kung alin ang dapat ayusin.
Bakit nagbabalik ang SearXNG ng mga 429 error
Ang isang self-hosted na SearXNG instance ay nakakaranas ng rate limit sa dalawang magkahiwalay na lugar, at kadalasan ay hindi ang inaakala mong rate limit ang kailangang ayusin. Isa lamang sa mga ito ang nagbabalik ng 429. Ang una ay lokal: nagpasya ang sariling limiter ng SearXNG na galing sa bot ang isang request at sumagot ng Too Many Requests na may status na 429. Ang limiter na ito lamang ang bahagi ng SearXNG na nagpapadala ng 429 sa client. Ang ikalawa ay upstream: tinanggihan ng isang search engine ang IP address ng iyong server. Minamarkahan ng SearXNG na unresponsive ang engine na iyon at sinusu-suspend ito. Makakakuha pa rin ang iyong mga user ng normal na results page, pero may nawawalang resulta; hindi sila makakakuha ng 429.
Walang iisang fix para sa dalawang kasong ito. Iyo ang limiter, kaya maaari mo itong baguhin. Sa panig ng Google nangyayari ang upstream blocking, kaya walang setting sa iyong settings.yml ang makapag-aalis nito. Sasabihin ng log kung alin sa dalawa ang nangyayari sa loob ng humigit-kumulang isang minuto, kaya doon ka magsimula.
Ipinapalagay ng gabay na ito ang container install na inilalarawan sa isang self-hosted na SearXNG instance sa sarili mong VPS. Ang bawat setting name sa ibaba ay mula sa kasalukuyang upstream documentation at source, na sinuri noong 17 October 2026.
Basahin ang log bago magbago ng setting
Gawin ang problema habang bukas ang log window. Sa upstream compose file, ang pangalan ng SearXNG service ay core (ang pangalan ng container nito ay searxng-core), at ginagamit ng mga command na docker compose ang pangalan ng service:
cd ./searxng/
docker compose logs -f coreAng mga mensahe ng limiter ay nagmumula sa logger na pinangalanang searx.limiter, at tinutukoy ng mga ito ang client network. Ang blocklist hit ay ganito ang nakasulat: BLOCK 203.0.113.10/32: matched BLOCKLIST, habang ang allowlist hit ay ganito: PASS 203.0.113.10/32: matched PASSLIST. Kasunod ng bawat isa ang list entry na tumugma. Kung hindi maabot ng limiter ang counter store nito, nakasulat sa log ang The limiter requires Valkey, please consult the documentation. Ibig sabihin nito, walang binibilang.
Naka-log sa debug level ang bawat indibidwal na bot check, kaya hindi mo ito makikita bilang default. I-on ang debug para sa isang test sa settings.yml:
general:
debug: trueMagdaragdag ang log ng mga linyang may anyong BLOCK 203.0.113.10/32: missing HTTP header Accept-Language, kasama ang client network at header na hindi pumasa. I-off muli ito pagkatapos, dahil sinasabi ng upstream na huwag magpatakbo ng deployed instance na naka-on ang debug.
Ibang-iba ang anyo ng engine failures. Tinutukoy ng mga ito ang engine sa halip na IP, at ang mga ito ay nasa debug level din sa kasalukuyang source logs. Ang pinakakaraniwan ay timeout, na sinusundan ng pangalan ng exception:
HTTP requests timeout (search duration : 3.1 s, timeout: 3.0 s)May page din para rito. Kapag nakatakda sa default nitong true ang enable_metrics, nire-record ng instance mo ang engine errors sa /stats/errors, at inililista ng /preferences kung aling mga engine ang kasalukuyang sumasagot. Kung puno ang /stats/errors at walang searx.limiter lines sa log, hindi limiter ang problema mo.
I-pin ang version bago mag-debug
Dalawang file ang upstream container setup.
mkdir -p ./searxng/core-config/
cd ./searxng/
curl -fsSL \
-O https://raw.githubusercontent.com/searxng/searxng/master/container/docker-compose.yml \
-O https://raw.githubusercontent.com/searxng/searxng/master/container/.env.example
cp -i .env.example .envKinukuha ng compose file ang docker.io/searxng/searxng:${SEARXNG_VERSION:-latest}. Kapag unset ang variable, nangangahulugan ito ng latest, at ang latest ay nangangahulugang magbabago ang instance sa susunod na docker compose pull. Dahil dito, maaaring hindi na tumugma ang setting na gumana noong nakaraang linggo sa code na nagbabasa nito. May date at commit ang mga SearXNG tag. Ang halimbawang tag sa upstream .env.example noong October 2026 ay 2026.3.25-541c6c3cb, kaya magtakda ng aktuwal na value sa .env:
SEARXNG_VERSION=2026.3.25-541c6c3cbSuriin ang mga published tag at i-pin ang release na aktuwal mong sinubukan. Pagkatapos, mag-debug gamit ang fixed target. Nasa parehong .env file ang iyong secret key, kaya basahin ang kung paano gumagana ang env files at secrets sa Docker Compose bago mo i-commit ang directory na iyon kahit saan.
Kailangan ng limiter ang Valkey para gumana
Binibilang ng limiter ang mga request ng bawat client, at kailangang maibahagi ang mga bilang na ito sa mga worker process. Ang store na ito ay Valkey, ang minamanatiling fork ng Redis. Tinatawag ng mga lumang SearXNG guide ang setting na ito na redis:. Binabasa ng kasalukuyang releases ang valkey:, kaya kunin ang key name mula sa kasalukuyang documentation sa halip na sa lumang post. May ilang page na mas luma pa at tungkol sa Searx, hindi sa SearXNG. Magkaibang codebase ang mga ito at magkaiba rin ang limiter. Kaya tukuyin kung para sa alin sa dalawang project isinulat ang page bago kopyahin ang config block mula rito.
use_default_settings: true
server:
secret_key: "change-this-value"
limiter: true
public_instance: false
valkey:
url: valkey://searxng-valkey:6379/0May valkey service na ang upstream compose file sa docker.io/valkey/valkey:9-alpine image, sa loob ng container na may pangalang searxng-valkey. Dahil dito, nareresolba ang host name na iyon sa loob ng compose network. Maaari ring itakda ang kaparehong value gamit ang SEARXNG_VALKEY_URL environment variable. Gumagana rin ang Unix socket URL na unix:///path/to/socket.sock?db=0 kapag magkapareho ng host ang SearXNG at Valkey.
Ang mangyayari kapag nawawala ang store ay nakadepende sa isa pang key. Kapag public_instance: false, inilalagay ng limiter sa log ang Valkey error at humihinto, kaya patuloy na nagsi-serve ang instance nang walang anumang rate limiting. Kapag public_instance: true, tinatawag naman ng process ang sys.exit(1), dahil ang bukas na instance na sira ang bot protection ay makakakuha ng CAPTCHA (completely automated public turing test to tell computers and humans apart) mula sa bawat engine sa loob ng isang araw. Kapag paulit-ulit na nagre-restart ang container agad pagkatapos mong itakda ang public_instance: true, ito ang dahilan. Ang huling linya bago ang bawat pag-exit ang tumutukoy sa Valkey.
Ang aktuwal na binibilang ng limiter
Ang datos sa likod ng tsart na ito
[
{
"label": "Burst, normal client",
"max_requests": 15,
"window": "20 seconds"
},
{
"label": "Burst, flagged client",
"max_requests": 2,
"window": "20 seconds"
},
{
"label": "Sustained, normal client",
"max_requests": 150,
"window": "10 minutes"
},
{
"label": "Sustained, flagged client",
"max_requests": 10,
"window": "10 minutes"
},
{
"label": "Any non-HTML format",
"max_requests": 4,
"window": "1 hour"
},
{
"label": "Flagged requests before block",
"max_requests": 3,
"window": "30 days"
}
]Ang karaniwang client ay pinapayagang gumawa ng 15 request sa loob ng 20 segundong burst window at 150 sa loob ng 10 minutong window. Kapag na-flag na suspicious ang isang client, bumababa ito sa 2 bawat burst window. Pinakamahigpit ang huling row: matapos ang 3 na na-flag na request sa loob ng 30 araw na window, nire-redirect ang address na iyon sa start page sa halip na sa search, at sinasabi ng log na BLOCK: too many request from ... in SUSPICIOUS_IP_WINDOW (redirect to /).
Mga constant ang mga numerong ito sa searx/botdetection/ip_limit.py. Hindi ang mga ito settings, at hindi inilalantad ng limiter.toml ang mga ito, kaya kailangang i-edit ang source para mapalitan ang mga ito. Ang kinokontrol naman ng /etc/searxng/limiter.toml ay ang mga address prefix na ginagamit sa pagpapangkat ng mga client, ang listahan ng mga pinagkakatiwalaang proxy, ang optional na link token check, at ang pass at block list.
Nalalapat lamang ang mga na-flag na row kapag naka-on ang link token check, alinman sa pamamagitan ng link_token = true sa limiter.toml o dahil awtomatiko itong ino-on ng public_instance: true. Itinuturing na suspicious ang isang client hanggang sa mag-load ang browser nito ng stylesheet na may random token sa URL, na hindi kailanman ginagawa ng isang script. Kapag naka-off ang link token, na siyang default, lahat ng client ay gumagamit ng mga normal na row.
Mas mahigpit ang header check dahil wala itong hina-flag: agad tinatanggihan ng 429 ang request na pumalya sa alinman sa mga ito. Module ang bawat check sa searx/botdetection/, at tinutukoy sa debug log line ang header na pumalya:
http_accept: hindi naglalaman angAcceptheader ngtext/html.http_accept_encoding: walanggzipodeflatesaAccept-Encodingheader.http_accept_language: walangAccept-Languageheader.http_user_agent: nawawala angUser-Agento tumutugma ito sa kilalang bot pattern.http_sec_fetch: hindi tugma sa ipinapadala ng browser angSec-Fetch-*headers. Tumatakbo lamang ito sa HTTPS request mula sa mga bersyon ng browser na kilalang nagpapadala ng mga ito, at nire-redirect nito ang request sa start page sa halip na tumugon ng 429.
Ipinapadala ng browser ang lahat ng ito. Halos wala sa mga ito ang ipinapadala ng isang simpleng curl call, kaya tinatanggihan agad sa unang pagsubok ang isang manu-manong ginawang test request habang gumagana ang parehong search sa browser tab. Kaya normal na resulta ang “gumagana sa browser ko, pero nakakakuha ng 429 ang script ko,” hindi ito isang misteryo.
Sa likod ng reverse proxy, sabay-sabay bina-block ng limiter ang lahat
Ito ang pinakakaraniwang paraan para masira ang gumaganang instance. Kinukuha ng SearXNG ang client address mula sa unang untrusted IP sa X-Forwarded-For, at kung wala roon ay gumagamit ng X-Real-IP. Kung wala pa rin, ginagamit nito ang address na nagbukas ng connection. Ang pagtitiwala sa mga header na ito ay tinutukoy ng trusted_proxies sa limiter.toml. Sinasabi sa botdetection documentation na hindi pinapansin ang trusted_proxies kapag X-Real-IP lang ang naka-set, pero ang code sa searx/botdetection/trusted_proxies.py, na sinuri noong 17 October 2026, ay nagtatanggal sa dalawang header kapag hindi trusted ang connecting address. Kaya hindi malalampasan ang listahan sa pamamagitan ng pagpapadala lamang ng X-Real-IP.
Kung wala sa listahang iyon ang address ng proxy mo, hindi pinapansin ang mga header at dumarating ang bawat visitor na may address ng proxy. Iisa ang counter nilang lahat, kaya sabay-sabay na bina-block ang buong site kapag lumampas ang kabuuan sa 150 requests sa loob ng 10 minuto. Kapag ilang beses nag-reload ng results page ang isang user, maaari nitong ma-block ang lahat.
Mas mapanganib ang labis na pagtitiwala. Kung may nakalistang public range, maaaring magpadala ang sinumang visitor ng sarili nilang X-Forwarded-For header at pumili ng bagong identity sa bawat request. Dahil dito, napapatay ang limiter para sa sinumang nakaaalam na subukan ito. Ilista lamang ang address kung saan kumokonekta ang sarili mong proxy. Sa Docker, karaniwan itong bridge network sa loob ng 172.16.0.0/12, at naka-comment out ang linyang iyon.
[botdetection]
ipv4_prefix = 32
ipv6_prefix = 48
trusted_proxies = [
'127.0.0.0/8',
'::1',
'172.16.0.0/12',
]Kailangan ding ipadala ng proxy ang mga header. Walang awtomatikong idinadagdag ang Nginx sa mga ito:
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header Connection $http_connection;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}Itinatakda ng Caddy at Traefik ang forwarded headers para sa iyo, kaya sa mga iyon, ang trusted_proxies na bahagi lang ng configuration ang kailangan mo. Tinalakay ang mga trade-off sa pagpili ng reverse proxy para sa self-hosted service. Para i-verify ang alinmang setup, i-on ang debug, magsagawa ng isang search mula sa phone mo gamit ang mobile data, at tiyaking ang network sa log line ay address ng phone mo, hindi ng proxy.
May apat na API request bawat oras ang agent mo
Naka-disable bilang default ang JSON output, kaya kailangan itong idagdag sa agent:
search:
formats:
- html
- jsonBasahin muli ang row ng chart. Ang bawat request na humihingi ng format maliban sa HTML ay binibilang sa sarili nitong window: 4 request bawat 1 hour, para sa bawat address. Mauubos ito ng isang research agent sa iisang task, at magbabalik ng 429 ang bawat kasunod na call. Hindi opsyon ang pagtaas ng limit dahil nasa source ang value.
Ang maayos na fix ay sabihin sa limiter na hindi stranger ang client na ito. Idagdag ang address nito sa pass list sa limiter.toml:
[botdetection.ip_lists]
block_ip = []
pass_ip = [
'10.8.0.0/24',
]
pass_searxng_org = trueNangunguna ang pass_ip sa lahat ng ibang method, kaya nilalampasan din ng allowlisted client ang mga header check at gumagana ang isang bare na curl call. Panatilihing pinakamaliit ang range na maaari, at mas piliin ang VPN subnet o container network kaysa sa anumang routable network. Ang isa pang maayos na fix ay ganap na alisin ang agent sa public path: ituro ito sa container address sa internal network, kung saan hindi nakikita ng proxy at limiter nito ang traffic. Saklaw ng pagbibigay sa AI agent ng SearXNG search skill ang pag-configure nito.
Iwasang ituro ang agent sa public instance na pinapatakbo ng ibang tao. Ito ang pinakamabilis na paraan para ma-block ng upstream engine ang IP address ng isang volunteer. Ito rin ang dahilan kung bakit naka-disable bilang default ang JSON format.
Kapag ang engines ang humaharang sa iyo
Ang datos sa likod ng tsart na ito
[
{
"label": "SearxEngineTooManyRequests",
"suspended_seconds": 180,
"roughly": "3 minutes"
},
{
"label": "SearxEngineAccessDenied",
"suspended_seconds": 180,
"roughly": "3 minutes"
},
{
"label": "SearxEngineCaptcha",
"suspended_seconds": 3600,
"roughly": "1 hour"
},
{
"label": "recaptcha_SearxEngineCaptcha",
"suspended_seconds": 604800,
"roughly": "7 days"
},
{
"label": "cf_SearxEngineCaptcha",
"suspended_seconds": 1296000,
"roughly": "15 days"
}
]Kapag nagbalik ang isang engine ng sarili nitong 429 o CAPTCHA page, naglalabas ang SearXNG ng pinangalanang exception at pansamantalang hindi na ito tinatanong. Hindi makikita ng iyong mga visitor ang 429 na iyon: magbabalik pa rin ang search ng normal na results page, ngunit wala ang engine na iyon. Kapag too many requests ang sagot, masususpinde ito nang 180 segundo, at ganoon din katagal ang access-denied na sagot para sa 3 minutes. Ang plain CAPTCHA ay nagsususpinde rito nang 1 hour. Ang CAPTCHA na inihatid sa pamamagitan ng Cloudflare ay nagsususpinde rito nang 15 days, ang pinakamahabang default sa listahan, dahil ipinapahiwatig ng sagot na nasa edge ang block at walang maitutulong ang muling pag-request. Nagbabago ang susunod na hakbang depende sa tatlong CAPTCHA row kung saan napunta ang iyong request, at may sarili ring set ng mga pag-aayos ang mga CAPTCHA error kapag alam mo na kung aling exception ang na-record ng iyong instance.
Ito ang mga value sa searx/settings.yml na kasama ng SearXNG, at sinuri noong 17 October 2026. Nagpapakita pa rin ang settings documentation ng mas luma at mas mahahabang value: one hour para sa too many requests, at one day para sa access denied at plain CAPTCHA. Kaya mas dapat pagkatiwalaan ang file na aktuwal na nilo-load ng iyong instance kaysa sa page na nagbabanggit ng mga value na iyon.
Iba ang settings para sa mga ordinaryong failure. Kapag nag-timeout o nabigo ang connection, masususpinde ang engine nang search.ban_time_on_fail segundo, na 5 bilang default, at hindi kailanman lalampas sa search.max_ban_time_on_fail, na 120 bilang default. Nire-record ang parse error sa /stats/errors, ngunit hindi nito sinusususpinde ang engine. Kaya awtomatikong nakakabawi sa loob ng ilang segundo ang mabagal na engine, samantalang mawawala nang isang oras o higit pa ang engine na naghatid ng CAPTCHA. Ipinapaliwanag ng pagkakaibang ito ang isang sintomas na iniuulat ng mga user bilang random: maayos ang results, tapos biglang nawawala nang isang oras sa bawat pagkakataon ang results mula sa isang engine.
Sulit ayusin ang timeouts bago manisi ng sinuman. Ang default na request_timeout ay 3.0 seconds, na maaaring masyadong maikli para sa maliit na VPS na malayo sa pinakamalapit na edge server ng isang engine.
outgoing:
request_timeout: 3.5
max_request_timeout: 10.0
engines:
- name: bing
timeout: 5.0Ang request_timeout ang default para sa bawat engine, ang max_request_timeout ang maximum, at maaaring magkaroon ang isang engine ng sarili nitong timeout. Kapag tinaasan ang mga value na ito, kapalit nito ang mas mataas na page latency para sa mas kaunting failure. Kaya dagdagan ito nang tig-kalahating segundo at obserbahan ang /stats/errors sa halip na agad itong itaas sa 10.
Kung tunay na hinaharangan ng isang engine ang iyong address, alisin ito. Naghihintay ang bawat search sa pinakamabagal na engine, kaya nagdudulot lamang ng latency ang pagpapanatili sa isang permanenteng suspended na engine at wala itong ibinabalik na results.
use_default_settings:
engines:
remove:
- googleIlapat ang mga pagbabago gamit ang docker compose restart core, pagkatapos ay magsagawa ng ilang search at i-reload ang /stats/errors. Kung blangko ang page matapos ang limang minutong aktuwal na paggamit, gumana ang pagbabago.
Ituturing na bot ang IP ng datacentre
Ang address ng VPS mo ay kabilang sa isang hosting range, at itinuturing ng malalaking search engine na automation ang mga range na ito. May ilang engine na nagpapakita ng CAPTCHA sa bawat request mula sa ganoong address, gaano man kaayos ang headers o kabagal ang request rate. Walang setting sa settings.yml na makakapagpabago sa pagtatayang iyon. Bahagi rin ng privacy trade-off sa self-hosting ang pagkakita ng mga engine sa server mo sa halip na sa taong nagta-type ng query, kaya sulit basahin ang kung ano talaga ang itinatago ng SearXNG bago mo ipalagay na mas malawak ang saklaw nito.
Ang maaari mong baguhin ay kung aling mga engine ang gagamitin mo at kung ililista sa publiko ang instance mo. Ang private instance na ginagamit ng isang household ay bihirang ma-trigger ang mga mekanismong ito. Ang public instance sa hosting IP ay makakaranas ng suspensions sa mga pinakahigpit na engine, at normal na kalagayan ito ng software sa halip na problema sa config mo. Maaaring i-route ng SearXNG ang mga request sa engine sa pamamagitan ng proxy gamit ang outgoing.proxies o outgoing.using_tor_proxy, na inililipat ang traffic sa ibang address. Mas mababa ang score ng exit node at murang proxy pool kaysa sa hosting range, kaya asahan mong mas lalala ang mga resulta kapag ginawa mo iyon.
Subaybayan ang instance para ikaw ang unang makaalam
Sumasagot ang SearXNG sa port nito kahit naka-suspend ang lahat ng engine. Kaya mananatiling green ang uptime check na status code lamang ang sinusubaybayan kahit walang ibinabalik ang instance. Suriin ang content. Mag-request ng aktuwal na search at maghanap ng salitang inaasahan mo sa response body. Eksaktong ginagawa ito ng keyword monitoring sa Uptime Kuma nang walang karagdagang tooling. Subaybayan din ang /stats/errors pagkatapos ng bawat version bump dahil nagbabago ang HTML ng mga engine at maaaring masira ang parser nang walang kinalaman sa rate limit.
FAQ
Bakit 429 ang ibinabalik ng SearXNG sa bawat visitor matapos itong ilagay sa likod ng reverse proxy?
Dahil binibilang ng limiter ang proxy bilang client. Binabasa lamang ng SearXNG ang X-Forwarded-For kapag nakalista ang connecting address sa trusted_proxies sa /etc/searxng/limiter.toml. Kung hindi ito nakalista, iisang counter ang ginagamit ng lahat ng visitor at sabay-sabay nilang nalalampasan ang limit na 150 requests kada 10 minuto. Idagdag ang address kung saan kumokonekta ang proxy. Sa Docker, karaniwan itong bridge range na 172.16.0.0/12. Tiyakin ding ipinapadala ng proxy ang X-Real-IP at X-Forwarded-For. Huwag kailanman maglista ng range na hindi mo kontrolado, dahil kapag pinagkakatiwalaan ang network na iyon, maaaring itakda ng sinumang visitor ang header na iyon at pumili ng bagong identity sa bawat request.
Ilang API request kada oras ang pinapayagan ng SearXNG limiter?
Apat bawat IP address kada oras. Ang bawat request na humihingi ng format maliban sa HTML ay binibilang sa hiwalay na one-hour window. Ang limit na iyon ay nakatakda sa searx/botdetection/ip_limit.py, hindi sa limiter.toml, kaya hindi ito maitataas mula sa config. Nalalampasan ito ng isang agent o script sa iisang task. Idagdag ang address ng client sa pass_ip sa limiter.toml, o i-access ang instance sa internal network kung saan hindi nakikita ng limiter ang request.
Bakit walang laman ang search results ko at walang 429 error?
Ang mga engine ang tumatanggi sa server mo, hindi ang mga user mo. Buksan ang /stats/errors sa sarili mong instance. Nakalista rito ang bawat engine na nag-fail at ang dahilan. Ibig sabihin ng CAPTCHA o access-denied entry na bina-block ng engine na iyon ang IP address ng server mo. Pagkatapos, sinususpinde ng SearXNG ang engine: nang tatlong minuto matapos ang sagot na too-many-requests o access-denied, nang isang oras matapos ang plain CAPTCHA, at nang isang linggo o higit pa matapos ang Google o Cloudflare CAPTCHA. Walang local setting na makapag-aalis ng upstream block. Alisin ang mga engine na nagba-block sa address mo at panatilihin ang mga engine na sumasagot.
Dapat ko bang i-enable ang limiter sa isang private instance?
Kung ikaw lamang ang nakaka-access sa instance, iwanang naka-disable ang limiter: false. Nagdaragdag ito ng Valkey dependency at bina-block nito ang sarili mong scripts, kahit wala kang traffic na kailangang protektahan. I-enable ito sa sandaling magkaroon ng public address ang instance, kasama ang public_instance: true. Sadyang ganito ang pares na iyon: kapag naka-enable ang public_instance: true ngunit walang gumaganang Valkey, lalabas ang process na may status 1 sa halip na tumakbo nang walang proteksiyon.