SearXNG: 429-Fehler und Rate Limits beheben
SearXNG 429-Fehler haben zwei Ursachen: eigener Limiter oder blockierte Server-IP. Prüfen Sie das Log und beheben Sie gezielt die richtige Ursache.
Why SearXNG returns 429 errors
A self-hosted SearXNG instance returns 429 errors for two unrelated reasons, and the rate limit you need to fix is usually not the one you assume. The first reason is local: SearXNG's own limiter decided a request came from a bot and answered Too Many Requests with status 429. The second is upstream: a search engine refused your server's IP address, which reaches your users as a results page with things missing, not as a 429.
The two cases share no fix. The limiter is yours, so you can change it. Upstream blocking happens on Google's side, so nothing in your settings.yml will lift it. The log tells you which one you have in about a minute, so start there.
This guide assumes the container install described in a self-hosted SearXNG instance on your own VPS. Every setting name below comes from current upstream documentation and source, checked in August 2026.
Lesen Sie das Log, bevor Sie eine Einstellung ändern
Reproduzieren Sie das Problem, während ein Log-Fenster geöffnet ist.
cd ./searxng/
docker compose logs -f searxng-coreLimiter-Meldungen stammen vom Logger searx.limiter und enthalten eine IP-Adresse. Ein Treffer in der Blocklist wird als BLOCK 203.0.113.10: matched BLOCKLIST protokolliert, ein Treffer in der Allowlist als PASS 203.0.113.10: matched PASSLIST. Wenn der Limiter seinen Zählerspeicher nicht erreichen kann, enthält das Log die Meldung The limiter requires Valkey, please consult the documentation. Das bedeutet, dass überhaupt nichts gezählt wird.
Jede einzelne Bot-Prüfung wird auf Debug-Level protokolliert und ist daher standardmäßig nicht sichtbar. Aktivieren Sie Debug für einen Test in settings.yml:
general:
debug: trueDas Log enthält dann neben dem Client-Netzwerk Zeilen im Format NOT OK (http_accept_language). Diese benennen die fehlgeschlagene Prüfung. Deaktivieren Sie Debug anschließend wieder, da der Upstream davon abrät, eine bereitgestellte Instanz mit aktiviertem Debug zu betreiben.
Fehler der Engines sehen völlig anders aus. Sie nennen statt einer IP eine Engine. Am häufigsten tritt ein Timeout auf:
HTTP requests timeout (search duration : 3.1 s, timeout: 3.0 s)Dafür gibt es ebenfalls eine Seite. Wenn enable_metrics den Standardwert true hat, protokolliert Ihre Instanz Engine-Fehler in /stats/errors. /preferences zeigt, welche Engines derzeit antworten. Wenn /stats/errors vollständig ist und das Log keine searx.limiter-Zeilen enthält, liegt das Problem nicht beim Limiter.
Version festlegen, bevor Sie mit der Fehlersuche beginnen
Das Container-Setup des Upstream-Projekts besteht aus zwei Dateien.
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 .envDie Compose-Datei ruft docker.io/searxng/searxng:${SEARXNG_VERSION:-latest} ab. Eine nicht gesetzte Variable bedeutet latest. latest bedeutet, dass sich die Instanz beim nächsten docker compose pull unter Ihrer Kontrolle ändert. Eine Einstellung, die letzte Woche funktioniert hat, kann dann nicht mehr zum Code passen, der sie ausliest. SearXNG-Tags enthalten ein Datum und einen Commit. Das Beispiel-Tag im Upstream-.env.example vom August 2026 lautet 2026.3.25-541c6c3cb. Legen Sie daher in .env einen konkreten Wert fest:
SEARXNG_VERSION=2026.3.25-541c6c3cbPrüfen Sie die veröffentlichten Tags und legen Sie das Release fest, das Sie tatsächlich getestet haben. Führen Sie die Fehlersuche anschließend gegen ein unveränderliches Ziel durch. Die gleiche Datei .env enthält Ihren geheimen Schlüssel. Lesen Sie daher wie Env-Dateien und Secrets in Docker Compose funktionieren, bevor Sie dieses Verzeichnis irgendwo committen.
Der Limiter benötigt Valkey, sonst läuft er nicht
Der Limiter zählt Anfragen pro Client. Diese Zähler müssen zwischen Worker-Prozessen gemeinsam genutzt werden. Dafür wird Valkey verwendet, der gepflegte Fork von Redis. In älteren SearXNG-Anleitungen wird diese Einstellung als redis: bezeichnet. Aktuelle Releases lesen valkey:. Übernehmen Sie den Schlüsselnamen daher aus der aktuellen Dokumentation und nicht aus einem älteren Beitrag.
use_default_settings: true
server:
secret_key: "change-this-value"
limiter: true
public_instance: false
valkey:
url: valkey://searxng-valkey:6379/0Die Upstream-Compose-Datei startet bereits einen Dienst searxng-valkey mit dem Image docker.io/valkey/valkey:9-alpine. Dieser Hostname ist daher im Compose-Netzwerk auflösbar. Derselbe Wert kann über die Umgebungsvariable SEARXNG_VALKEY_URL gesetzt werden. Eine Unix-Socket-URL (unix:///path/to/socket.sock?db=0) funktioniert, wenn SearXNG und Valkey auf demselben Host laufen.
Was passiert, wenn der Store fehlt, hängt von einem weiteren Schlüssel ab. Mit public_instance: false protokolliert der Limiter den Valkey-Fehler und beendet seinen Versuch. Die Instanz liefert dann weiterhin Antworten, jedoch vollständig ohne Ratenbegrenzung. Mit public_instance: true ruft der Prozess stattdessen sys.exit(1) auf. Eine offene Instanz mit fehlerhaftem Bot-Schutz sammelt sonst innerhalb eines Tages CAPTCHAs (vollautomatisierte öffentliche Turing-Tests zur Unterscheidung zwischen Computern und Menschen) von jeder Suchmaschine. Ein Container, der direkt nach dem Setzen von public_instance: true in einer Neustartschleife läuft, zeigt genau dieses Problem. Die letzte Zeile vor jedem Beenden nennt Valkey.
Was der Limiter tatsächlich zählt
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"
}
]Ein normaler Client erhält 15 Anfragen innerhalb eines Burst-Fensters von 20 Sekunden und 150 innerhalb eines Fensters von 10 Minuten. Sobald eine Anfrage als verdächtig markiert wurde, sinkt das Limit für denselben Client auf 2 pro Burst-Fenster. Die letzte Zeile ist am strengsten: Nach 3 markierten Anfragen innerhalb eines Fensters von 30 Tagen wird diese Adresse an den Anfang der Seite weitergeleitet, anstatt die Suche auszuführen. Im Log steht dann BLOCK: too many request from ... in SUSPICIOUS_IP_WINDOW (redirect to /).
Diese Zahlen sind Konstanten in searx/botdetection/ip_limit.py. Sie sind keine Einstellungen, und limiter.toml stellt sie nicht bereit. Eine Änderung erfordert daher eine Bearbeitung des Quelltexts. Über /etc/searxng/limiter.toml lassen sich die Adresspräfixe zur Gruppierung von Clients, die Liste vertrauenswürdiger Proxys, die optionale Prüfung des Link-Tokens sowie die Pass- und Blocklisten steuern.
Eine Anfrage wird aufgrund von Header-Prüfungen als verdächtig markiert. Jede Prüfung hat einen Namen, der im Debug-Log erscheint:
http_accept: Der HeaderAcceptenthält nichttext/html.http_accept_encoding: Der HeaderAccept-Encodingnennt wedergzipnochdeflate.http_accept_language: Es gibt keinen HeaderAccept-Language.http_connection: Der HeaderConnectionist aufclosegesetzt.http_user_agent:User-Agentfehlt oder entspricht einem bekannten Bot-Muster.http_sec_fetch: Der HeaderSec-Fetch-ModeoderSec-Fetch-Destentspricht nicht dem, was ein Browser sendet.
Ein Browser sendet all diese Header. Ein einfacher curl-Aufruf sendet fast keinen davon. Deshalb wird eine manuell erstellte Testanfrage bereits beim ersten Versuch markiert, während dieselbe Suche in einem Browser-Tab funktioniert. Daher ist „In meinem Browser funktioniert es, aber mein Script erhält 429“ das normale Ergebnis und kein Rätsel.
Hinter einem Reverse Proxy blockiert der Limiter alle gleichzeitig
Dies ist die häufigste Ursache dafür, dass eine funktionierende Instanz ausfällt. SearXNG übernimmt die Client-Adresse aus der ersten nicht vertrauenswürdigen IP-Adresse in X-Forwarded-For, verwendet ersatzweise X-Real-IP und greift danach auf die Adresse zurück, die die Verbindung geöffnet hat. Ob diesen Headern überhaupt vertraut wird, legt trusted_proxies in limiter.toml fest.
Wenn die Adresse Ihres Proxys nicht in dieser Liste steht, werden die Header ignoriert und jeder Besucher kommt mit der Adresse des Proxys an. Alle teilen sich dann einen Zähler. Sobald die Summe 150 Anfragen in 10 Minuten überschreitet, wird die gesamte Website gemeinsam blockiert. Ein Benutzer, der eine Ergebnisseite einige Male neu lädt, kann dadurch alle anderen mit blockieren.
Zu viel Vertrauen ist noch problematischer. Wenn ein öffentlicher Bereich eingetragen ist, kann jeder Besucher seinen eigenen X-Forwarded-For-Header senden und für jede Anfrage eine neue Identität auswählen. Dadurch wird der Limiter für jeden deaktiviert, der dieses Verhalten kennt. Tragen Sie nur die Adresse ein, von der aus Ihr eigener Proxy Verbindungen herstellt. In Docker ist das normalerweise ein Bridge-Netzwerk innerhalb von 172.16.0.0/12. Diese Zeile ist standardmäßig auskommentiert.
[botdetection]
ipv4_prefix = 32
ipv6_prefix = 48
trusted_proxies = [
'127.0.0.0/8',
'::1',
'172.16.0.0/12',
]Der Proxy muss die Header ebenfalls senden. Nginx fügt sie nicht selbstständig hinzu:
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 und Traefik setzen die weitergeleiteten Header automatisch. Bei diesen beiden müssen Sie daher nur den Teil trusted_proxies konfigurieren. Die Abwägungen werden unter Auswahl eines Reverse Proxys für einen selbst gehosteten Dienst erläutert. Um beide Konfigurationen zu prüfen, aktivieren Sie debug, führen Sie einmal über Ihr Smartphone im Mobilfunknetz eine Suche durch und stellen Sie sicher, dass die Adresse Ihres Smartphones statt der Proxy-Adresse im Netzwerkfeld der Logzeile steht.
Ihr Agent darf vier API-Anfragen pro Stunde senden
Die JSON-Ausgabe ist standardmäßig deaktiviert. Ein Agent muss sie daher aktivieren:
search:
formats:
- html
- jsonLesen Sie jetzt erneut die betreffende Zeile in der Tabelle. Jede Anfrage, die ein anderes Format als HTML anfordert, wird in ihrem eigenen Zeitfenster gezählt: 4 Anfragen pro 1 hour, pro Adresse. Ein Recherche-Agent verbraucht dieses Kontingent in einer einzigen Aufgabe. Jede weitere Anfrage liefert anschließend den Status 429. Eine Erhöhung des Limits ist nicht möglich, weil der Wert im Quelltext festgelegt ist.
Die saubere Lösung besteht darin, dem Limiter mitzuteilen, dass dieser Client kein unbekannter Client ist. Fügen Sie seine Adresse in limiter.toml zur Allowlist hinzu:
[botdetection.ip_lists]
block_ip = []
pass_ip = [
'10.8.0.0/24',
]
pass_searxng_org = truepass_ip hat Vorrang vor allen anderen Methoden. Ein Client auf der Allowlist überspringt daher auch die Header-Prüfungen, und ein einfacher Aufruf von curl funktioniert. Halten Sie den Bereich so klein wie möglich. Bevorzugen Sie ein VPN-Subnetz oder ein Containernetzwerk gegenüber einem routbaren Netzwerk. Die andere saubere Lösung besteht darin, den Agenten vollständig aus dem öffentlichen Netzwerkpfad herauszuhalten. Verweisen Sie ihn auf die Containeradresse im internen Netzwerk. Dort sehen der Proxy und sein Limiter den Netzwerkverkehr nicht. Die Einrichtung wird unter einem SearXNG-Suchdienst für einen AI-Agenten beschrieben.
Vermeiden Sie es, einen Agenten auf eine öffentliche Instanz zu verweisen, die von einer anderen Person betrieben wird. Dadurch wird die IP-Adresse eines freiwilligen Betreibers am schnellsten von übergeordneten Suchmaschinen blockiert. Genau deshalb ist das JSON-Format standardmäßig deaktiviert.
Wenn die Engines Sie stattdessen blockieren
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"
}
]Wenn eine Engine mit einem eigenen 429-Fehler oder einer CAPTCHA-Seite antwortet, löst SearXNG eine benannte Exception aus und fragt diese Engine eine Zeit lang nicht mehr ab. Eine Antwort mit „Too Many Requests“ setzt sie für 3600 Sekunden aus. Eine normale CAPTCHA- oder eine „Access Denied“-Antwort setzt sie für 1 day aus. Ein CAPTCHA, das über Cloudflare ausgeliefert wird, setzt sie für 15 days aus. Das ist der längste Standardwert in der Liste, weil die Blockierung in diesem Fall am Edge erfolgt und weitere Versuche nicht helfen.
Für normale Fehler gelten andere Einstellungen. Ein Timeout oder ein Parse-Fehler setzt die Engine für eine kurze, aus search.ban_time_on_fail abgeleitete Zeit aus. Dieser Wert beträgt standardmäßig 5 Sekunden und wird durch search.max_ban_time_on_fail auf 120 Sekunden begrenzt. Eine langsame Engine erholt sich daher innerhalb weniger Minuten selbstständig, während eine blockierte Engine stundenlang nicht verfügbar ist. Dieser Unterschied erklärt ein Symptom, das häufig als zufällig wahrgenommen wird: Zunächst sind die Ergebnisse in Ordnung, dann verschwinden die Ergebnisse einer Engine für den restlichen Nachmittag.
Beheben Sie Timeouts, bevor Sie jemandem die Schuld geben. Der Standardwert request_timeout beträgt 2.0 Sekunden. Das ist für einen kleinen VPS, der weit vom nächstgelegenen Edge-Server einer Engine entfernt steht, knapp bemessen.
outgoing:
request_timeout: 3.0
max_request_timeout: 10.0
engines:
- name: bing
timeout: 5.0request_timeout ist der Standardwert für jede Engine, max_request_timeout ist die Obergrenze, und eine einzelne Engine kann einen eigenen Wert für timeout verwenden. Höhere Werte erhöhen die Latenz beim Laden von Seiten, reduzieren aber die Anzahl der Fehler. Erhöhen Sie den Wert daher in Schritten von einer halben Sekunde und beobachten Sie /stats/errors, statt direkt auf 10 zu gehen.
Wenn eine Engine Ihre Adresse tatsächlich blockiert, entfernen Sie sie. Jede Suche wartet auf die langsamste Engine. Eine dauerhaft ausgesetzte Engine erhöht daher nur die Latenz und liefert keine Ergebnisse.
use_default_settings:
engines:
remove:
- googleÜbernehmen Sie die Änderungen mit docker compose restart searxng-core. Führen Sie anschließend einige Suchen aus und laden Sie /stats/errors neu. Wenn die Seite nach fünf Minuten tatsächlicher Nutzung leer ist, wurde die Änderung übernommen.
Eine IP-Adresse aus einem Rechenzentrum wird als Bot behandelt
Die Adresse Ihres VPS gehört zu einem Hosting-Netzbereich. Große Suchmaschinen bewerten solche Netzbereiche als automatisierten Datenverkehr. Einige von ihnen liefern für jede Anfrage von einer solchen Adresse ein CAPTCHA aus, unabhängig davon, wie korrekt die Header sind oder wie langsam die Anfragen erfolgen. Keine Einstellung in settings.yml ändert diese Bewertung.
Sie können jedoch festlegen, welche Suchmaschinen Sie abfragen und ob Ihre Instanz öffentlich erreichbar ist. Eine private Instanz, die von einem Haushalt verwendet wird, löst nur selten solche Maßnahmen aus. Eine öffentliche Instanz mit einer Hosting-IP wird bei den strengsten Suchmaschinen Sperren anhäufen. Das ist der normale Betriebszustand der Software und kein Fehler in Ihrer Konfiguration. SearXNG kann Suchmaschinenanfragen mit outgoing.proxies oder outgoing.using_tor_proxy über einen Proxy leiten. Dadurch wird der Netzwerkverkehr von einer anderen Adresse aus übertragen. Exit-Nodes und günstige Proxy-Pools werden schlechter bewertet als Hosting-Netzbereiche. Rechnen Sie daher damit, dass sich die Ergebnisse durch diese Änderung verschlechtern.
Überwachen Sie die Instanz, damit Sie Probleme früh erkennen
SearXNG antwortet auf seinem Port auch dann, wenn alle Engines pausiert sind. Eine Uptime-Prüfung, die nur den Statuscode überwacht, bleibt deshalb grün, obwohl die Instanz keine Ergebnisse liefert. Prüfen Sie stattdessen den Inhalt: Führen Sie eine echte Suche aus und suchen Sie im Antworttext nach einem erwarteten Wort. Keyword-Überwachung mit Uptime Kuma erledigt das ohne zusätzliche Tools. Überwachen Sie /stats/errors außerdem nach jedem Versions-Update, weil Engines ihr HTML ändern können und ein Parser dann ohne Zusammenhang mit einer Ratenbegrenzung ausfällt.
FAQ
Warum gibt SearXNG jedem Besucher den Status 429 zurück, nachdem ich es hinter einen Reverse Proxy gestellt habe?
Weil der Limiter den Proxy als Client zählt. SearXNG liest X-Forwarded-For nur aus, wenn die Verbindungsadresse in trusted_proxies unter /etc/searxng/limiter.toml aufgeführt ist. Ist sie dort nicht aufgeführt, verwenden alle Besucher denselben Zähler und überschreiten gemeinsam das Limit von 150 Anfragen in 10 Minuten. Fügen Sie die Adresse hinzu, von der aus Ihr Proxy die Verbindung herstellt. In Docker ist das normalerweise der Bridge-Bereich 172.16.0.0/12. Stellen Sie außerdem sicher, dass der Proxy X-Real-IP und X-Forwarded-For sendet. Führen Sie niemals einen Bereich auf, den Sie nicht kontrollieren. In einem vertrauenswürdigen Netzwerk kann jeder Besucher diesen Header setzen und für jede Anfrage eine neue Identität wählen.
Wie viele API-Anfragen pro Stunde erlaubt der SearXNG-Limiter?
Vier pro IP-Adresse und Stunde. Jede Anfrage, die ein anderes Format als HTML anfordert, zählt in einem separaten Zeitfenster von einer Stunde. Dieses Limit ist in searx/botdetection/ip_limit.py statt in limiter.toml festgelegt und kann daher nicht über die Konfiguration erhöht werden. Ein Agent oder ein Skript überschreitet es innerhalb einer Aufgabe. Fügen Sie die Adresse des Clients in pass_ip unter limiter.toml hinzu, oder greifen Sie über ein internes Netzwerk auf die Instanz zu, in dem der Limiter die Anfrage nicht sieht.
Warum bleiben meine Suchergebnisse leer, ohne dass ein Fehler 429 angezeigt wird?
Die Engines weisen Ihren Server zurück, nicht Ihre Benutzer. Öffnen Sie /stats/errors auf Ihrer eigenen Instanz. Dort wird für jede fehlgeschlagene Engine der Grund aufgeführt. Ein CAPTCHA- oder Access-denied-Eintrag bedeutet, dass die Engine die IP-Adresse Ihres Servers blockiert hat. SearXNG deaktiviert die Engine anschließend vorübergehend: eine Stunde nach einer Antwort mit zu vielen Anfragen und einen Tag nach einem CAPTCHA. Keine lokale Einstellung hebt eine Sperre beim Upstream auf. Entfernen Sie daher die Engines, die Ihre Adresse blockieren, und behalten Sie die Engines, die antworten.
Sollte ich den Limiter auf einer privaten Instanz aktivieren?
Wenn außer Ihnen niemand auf die Instanz zugreift, lassen Sie limiter: false deaktiviert. Der Limiter fügt eine Valkey-Abhängigkeit hinzu und blockiert Ihre eigenen Skripte. Außerdem schützt er vor Netzwerkverkehr, den es nicht gibt. Aktivieren Sie ihn, sobald die Instanz eine öffentliche Adresse erhält, zusammen mit public_instance: true. Diese Kombination ist beabsichtigt: Mit public_instance: true und ohne funktionierendes Valkey beendet sich der Prozess mit Status 1, statt ungeschützt weiterzulaufen.