SearXNG 429 Error और Rate Limit कैसे ठीक करें
SearXNG में 429 error के दो मुख्य कारण हैं। या तो आपका अपना limiter सक्रिय है या search engine ने आपके IP को ब्लॉक किया है। लॉग देखकर सही समस्या पहचानें और उसे फिक्स करें।
SearXNG 429 errors क्यों देता है
एक self-hosted SearXNG instance दो असंबंधित कारणों से 429 errors देता है, और जिस rate limit को आपको ठीक करने की आवश्यकता है, वह आमतौर पर वह नहीं होती जिसे आप मान रहे होते हैं। पहला कारण स्थानीय है: SearXNG के अपने limiter ने यह तय किया कि request एक bot से आई है और Too Many Requests के साथ 429 status में उत्तर दिया। दूसरा कारण upstream है: एक search engine ने आपके server के IP address को मना कर दिया है, जो आपके users तक परिणाम पृष्ठ पर गायब जानकारी के रूप में पहुँचता है, न कि 429 के रूप में।
दोनों स्थितियों का कोई साझा समाधान नहीं है। Limiter आपका है, इसलिए आप इसे बदल सकते हैं। Upstream blocking Google की तरफ से होती है, इसलिए आपके settings.yml में कुछ भी इसे नहीं हटाएगा। Log आपको लगभग एक मिनट में बता देता है कि आपके पास कौन सी समस्या है, इसलिए वहीं से शुरुआत करें।
यह मार्गदर्शिका अपने VPS पर self-hosted SearXNG instance में वर्णित container install को मानकर चलती है। नीचे दिए गए सभी setting नाम वर्तमान upstream documentation और source से लिए गए हैं, जिन्हें अगस्त 2026 में जाँचा गया है।
सेटिंग बदलने से पहले लॉग पढ़ें
लॉग विंडो खुली रखकर समस्या को दोबारा उत्पन्न करें।
cd ./searxng/
docker compose logs -f searxng-coreLimiter संदेश searx.limiter नामक लॉगर से आते हैं और उनमें एक IP address का उल्लेख होता है। Blocklist हिट होने पर BLOCK 203.0.113.10: matched BLOCKLIST दिखाई देता है, और Allowlist हिट होने पर PASS 203.0.113.10: matched PASSLIST दिखाई देता है। यदि Limiter अपने counter store तक नहीं पहुँच पाता है, तो लॉग में The limiter requires Valkey, please consult the documentation दिखाई देता है, जिसका अर्थ है कि कुछ भी count नहीं किया जा रहा है।
प्रत्येक व्यक्तिगत bot check को debug level पर लॉग किया जाता है, इसलिए आप इसे डिफ़ॉल्ट रूप से नहीं देख पाएंगे। एक परीक्षण के लिए settings.yml में debug को चालू करें:
general:
debug: trueइसके बाद लॉग में client network के बगल में NOT OK (http_accept_language) जैसी लाइनें जुड़ जाती हैं, जिनमें विफल हुए check का नाम होता है। बाद में इसे फिर से बंद कर दें, क्योंकि upstream आपको deployed instance को debug मोड में न चलाने की सलाह देता है।
Engine की विफलताएं ऐसी नहीं दिखती हैं। वे IP के बजाय एक engine का नाम लेती हैं, और सबसे आम समस्या timeout है:
HTTP requests timeout (search duration : 3.1 s, timeout: 3.0 s)इसके लिए एक पेज भी है। यदि enable_metrics को इसके डिफ़ॉल्ट मान true पर छोड़ दिया जाए, तो आपका instance /stats/errors पर engine errors को रिकॉर्ड करता है, और /preferences यह सूचीबद्ध करता है कि कौन से engines वर्तमान में उत्तर दे रहे हैं। यदि /stats/errors भरा हुआ है और लॉग में कोई searx.limiter लाइनें नहीं हैं, तो समस्या Limiter के साथ नहीं है।
किसी भी समस्या को डीबग करने से पहले version को पिन करें
अपस्ट्रीम कंटेनर सेटअप दो फाइलों से बना है।
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 .envCompose फाइल docker.io/searxng/searxng:${SEARXNG_VERSION:-latest} को पुल करती है। एक unset variable का मतलब latest होता है, और latest का मतलब है कि अगले docker compose pull पर instance आपके नियंत्रण के बिना बदल जाएगा। इस कारण, जो सेटिंग पिछले हफ्ते काम कर रही थी, वह उस कोड के साथ मेल खाना बंद कर सकती है जो उसे पढ़ता है। SearXNG टैग्स में एक तारीख और एक कमिट (commit) शामिल होती है। अगस्त 2026 तक अपस्ट्रीम .env.example में उदाहरण टैग 2026.3.25-541c6c3cb है, इसलिए .env में एक वास्तविक टैग सेट करें:
SEARXNG_VERSION=2026.3.25-541c6c3cbप्रकाशित टैग्स की जाँच करें और जिस रिलीज को आपने वास्तव में टेस्ट किया है उसे पिन करें, फिर एक निश्चित टारगेट के आधार पर डीबग करें। वही .env फाइल आपकी secret key को रखती है, इसलिए उस डायरेक्टरी को कहीं भी कमिट करने से पहले Docker Compose में env फाइलें और सीक्रेट्स कैसे काम करते हैं पढ़ें।
Limiter को Valkey की आवश्यकता है, अन्यथा यह नहीं चलेगा
Limiter प्रत्येक client के अनुरोधों की संख्या गिनता है, और इन counts को worker processes के बीच साझा करना आवश्यक है। यह store Redis के maintained fork Valkey में होता है। पुराने SearXNG guides इस setting को redis: कहते हैं। Current releases valkey: को पढ़ते हैं, इसलिए key name किसी पुराने post के बजाय current documentation से copy करें। इनमें से कुछ pages इससे भी पुराने हैं और Searx का वर्णन करते हैं, जो अलग codebase और अलग limiter वाला project है। इसलिए किसी page से config block copy करने से पहले जाँच लें कि वह page दोनों में से किस project के लिए लिखा गया है।
use_default_settings: true
server:
secret_key: "change-this-value"
limiter: true
public_instance: false
valkey:
url: valkey://searxng-valkey:6379/0Upstream compose file पहले से ही docker.io/valkey/valkey:9-alpine image पर एक searxng-valkey service चलाती है, इसलिए वह host name compose network के भीतर resolve हो जाता है। वही मान SEARXNG_VALKEY_URL environment variable के साथ set किया जा सकता है, और जब SearXNG और Valkey एक ही host साझा करते हैं, तो Unix socket URL (unix:///path/to/socket.sock?db=0) काम करता है।
जब store अनुपस्थित हो तो क्या होगा, यह एक अन्य key पर निर्भर करता है। public_instance: false के साथ, limiter Valkey error को log करता है और प्रयास छोड़ देता है, इसलिए instance बिना किसी rate limiting के काम करना जारी रखता है। public_instance: true के साथ, process इसके बजाय sys.exit(1) को call करती है, क्योंकि broken bot protection वाला एक open instance एक दिन के भीतर हर engine से CAPTCHAs (कंप्यूटर और इंसानों के बीच अंतर करने के लिए पूरी तरह से स्वचालित सार्वजनिक ट्यूरिंग परीक्षण) एकत्र कर लेता है। public_instance: true set करने के तुरंत बाद loop में restart होने वाला container यही स्थिति है, और प्रत्येक exit से पहले की अंतिम पंक्ति Valkey का नाम बताती है।
What the limiter actually counts
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"
}
]A normal client gets 15 requests inside a 20 second burst window and 150 inside a 10 minute window. Once a request is flagged as suspicious, the same client drops to 2 per burst window. The last row is the harshest: after 3 flagged requests inside a 30 day window, that address is redirected to the start page instead of searching, and the log says BLOCK: too many request from ... in SUSPICIOUS_IP_WINDOW (redirect to /).
These numbers are constants in searx/botdetection/ip_limit.py. They are not settings, and limiter.toml does not expose them, so changing them means editing the source. What /etc/searxng/limiter.toml does control is the address prefixes used to group clients, the list of trusted proxies, the optional link token check, and the pass and block lists.
A request gets flagged as suspicious by header checks, and each check has a name you will see in the debug log:
http_accept: theAcceptheader does not containtext/html.http_accept_encoding: theAccept-Encodingheader names neithergzipnordeflate.http_accept_language: there is noAccept-Languageheader.http_connection: theConnectionheader is set toclose.http_user_agent: theUser-Agentis missing or matches a known bot pattern.http_sec_fetch: theSec-Fetch-ModeorSec-Fetch-Destheader is not what a browser sends.
A browser sends all of these. A plain curl call sends almost none of them, so a hand-written test request is flagged on its first try while the same search works in a browser tab. That is why "it works in my browser, but my script gets 429" is the normal result rather than a mystery.
Reverse proxy के पीछे होने पर limiter सभी को एक साथ block कर देता है
यह एक कार्यशील instance को खराब करने का सबसे सामान्य तरीका है। SearXNG क्लाइंट का पता X-Forwarded-For में मौजूद पहले untrusted IP से लेता है, फिर X-Real-IP पर वापस जाता है, और अंत में उस पते पर वापस जाता है जिसने connection खोला था। इन headers पर भरोसा करना है या नहीं, यह limiter.toml में मौजूद trusted_proxies द्वारा तय किया जाता है।
यदि आपके proxy का पता उस सूची में नहीं है, तो headers को अनदेखा कर दिया जाता है और हर visitor proxy के पते के साथ आता है। वे सभी एक ही counter साझा करते हैं, इसलिए जैसे ही कुल संख्या 10 मिनट में 150 requests को पार करती है, पूरी साइट एक साथ block हो जाती है। एक user द्वारा results page को कुछ बार reload करने से सभी users का access बंद हो जाता है।
बहुत अधिक भरोसा करना और भी बुरा है। यदि कोई public range सूची में है, तो कोई भी visitor अपना खुद का X-Forwarded-For header भेज सकता है और हर request के लिए एक नई पहचान चुन सकता है, जिससे यह limiter उन सभी के लिए बंद हो जाता है जो ऐसा करना जानते हैं। केवल उसी पते को सूचीबद्ध करें जहाँ से आपका अपना proxy connect होता है। Docker में यह आमतौर पर 172.16.0.0/12 के अंदर एक bridge network होता है, और वह line comment के रूप में दी गई होती है।
[botdetection]
ipv4_prefix = 32
ipv6_prefix = 48
trusted_proxies = [
'127.0.0.0/8',
'::1',
'172.16.0.0/12',
]Proxy को भी headers भेजने होंगे। Nginx अपने आप इनमें से कोई भी header नहीं जोड़ता है:
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;
}Caddy और Traefik आपके लिए forwarded headers set कर देते हैं, इसलिए उनके साथ आपको केवल trusted_proxies वाला हिस्सा पूरा करने की आवश्यकता होती है। इनके फायदे और नुकसान self-hosted service के लिए reverse proxy चुनना में बताए गए हैं। किसी भी setup को verify करने के लिए, debug को on करें, अपने फोन पर mobile data का उपयोग करके एक बार search करें, और log line में network को देखें कि वह proxy का पता न होकर आपके फोन का पता है।
आपका एजेंट प्रति घंटे चार API अनुरोध प्राप्त करता है
JSON आउटपुट डिफ़ॉल्ट रूप से अक्षम होता है, इसलिए एजेंट के लिए इसे जोड़ना आवश्यक है:
search:
formats:
- html
- jsonअब चार्ट की पंक्ति को फिर से पढ़ें। HTML के अलावा किसी अन्य प्रारूप के लिए किया गया कोई भी अनुरोध अपनी स्वयं की विंडो में गिना जाता है: प्रति पता, प्रति 1 hour में 4 अनुरोध। एक रिसर्च एजेंट इसे एक ही कार्य में समाप्त कर देता है, और उसके बाद प्रत्येक कॉल 429 त्रुटि लौटाती है। सीमा बढ़ाना कोई विकल्प नहीं है, क्योंकि यह संख्या सोर्स कोड में निर्धारित है।
इसका सटीक समाधान यह है कि लिमिटर को सूचित करें कि यह क्लाइंट कोई अनजान व्यक्ति नहीं है। इसके पते को limiter.toml में पास लिस्ट में जोड़ें:
[botdetection.ip_lists]
block_ip = []
pass_ip = [
'10.8.0.0/24',
]
pass_searxng_org = truepass_ip की प्राथमिकता अन्य सभी विधियों से अधिक है, इसलिए एक अलाउलिस्टेड क्लाइंट हेडर जांच को भी छोड़ देता है और एक साधारण curl कॉल काम करता है। रेंज को जितना संभव हो उतना छोटा रखें, और किसी भी राउटेबल नेटवर्क के बजाय VPN सबनेट या कंटेनर नेटवर्क को प्राथमिकता दें। दूसरा सटीक समाधान यह है कि एजेंट को सार्वजनिक पथ से पूरी तरह दूर रखें: इसे आंतरिक नेटवर्क पर कंटेनर पते की ओर निर्देशित करें, जहाँ प्रॉक्सी और उसका लिमिटर ट्रैफ़िक को कभी नहीं देखते हैं। इसे सेटअप करने की प्रक्रिया AI एजेंट को SearXNG सर्च स्किल देना में कवर की गई है।
किसी अन्य व्यक्ति द्वारा संचालित सार्वजनिक इंस्टेंस पर एजेंट को निर्देशित करने के विकल्प से बचें। यह किसी स्वयंसेवक के IP पते को अपस्ट्रीम इंजन द्वारा ब्लॉक करवाने का सबसे तेज़ तरीका है, और यही कारण है कि JSON प्रारूप डिफ़ॉल्ट रूप से अक्षम रखा गया है।
जब सर्च इंजन आपको ब्लॉक कर दें
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"
}
]जब कोई engine अपने 429 उत्तर या CAPTCHA page के साथ जवाब देता है, तो SearXNG नामित exception उठाता है और कुछ समय तक उस engine से अनुरोध भेजना रोक देता है। Too-many-requests उत्तर के बाद यह उसे 3600 seconds के लिए suspend करता है। सामान्य CAPTCHA या access-denied उत्तर के बाद यह उसे 1 day के लिए suspend करता है। Cloudflare के माध्यम से दिए गए CAPTCHA के बाद यह उसे 15 days के लिए suspend करता है। यह list में सबसे लंबी default अवधि है, क्योंकि इस उत्तर का अर्थ है कि block edge पर है और दोबारा प्रयास करने से मदद नहीं मिलेगी। आप CAPTCHA की तीन rows में से किस पर पहुँचे हैं, इससे यह बदलता है कि अगला कौन-सा उपाय उपयोगी होगा। यह पता चलने के बाद कि आपके instance ने कौन-सा exception record किया है, CAPTCHA errors के लिए अलग fixes उपलब्ध हैं।
सामान्य विफलताएं अलग सेटिंग्स का उपयोग करती हैं। टाइमआउट या पार्स एरर इंजन को search.ban_time_on_fail से प्राप्त कम समय के लिए निलंबित करते हैं, जो डिफ़ॉल्ट रूप से 5 सेकंड है और search.max_ban_time_on_fail द्वारा अधिकतम 120 सेकंड तक सीमित है। इसलिए, एक धीमा इंजन कुछ ही मिनटों में अपने आप ठीक हो जाता है, जबकि एक ब्लॉक किया गया इंजन घंटों तक अनुपलब्ध रहता है। यह अंतर उस लक्षण की व्याख्या करता है जिसे लोग रैंडम बताते हैं: परिणाम ठीक होते हैं, फिर एक इंजन के परिणाम दोपहर के शेष समय के लिए गायब हो जाते हैं।
किसी पर दोष मढ़ने से पहले टाइमआउट को ठीक करना उचित है। डिफ़ॉल्ट request_timeout 2.0 सेकंड है, जो इंजन के निकटतम एज सर्वर से दूर स्थित एक छोटे VPS के लिए बहुत कम है।
outgoing:
request_timeout: 3.0
max_request_timeout: 10.0
engines:
- name: bing
timeout: 5.0request_timeout हर इंजन के लिए डिफ़ॉल्ट है, max_request_timeout अधिकतम सीमा है, और एक एकल इंजन का अपना timeout हो सकता है। इन्हें बढ़ाने से पेज लेटेंसी के बदले कम विफलताएं मिलती हैं, इसलिए आधे सेकंड के अंतराल में बदलाव करें और सीधे 10 पर जाने के बजाय /stats/errors पर नज़र रखें।
जो इंजन वास्तव में आपके पते को ब्लॉक कर रहा है, उसे हटा दें। प्रत्येक खोज अपने सबसे धीमे इंजन पर निर्भर करती है, इसलिए स्थायी रूप से निलंबित इंजन को बनाए रखने से लेटेंसी बढ़ती है और कोई परिणाम नहीं मिलता।
use_default_settings:
engines:
remove:
- googledocker compose restart searxng-core के साथ बदलाव लागू करें, फिर कुछ खोजें करें और /stats/errors को पुनः लोड करें। पांच मिनट के वास्तविक उपयोग के बाद एक खाली पेज का मतलब है कि बदलाव ने काम किया।
Datacentre IP को bot माना जाएगा
आपका VPS address एक hosting range का हिस्सा है, और बड़े search engines इन ranges को automation के रूप में चिह्नित करते हैं। इनमें से कुछ engines ऐसे address से आने वाली हर request पर CAPTCHA दिखाते हैं, चाहे आपके headers कितने भी सही हों या request की गति कितनी भी धीमी हो। settings.yml में कोई भी setting इस निर्णय को नहीं बदल सकती। यह तथ्य कि search engines को आपकी query टाइप करने वाले व्यक्ति के बजाय आपका सर्वर दिखाई देता है, वही privacy समझौता है जो आपने self-hosting चुनकर किया है। यह मानने से पहले कि SearXNG आपकी पूरी privacy सुरक्षित रखता है, SearXNG वास्तव में कितनी privacy देता है के बारे में पढ़ना उपयोगी होगा।
आप यह बदल सकते हैं कि आप किन engines से जानकारी मांगते हैं और क्या आपका instance सार्वजनिक रूप से सूचीबद्ध है या नहीं। एक household द्वारा उपयोग किया जाने वाला private instance शायद ही कभी किसी समस्या का सामना करता है। hosting IP पर चल रहा एक public instance सबसे सख्त engines द्वारा बार-बार block किया जाएगा, और यह software की कोई खराबी नहीं बल्कि सामान्य स्थिति है। SearXNG, outgoing.proxies या outgoing.using_tor_proxy का उपयोग करके engine requests को proxy के माध्यम से भेज सकता है, जिससे traffic एक अलग address पर चला जाता है। Exit nodes और सस्ते proxy pools की reputation hosting ranges से भी खराब होती है, इसलिए उम्मीद करें कि ऐसा करने से search results की गुणवत्ता और गिर जाएगी।
इंस्टेंस पर नज़र रखें ताकि आपको सबसे पहले पता चले
SearXNG अपने पोर्ट पर तब भी जवाब देता है जब सभी इंजन सस्पेंड (suspended) हों, इसलिए केवल स्टेटस कोड देखने वाला अपटाइम चेक तब भी 'green' रहता है जब इंस्टेंस कोई परिणाम नहीं दे रहा होता। इसके बजाय कंटेंट की जाँच करें: एक वास्तविक सर्च रिक्वेस्ट भेजें और रिस्पॉन्स बॉडी में किसी अपेक्षित शब्द का मिलान करें। Uptime Kuma कीवर्ड मॉनिटरिंग बिना किसी अतिरिक्त टूल के ठीक यही काम करती है। हर वर्जन अपडेट के बाद /stats/errors पर भी नज़र रखें, क्योंकि इंजन अपना HTML बदल देते हैं और बिना किसी रेट लिमिट के भी पार्सर (parser) काम करना बंद कर सकता है।
FAQ
SearXNG को reverse proxy के पीछे रखने के बाद यह हर visitor को 429 error क्यों देता है?
क्योंकि limiter proxy को ही client मानकर गिनती कर रहा है। SearXNG केवल तभी X-Forwarded-For को पढ़ता है जब connecting address /etc/searxng/limiter.toml में trusted_proxies के अंतर्गत सूचीबद्ध हो। यदि यह सूचीबद्ध नहीं है, तो सभी visitors एक ही counter साझा करते हैं और वे सभी मिलकर 10 मिनट में 150 requests की सीमा पार कर लेते हैं। उस address को जोड़ें जहाँ से आपका proxy connect होता है, जो Docker में आमतौर पर bridge range 172.16.0.0/12 होती है, और सुनिश्चित करें कि proxy X-Real-IP और X-Forwarded-For भेजता है। कभी भी ऐसी range को सूचीबद्ध न करें जिसे आप control नहीं करते, क्योंकि एक trusted network किसी भी visitor को वह header set करने और हर request के लिए एक नई identity चुनने की अनुमति देता है।
SearXNG limiter प्रति घंटे कितनी API requests की अनुमति देता है?
प्रति IP address प्रति घंटे चार। HTML के अलावा किसी अन्य format की मांग करने वाली कोई भी request एक अलग एक घंटे की window में गिनी जाती है, और वह सीमा limiter.toml के बजाय searx/botdetection/ip_limit.py में set होती है, इसलिए इसे config से नहीं बढ़ाया जा सकता। एक agent या script इसे एक ही task में pass कर देता है। client के address को limiter.toml में pass_ip में जोड़ें, या instance तक ऐसे internal network के माध्यम से पहुँचें जहाँ limiter कभी request न देख सके।
मेरे search results बिना किसी 429 error के खाली क्यों आते हैं?
engines आपके server को मना कर रहे हैं, आपके users को नहीं। अपने instance पर /stats/errors खोलें: यह उन सभी engines के नाम बताता है जो विफल रहे और क्यों, और CAPTCHA या access-denied entry का मतलब है कि उस engine ने आपके server के IP address को block कर दिया है। SearXNG फिर उस engine को निलंबित कर देता है, too-many-requests उत्तर के बाद एक घंटे के लिए और CAPTCHA के बाद एक दिन के लिए। कोई भी local setting upstream block को नहीं हटा सकती, इसलिए उन engines को हटा दें जो आपके address को block करते हैं और केवल उन्हें रखें जो उत्तर देते हैं।
क्या मुझे private instance पर limiter enable करना चाहिए?
यदि instance तक आपके अलावा कुछ नहीं पहुँचता है, तो limiter: false को रहने दें। यह एक Valkey dependency जोड़ता है और आपकी अपनी scripts को block करता है, और यह ऐसे traffic से सुरक्षा देता है जो आपके पास है ही नहीं। जिस क्षण instance को public address मिले, इसे public_instance: true के साथ enable करें। यह जोड़ी जानबूझकर बनाई गई है: public_instance: true के साथ और बिना काम करने वाले Valkey के, process असुरक्षित चलने के बजाय status 1 के साथ exit हो जाती है।