SSD Nodes Learn Hosting plans →
Mga Gabay Matt ConnorNi Matt Connor · Na-update 2026-09-05

Paano Ayusin ang SearXNG 429 Errors at Rate Limits

May dalawang sanhi ng SearXNG 429: sariling limiter o pag-block ng search engine sa server IP. Alamin sa log kung alin ang problema bago magbago ng setting.

Bakit nagbabalik ang SearXNG ng 429 errors

Ang isang self-hosted SearXNG instance ay nagbabalik ng 429 errors dahil sa dalawang magkahiwalay na dahilan. Karaniwang hindi ang rate limit na inaakala mo ang kailangang ayusin. Ang unang dahilan ay lokal: nagpasya ang sariling limiter ng SearXNG na galing sa bot ang request, kaya sumagot ito ng Too Many Requests na may status na 429. Ang ikalawang dahilan ay upstream: tinanggihan ng isang search engine ang IP address ng server mo. Sa mga user, lumalabas ito bilang results page na may mga nawawalang bahagi, hindi bilang 429.

Walang iisang fix para sa dalawang sitwasyon. Iyo ang limiter, kaya maaari mo itong baguhin. Sa panig ng Google nangyayari ang upstream blocking, kaya walang setting sa iyong settings.yml ang makakaalis nito. Sinasabi 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 SearXNG instance sa sarili mong VPS. Ang bawat setting name sa ibaba ay mula sa kasalukuyang upstream documentation at source, na sinuri noong August 2026.

Basahin ang log bago baguhin ang isang setting

Ulitin ang problema habang nakabukas ang log window.

cd ./searxng/
docker compose logs -f searxng-core

Ang mga mensahe ng limiter ay nagmumula sa logger na pinangalanang searx.limiter, at naglalaman ang mga ito ng IP address. Ang hit sa blocklist ay nakasulat bilang BLOCK 203.0.113.10: matched BLOCKLIST, habang ang hit sa allowlist ay nakasulat bilang PASS 203.0.113.10: matched PASSLIST. Kung hindi maabot ng limiter ang counter store nito, nakasaad sa log ang The limiter requires Valkey, please consult the documentation. Ibig sabihin, 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: true

Magdaragdag ang log ng mga linyang may anyong NOT OK (http_accept_language) sa tabi ng client network. Nakasaad dito kung aling check ang nabigo. I-off itong muli pagkatapos, dahil sinasabi ng upstream na huwag magpatakbo ng deployed instance na naka-on ang debug.

Ibang-iba ang anyo ng mga engine failure. Engine ang binabanggit ng mga ito sa halip na IP, at timeout ang pinakakaraniwang error:

HTTP requests timeout (search duration : 3.1 s, timeout: 3.0 s)

May page din para rito. Kapag nananatili sa default na true ang enable_metrics, itinatala ng iyong instance ang mga engine error sa /stats/errors, at inililista ng /preferences kung aling mga engine ang kasalukuyang sumasagot. Kung puno ang /stats/errors at walang searx.limiter na linya sa log, hindi limiter ang problema.

I-lock ang version bago mag-debug ng anuman

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 .env

Kinukuha ng compose file ang docker.io/searxng/searxng:${SEARXNG_VERSION:-latest}. Ang unset na variable ay nangangahulugang latest, at ang latest ay nangangahulugang nagbabago ang instance sa susunod na docker compose pull. Dahil dito, maaaring tumigil sa pagtutugma sa code na nagbabasa rito ang setting na gumana noong nakaraang linggo. May petsa at commit ang mga SearXNG tag. Ang example tag sa upstream .env.example noong August 2026 ay 2026.3.25-541c6c3cb, kaya magtakda ng aktuwal na value sa .env:

SEARXNG_VERSION=2026.3.25-541c6c3cb

Suriin ang mga published tag at i-pin ang release na aktuwal mong sinubukan, saka mag-debug gamit ang fixed target. Nasa parehong .env file ang iyong secret key, kaya basahin ang kung paano gumagana ang env file at secret sa Docker Compose bago mo i-commit ang directory na iyon saanman.

Kailangan ng limiter ang Valkey; kung wala ito, hindi ito tatakbo

Binibilang ng limiter ang mga request mula sa bawat client. Kailangang maibahagi ang mga bilang na ito sa lahat ng worker process. Ang store na ito ay Valkey, ang pinapanatiling fork ng Redis. Tinatawag ng mga lumang gabay para sa SearXNG ang setting na ito na redis:. Binabasa ng mga kasalukuyang release ang valkey:, kaya kunin ang key name mula sa kasalukuyang documentation at hindi sa lumang post. May ilang page na mas luma pa at inilalarawan ang Searx sa halip na SearXNG. Magkaibang codebase ang mga ito at magkaiba rin ang limiter, kaya tukuyin kung para sa alin sa dalawang project isinulat ang page bago kumopya ng 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/0

May searxng-valkey service na ang upstream compose file, na tumatakbo sa docker.io/valkey/valkey:9-alpine image. Dahil dito, nareresolba ang host name na iyon sa loob ng compose network. Maaari ring itakda ang parehong value gamit ang SEARXNG_VALKEY_URL environment variable. Gumagana rin ang Unix socket URL (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, ila-log ng limiter ang Valkey error at hihinto ito. Magpapatuloy ang instance sa pag-serve nang walang rate limiting. Kapag public_instance: true, sys.exit(1) naman ang tinatawag ng process. Ito ay dahil ang open instance na may sirang 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. Ganito ang nangyayari kapag paulit-ulit na nagre-restart ang container pagkatapos mong itakda ang public_instance: true. Tinutukoy ng huling line bago ang bawat pag-exit ang Valkey.

Ano talaga ang binibilang ng limiter

ChartSearXNG limiter: requests allowed per client IP, defaults in ip_limit.py
The data behind this chart
[
  {
    "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 normal na client ay nakakagawa ng 15 request sa loob ng 20 second burst window at 150 sa loob ng 10 minute window. Kapag na-flag na suspicious ang isang request, bumababa sa 2 bawat burst window ang limit para sa parehong client. Pinakamahigpit ang huling row: matapos ang 3 na na-flag na request sa loob ng 30 day window, nire-redirect ang address na iyon sa start page sa halip na payagang mag-search, at sinasabi ng log na BLOCK: too many request from ... in SUSPICIOUS_IP_WINDOW (redirect to /).

Constants ang mga numerong ito sa searx/botdetection/ip_limit.py. Hindi ang mga ito mga setting, at hindi inilalantad ng limiter.toml ang mga ito, kaya kailangang i-edit ang source para baguhin 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 trusted proxy, ang optional na link token check, at ang mga pass at block list.

Nafi-flag na suspicious ang isang request batay sa mga header check. May pangalan ang bawat check, at makikita mo ang mga pangalang ito sa debug log:

  • http_accept: hindi naglalaman ang Accept header ng text/html.
  • http_accept_encoding: wala sa Accept-Encoding header ang gzip o deflate.
  • http_accept_language: walang Accept-Language header.
  • http_connection: nakatakda ang Connection header sa close.
  • http_user_agent: nawawala ang User-Agent o tumutugma ito sa isang kilalang bot pattern.
  • http_sec_fetch: hindi tugma sa ipinapadala ng browser ang Sec-Fetch-Mode o Sec-Fetch-Dest header.

Ipinapadala ng browser ang lahat ng ito. Halos wala sa mga ito ang ipinapadala ng isang simpleng curl call, kaya nafi-flag sa unang pagsubok ang isang manually written na test request habang gumagana ang parehong search sa browser tab. Kaya normal na resulta, at hindi misteryo, ang “gumagana sa browser ko, pero 429 ang nakukuha ng script ko.”

Sa likod ng reverse proxy, sabay-sabay na bina-block ng limiter ang lahat

Ito ang pinakakaraniwang paraan para masira ang gumaganang instance. Kinukuha ng SearXNG ang client address mula sa unang hindi pinagkakatiwalaang IP sa X-Forwarded-For, pagkatapos ay gumagamit ng X-Real-IP bilang fallback, at muli itong nagfa-fallback sa address na nagbukas ng connection. Ang pagtiwala sa mga header na iyon ay itinatakda ng trusted_proxies sa limiter.toml.

Kung wala sa listahang iyon ang address ng proxy mo, binabalewala ang mga header at dumarating ang bawat visitor na may address ng proxy. Dahil dito, iisang counter ang ginagamit nila. Kaya sabay-sabay na bina-block ang buong site kapag lumampas ang kabuuan sa 150 requests sa loob ng 10 minuto. Kahit ilang pag-reload lang ng isang user sa results page ay maaaring magpabagsak sa access ng 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, nawawala ang bisa ng limiter para sa sinumang nakaaalam kung paano ito subukan. Ilista lamang ang address na ginagamit ng sarili mong proxy para kumonekta. 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;
}

Awtomatikong sine-set 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 ma-verify ang alinmang setup, i-on ang debug, isang beses na magsagawa ng search mula sa phone gamit ang mobile data, at tiyaking ang network sa log line ay address ng phone mo, hindi address 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
    - json

Basahin 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 = true

Nangunguna 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 mga engine ang humaharang sa iyo

ChartHow long SearXNG suspends an engine, search.suspended_times defaults
The data behind this chart
[
  {
    "label": "SearxEngineTooManyRequests",
    "suspended_seconds": 3600,
    "roughly": "1 hour"
  },
  {
    "label": "SearxEngineAccessDenied",
    "suspended_seconds": 86400,
    "roughly": "1 day"
  },
  {
    "label": "SearxEngineCaptcha",
    "suspended_seconds": 86400,
    "roughly": "1 day"
  },
  {
    "label": "recaptcha_SearxEngineCaptcha",
    "suspended_seconds": 604800,
    "roughly": "7 days"
  },
  {
    "label": "cf_SearxEngineCaptcha",
    "suspended_seconds": 1296000,
    "roughly": "15 days"
  }
]

Kapag sumagot ang isang engine gamit ang sarili nitong 429 o CAPTCHA page, nagtataas ang SearXNG ng pinangalanang exception at pansamantalang hindi na nagtatanong sa engine na iyon. Sinususpinde ito ng sagot na too-many-requests nang 3600 segundo. Sinususpinde ito ng plain CAPTCHA o access-denied na sagot nang 1 day. Kapag CAPTCHA ito na inihatid sa pamamagitan ng Cloudflare, sinususpinde ito nang 15 days, ang pinakamahabang default sa listahan, dahil ipinapahiwatig ng sagot na iyon na nasa edge ang block at walang maitutulong ang pag-retry. Nakaaapekto sa susunod na makabuluhang hakbang kung alin sa tatlong CAPTCHA row ang napuntahan mo, at may sarili ring hanay ng mga pag-aayos ang CAPTCHA errors kapag alam mo na kung aling exception ang naitala ng instance mo.

Iba ang mga setting para sa karaniwang failure. Ang timeout o parse error ay nagsu-suspend sa engine sa maikling panahong nakabatay sa search.ban_time_on_fail, na may default na 5 segundo at may maximum na 120 segundo ayon sa search.max_ban_time_on_fail. Kaya awtomatikong makakabawi sa loob ng ilang minuto ang mabagal na engine, samantalang mawawala nang ilang oras ang naka-block na engine. Ipinapaliwanag ng pagkakaibang ito ang sintomas na iniuulat ng mga tao bilang random: maayos ang mga resulta, tapos biglang nawawala ang mga resulta mula sa isang engine sa natitirang bahagi ng hapon.

Dapat ayusin muna ang mga timeout bago sisihin ang alinmang panig. Ang default na request_timeout ay 2.0 segundo, na maikli para sa isang maliit na VPS na malayo sa pinakamalapit na edge server ng engine.

outgoing:
  request_timeout: 3.0
  max_request_timeout: 10.0
engines:
  - name: bing
    timeout: 5.0

Ang request_timeout ang default para sa bawat engine, ang max_request_timeout ang maximum, at maaaring magkaroon ang isang engine ng sarili nitong timeout. Kapalit ng mas kaunting failure ang pagtaas sa mga halagang ito, ngunit tataas ang latency ng page. Dagdagan ito nang tig-kalahating segundo at obserbahan ang /stats/errors sa halip na agad itong itaas sa 10.

Para sa engine na talagang nagba-block sa iyong address, alisin ito. Naghihintay ang bawat search sa pinakamabagal na engine, kaya nagdudulot lamang ng latency at walang ibinabalik ang isang engine na permanenteng naka-suspend.

use_default_settings:
  engines:
    remove:
      - google

Ilapat ang mga pagbabago gamit ang docker compose restart searxng-core, pagkatapos ay magsagawa ng ilang search at i-reload ang /stats/errors. Kung walang laman ang page makalipas ang limang minuto ng 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 nagbabalik ang SearXNG ng 429 sa bawat bisita matapos ko 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 bisita, kaya sabay-sabay nilang nalalampasan ang limitasyong 150 requests bawat 10 minuto. Idagdag ang address kung saan kumokonekta ang proxy. Sa Docker, karaniwan itong bridge range na 172.16.0.0/12. Tiyaking ipinapadala rin ng proxy ang X-Real-IP at X-Forwarded-For. Huwag kailanman maglista ng range na hindi mo kontrolado, dahil maaaring magtakda ng header na iyon ang sinumang bisita sa isang trusted network at pumili ng bagong identity sa bawat request.

Ilang API request bawat 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 limitasyong iyon ay nakatakda sa searx/botdetection/ip_limit.py, hindi sa limiter.toml, kaya hindi ito maaaring taasan mula sa config. Malalampasan 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 mga search result 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. Nakasaad dito kung aling engine ang nag-fail at kung bakit. Ibig sabihin ng CAPTCHA o access-denied entry na na-block ng engine ang IP address ng server mo. Pagkatapos, sinususpinde ng SearXNG ang engine nang isang oras kapag too-many-requests ang sagot at nang isang araw kapag CAPTCHA ang sagot. Walang local setting na makakapag-alis 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 private instance?

Kung ikaw lamang ang nakaka-access sa instance, iwanang limiter: false. Nagdaragdag ito ng Valkey dependency at bina-block nito ang sarili mong mga script, kahit wala namang traffic na kailangan nitong protektahan. I-enable ito kapag nagkaroon ng public address ang instance, kasama ang public_instance: true. Sadyang magkasama ang dalawang setting na ito: 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.