SSD Nodes Learn 🎉 VPS $5.50/aydan başlayan
Rehberler Matt ConnorYazan Matt Connor

SearXNG 429 Hatası ve Hız Sınırı Çözümü

SearXNG 429 hatalarının yerel sınırlayıcıdan mı yoksa arama motoru engellemesinden mi kaynaklandığını günlük kayıtları üzerinden tespit edin ve doğru ayarları yapılandırın.

SearXNG neden 429 hataları döndürür

Kendi sunucunuzda barındırdığınız bir SearXNG örneği, birbiriyle ilgisiz iki nedenden dolayı 429 hatası döndürür ve düzeltmeniz gereken hız sınırı genellikle varsaydığınız değildir. İlk neden yereldir: SearXNG'nin kendi sınırlayıcısı, bir isteğin bot tarafından yapıldığına karar vermiş ve Too Many Requests durum koduyla 429 yanıtı dönmüştür. İkinci neden ise yukarı yönlüdür (upstream): bir arama motoru sunucunuzun IP adresini reddetmiştir; bu durum kullanıcılarınıza 429 olarak değil, sonuç sayfasında eksik öğeler içeren bir sayfa olarak yansır.

Bu iki durumun çözüm yolu ortak değildir. Sınırlayıcı size aittir, bu nedenle onu değiştirebilirsiniz. Yukarı yönlü engelleme ise Google tarafında gerçekleşir, dolayısıyla settings.yml dosyanızdaki hiçbir ayar bu engeli kaldırmayacaktır. Günlük kayıtları, hangi durumla karşı karşıya olduğunuzu yaklaşık bir dakika içinde size söyler, bu yüzden işe oradan başlayın.

Bu kılavuz, kendi VPS'inizde barındırdığınız bir SearXNG örneği kurulumunda açıklanan container kurulumunu temel alır. Aşağıdaki tüm ayar isimleri, Ağustos 2026 itibarıyla kontrol edilmiş güncel yukarı yönlü dokümantasyon ve kaynak koddan alınmıştır.

Ayarları değiştirmeden önce günlük kayıtlarını inceleyin

Sorunu, günlük kayıtlarını gösteren bir pencere açıkken yeniden oluşturun.

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

Sınırlayıcı (limiter) mesajları searx.limiter adlı günlük kaydedicisinden gelir ve bir IP adresi belirtir. Bir engelleme listesi (blocklist) eşleşmesi BLOCK 203.0.113.10: matched BLOCKLIST şeklinde, bir izin listesi (allowlist) eşleşmesi ise PASS 203.0.113.10: matched PASSLIST şeklinde görünür. Sınırlayıcı, sayaç deposuna erişemezse günlükte The limiter requires Valkey, please consult the documentation mesajı yer alır; bu, hiçbir şeyin sayılmadığı anlamına gelir.

Her bir bot denetimi hata ayıklama (debug) seviyesinde günlüğe kaydedilir, bu nedenle varsayılan olarak bunları göremezsiniz. Bir test için settings.yml dosyasında hata ayıklamayı açın:

general:
  debug: true

Günlük kaydı, istemci ağının yanında NOT OK (http_accept_language) biçiminde satırlar ekler ve başarısız olan denetimi belirtir. İşlem bittikten sonra hata ayıklamayı tekrar kapatın; çünkü yukarı akış (upstream) kaynakları, dağıtılmış bir örneğin hata ayıklama açıkken çalıştırılmamasını önerir.

Motor hataları bundan tamamen farklı görünür. Bir IP adresi yerine bir motor adı belirtirler ve en yaygın olanı zaman aşımıdır:

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

Bunun için bir sayfa da mevcuttur. enable_metrics değeri varsayılan olan true seviyesinde bırakıldığında, örneğiniz motor hatalarını /stats/errors dizininde kaydeder ve /preferences sayfası hangi motorların o an yanıt verdiğini listeler. Eğer /stats/errors doluysa ve günlükte hiç searx.limiter satırı yoksa, sorun sınırlayıcıdan kaynaklanmıyor demektir.

Hata ayıklamaya başlamadan önce sürümü sabitleyin

Yukarı akış (upstream) container kurulumu iki dosyadan oluşur.

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

Compose dosyası docker.io/searxng/searxng:${SEARXNG_VERSION:-latest} imajını çeker. Ayarlanmamış bir değişken latest anlamına gelir ve latest kullanımı, bir sonraki docker compose pull işleminde örneğin sizin bilginiz dışında değişmesine neden olur; bu yüzden geçen hafta çalışan bir ayar, onu okuyan kodla uyumsuz hale gelebilir. SearXNG etiketleri bir tarih ve commit bilgisi taşır. Ağustos 2026 itibarıyla yukarı akış .env.example içindeki örnek etiket 2026.3.25-541c6c3cb şeklindedir, bu nedenle .env içinde gerçek bir değer belirleyin:

SEARXNG_VERSION=2026.3.25-541c6c3cb

Yayınlanan etiketleri kontrol edin ve gerçekten test ettiğiniz sürümü sabitleyin, ardından hata ayıklama işlemini sabit bir hedef üzerinde gerçekleştirin. Aynı .env dosyası gizli anahtarınızı da barındırır, bu nedenle o dizini herhangi bir yere commit etmeden önce Docker Compose içinde env dosyaları ve gizli veriler nasıl çalışır konusunu inceleyin.

Sınırlayıcı Valkey gerektirir, aksi takdirde çalışmaz

Sınırlayıcı, istemci başına gelen istekleri sayar ve bu sayıların çalışan süreçler arasında paylaşılması gerekir. Bu depolama alanı, Redis'in güncel tutulan çatalı olan Valkey'dir. Eski SearXNG rehberleri bu ayarı redis: olarak adlandırır. Güncel sürümler valkey: değerini okur, bu nedenle anahtar adını eski bir gönderiden değil, güncel dokümantasyondan kopyalayın.

use_default_settings: true
server:
  secret_key: "change-this-value"
  limiter: true
  public_instance: false
valkey:
  url: valkey://searxng-valkey:6379/0

Yukarı akış (upstream) compose dosyası halihazırda docker.io/valkey/valkey:9-alpine imajı üzerinde bir searxng-valkey servisi çalıştırır, bu nedenle ilgili ana makine adı compose ağı içerisinde çözümlenir. Aynı değer SEARXNG_VALKEY_URL ortam değişkeni ile ayarlanabilir ve SearXNG ile Valkey aynı ana makineyi paylaştığında bir Unix soket URL'si (unix:///path/to/socket.sock?db=0) kullanılabilir.

Depolama alanı eksik olduğunda ne olacağı başka bir anahtara bağlıdır. public_instance: false ayarlandığında, sınırlayıcı Valkey hatasını günlüğe kaydeder ve işlemi bırakır; böylece örnek, herhangi bir hız sınırlaması olmaksızın hizmet vermeye devam eder. public_instance: true ayarlandığında ise süreç bunun yerine sys.exit(1) çağrısı yapar; çünkü bot koruması bozuk olan açık bir örnek, bir gün içerisinde her arama motorundan CAPTCHA (bilgisayarları ve insanları ayırt etmek için kullanılan tamamen otomatikleştirilmiş genel Turing testi) toplar. public_instance: true ayarlandıktan hemen sonra döngüsel olarak yeniden başlayan bir container bu durumdadır ve her çıkıştan önceki son satır Valkey'i işaret eder.

Sınırlayıcının gerçekte neleri saydığı

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"
  }
]

Normal bir istemci, 20 saniyelik bir ani yük (burst) penceresi içinde 15 adet, 10 dakikalık bir pencere içinde ise 150 adet istek gönderebilir. Bir istek şüpheli olarak işaretlendiğinde, aynı istemcinin limiti ani yük penceresi başına 2 seviyesine düşer. Son satır en katı olanıdır: 30 günlük bir pencere içinde 3 adet şüpheli istekten sonra, ilgili adres arama yapmak yerine başlangıç sayfasına yönlendirilir ve log kaydında BLOCK: too many request from ... in SUSPICIOUS_IP_WINDOW (redirect to /) ifadesi yer alır.

Bu sayılar searx/botdetection/ip_limit.py içinde sabit değerlerdir. Bunlar birer ayar değildir ve limiter.toml bunları dışarıya açmaz; dolayısıyla bu değerleri değiştirmek kaynak kodun düzenlenmesini gerektirir. /etc/searxng/limiter.toml ile kontrol edilebilen unsurlar; istemcileri gruplamak için kullanılan adres önekleri, güvenilir proxy listesi, isteğe bağlı bağlantı belirteci (token) kontrolü ile izin verilenler ve engellenenler listeleridir.

Bir istek, başlık (header) kontrolleri sonucunda şüpheli olarak işaretlenir ve her kontrolün hata ayıklama (debug) logunda göreceğiniz bir adı vardır:

  • http_accept: Accept başlığı text/html içermiyor.
  • http_accept_encoding: Accept-Encoding başlığı ne gzip ne de deflate değerlerini içeriyor.
  • http_accept_language: Accept-Language başlığı mevcut değil.
  • http_connection: Connection başlığı close olarak ayarlanmış.
  • http_user_agent: User-Agent eksik veya bilinen bir bot kalıbıyla eşleşiyor.
  • http_sec_fetch: Sec-Fetch-Mode veya Sec-Fetch-Dest başlığı bir tarayıcının gönderdiği değerle uyuşmuyor.

Bir tarayıcı bunların hepsini gönderir. Standart bir curl çağrısı ise bunların neredeyse hiçbirini göndermez; bu nedenle elle yazılmış bir test isteği ilk denemede işaretlenirken, aynı arama tarayıcı sekmesinde sorunsuz çalışır. "Tarayıcımda çalışıyor ama betiğim 429 hatası alıyor" durumu, gizemli bir sorun değil, beklenen bir sonuçtur.

Reverse proxy arkasında sınırlayıcı herkesi aynı anda engelliyor

Bu, çalışan bir örneği bozmanın en yaygın yoludur. SearXNG, istemci adresini X-Forwarded-For içindeki ilk güvenilmeyen IP'den alır, başarısız olursa X-Real-IP değerine, o da başarısız olursa bağlantıyı açan adrese döner. Bu başlıkların dikkate alınıp alınmayacağına limiter.toml içindeki trusted_proxies ayarı karar verir.

Proxy'nizin adresi bu listede değilse, başlıklar göz ardı edilir ve her ziyaretçi proxy'nin adresiyle gelir. Bu durumda hepsi tek bir sayacı paylaşır; toplam istek sayısı 10 dakika içinde 150 sınırını aştığında tüm site engellenir. Bir kullanıcının sonuç sayfasını birkaç kez yenilemesi, herkesin erişimini kesmesine neden olur.

Fazla güvenmek daha kötüdür. Eğer genel bir IP aralığı listelenirse, herhangi bir ziyaretçi kendi X-Forwarded-For başlığını göndererek her istekte yeni bir kimlik seçebilir; bu da sınırlayıcıyı, bunu bilen herkes için devre dışı bırakır. Yalnızca kendi proxy'nizin bağlandığı adresi listeleyin. Docker'da bu genellikle 172.16.0.0/12 içindeki bir köprü ağıdır ve bu satır varsayılan olarak yorum satırı halinde gelir.

[botdetection]
ipv4_prefix = 32
ipv6_prefix = 48

trusted_proxies = [
  '127.0.0.0/8',
  '::1',
  '172.16.0.0/12',
]

Proxy'nin de başlıkları göndermesi gerekir. Nginx bunları kendiliğinden eklemez:

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 ve Traefik, yönlendirilmiş başlıkları sizin yerinize ayarlar; bu nedenle onlarla çalışırken işin yalnızca trusted_proxies kısmını yapmanız yeterlidir. Avantaj ve dezavantajlar self-hosted bir servis için reverse proxy seçimi bölümünde ele alınmıştır. Her iki kurulumu da doğrulamak için debug ayarını açın, mobil veriniz üzerinden telefonunuzla bir kez arama yapın ve günlük kaydındaki ağ adresinin proxy'ninki değil, telefonunuzun adresi olduğunu teyit edin.

Ajanınız saatte dört API isteği alıyor

JSON çıktısı varsayılan olarak devre dışıdır, bu nedenle bir ajanın bunu eklemesi gerekir:

search:
  formats:
    - html
    - json

Şimdi tablo satırını tekrar okuyun. HTML dışındaki bir formatı isteyen her istek kendi penceresinde sayılır: 4 istek, her 1 hour başına ve her adres için. Bir araştırma ajanı bunu tek bir görevde tüketir ve sonrasındaki her çağrı 429 hatası döndürür. Limiti yükseltmek bir seçenek değildir, çünkü bu sayı kaynak kodun içinde yer alır.

Temiz çözüm, sınırlayıcıya (limiter) bu istemcinin yabancı olmadığını bildirmektir. Adresini limiter.toml içindeki izin verilenler listesine (pass list) ekleyin:

[botdetection.ip_lists]
block_ip = []

pass_ip = [
  '10.8.0.0/24',
]

pass_searxng_org = true

pass_ip diğer tüm yöntemlerden daha yüksek önceliğe sahiptir, bu nedenle izin verilenler listesindeki bir istemci başlık kontrollerini de atlar ve yalın bir curl çağrısı çalışır. Aralığı mümkün olduğunca küçük tutun ve yönlendirilebilir herhangi bir şey yerine bir VPN alt ağı veya container ağı tercih edin. Diğer temiz çözüm ise ajanı genel yoldan tamamen uzak tutmaktır: ajanı, proxy ve sınırlayıcısının trafiği hiç görmediği iç ağdaki container adresine yönlendirin. Bunun nasıl yapılacağı bir yapay zeka ajanına SearXNG arama yeteneği kazandırma bölümünde ele alınmıştır.

Kaçınılması gereken seçenek, ajanı başkasının çalıştırdığı genel bir örneğe (public instance) yönlendirmektir. Bu, bir gönüllünün IP adresinin üst kaynaklar (upstream engines) tarafından engellenmesini sağlamanın en hızlı yoludur ve JSON formatının varsayılan olarak devre dışı bırakılmasının temel nedeni de budur.

Arama motorları sizi engellediğinde

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"
  }
]

Bir arama motoru kendi 429 yanıtını döndürdüğünde veya bir CAPTCHA sayfası sunduğunda, SearXNG adlandırılmış bir istisna oluşturur ve ilgili motoru bir süreliğine sorgulamayı durdurur. Çok fazla istek (too-many-requests) yanıtı, motoru 3600 saniye boyunca askıya alır. Düz bir CAPTCHA veya erişim reddi yanıtı, motoru 1 day süreyle askıya alır. Cloudflare üzerinden sunulan bir CAPTCHA ise motoru 15 days süreyle askıya alır; bu, listedeki en uzun varsayılan süredir çünkü bu yanıt, engellemenin uç noktada (edge) olduğunu ve yeniden denemenin bir fayda sağlamayacağını gösterir.

Sıradan hatalar farklı ayarlar kullanır. Bir zaman aşımı veya ayrıştırma hatası, motoru search.ban_time_on_fail değerinden türetilen kısa bir süre için askıya alır; bu değer varsayılan olarak 5 saniyedir ve search.max_ban_time_on_fail ile 120 saniye ile sınırlandırılmıştır. Dolayısıyla yavaş bir motor birkaç dakika içinde kendiliğinden düzelirken, engellenen bir motor saatlerce devre dışı kalır. Bu fark, kullanıcıların rastgele olarak bildirdiği bir belirtiyi açıklar: sonuçlar düzgün gelirken, bir motorun sonuçları öğleden sonranın geri kalanında kaybolur.

Kimseyi suçlamadan önce zaman aşımlarını düzeltmekte fayda vardır. Varsayılan request_timeout değeri 2.0 saniyedir; bu, arama motorunun en yakın uç sunucusundan uzakta bulunan küçük bir VPS için oldukça kısıtlı bir süredir.

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

request_timeout her motor için varsayılan değerdir, max_request_timeout üst sınırdır ve tek bir motor kendi timeout değerini taşıyabilir. Bu değerleri artırmak, daha az hata almak için sayfa gecikme süresini feda etmek anlamına gelir; bu nedenle doğrudan 10 değerine çıkmak yerine yarım saniyelik artışlarla ilerleyin ve /stats/errors değerini izleyin.

IP adresinizi gerçekten engelleyen bir motor için, o motoru kaldırın. Her arama, en yavaş motorun yanıt vermesini bekler; bu nedenle kalıcı olarak askıya alınmış bir motoru tutmak, gecikmeye neden olur ve hiçbir sonuç döndürmez.

use_default_settings:
  engines:
    remove:
      - google

Değişiklikleri docker compose restart searxng-core ile uygulayın, ardından birkaç arama yapın ve /stats/errors sayfasını yeniden yükleyin. Beş dakikalık gerçek kullanımdan sonra boş bir sayfa ile karşılaşmıyorsanız, değişiklik işe yaramış demektir.

Bir veri merkezi IP adresi bot olarak değerlendirilecektir

VPS adresiniz bir barındırma aralığına aittir ve büyük arama motorları bu aralıkları otomasyon olarak puanlar. Bunların bazıları, başlıklar ne kadar düzgün veya hız ne kadar yavaş olursa olsun, böyle bir adresten gelen her isteğe bir CAPTCHA sunar. settings.yml içindeki hiçbir ayar bu yargıyı değiştirmez.

Değiştirebileceğiniz şey, hangi arama motorlarına sorgu gönderdiğiniz ve örneğinizin herkese açık listelenip listelenmediğidir. Tek bir hane tarafından kullanılan özel bir örnek nadiren herhangi bir engele takılır. Barındırma IP'si üzerinde çalışan herkese açık bir örnek, en katı arama motorlarında askıya alma işlemleriyle karşılaşacaktır; bu, yapılandırmanızdaki bir hatadan ziyade yazılımın normal durumudur. SearXNG, arama motoru isteklerini outgoing.proxies veya outgoing.using_tor_proxy ile bir proxy üzerinden yönlendirebilir; bu da trafiği farklı bir adrese taşır. Çıkış düğümleri ve ucuz proxy havuzları, barındırma aralıklarından daha kötü puanlanır; bu nedenle bu değişikliğin sonuçları daha da kötüleştirmesini beklemelisiniz.

Sunucuyu izleyerek ilk siz haberdar olun

SearXNG, tüm arama motorları askıya alınmış olsa bile kendi portu üzerinden yanıt verir; bu nedenle yalnızca durum kodunu kontrol eden bir çalışma süresi (uptime) denetimi, sunucu hiçbir sonuç döndürmediği halde başarılı (yeşil) görünecektir. Bunun yerine içeriği denetleyin: gerçek bir arama isteği gönderin ve yanıt gövdesinde beklediğiniz bir kelimeyi eşleştirin. Uptime Kuma anahtar kelime izleme özelliği, ek bir araca ihtiyaç duymadan tam olarak bunu yapar. Ayrıca her sürüm güncellemesinden sonra /stats/errors dosyasını izleyin; çünkü arama motorları HTML yapılarını değiştirebilir ve bu durum, herhangi bir hız sınırlaması (rate limit) söz konusu olmaksızın ayrıştırıcının (parser) bozulmasına neden olabilir.

FAQ

SearXNG'yi bir reverse proxy arkasına koyduktan sonra neden her ziyaretçiye 429 hatası dönüyor?

Çünkü sınırlayıcı, proxy'yi istemci olarak saymaktadır. SearXNG, X-Forwarded-For değerini yalnızca bağlantı kuran adres /etc/searxng/limiter.toml dosyasındaki trusted_proxies listesinde yer aldığında okur. Eğer adres listelenmemişse, tüm ziyaretçiler tek bir sayacı paylaşır ve hepsi 10 dakikada 150 istek sınırını birlikte aşar. Proxy'nizin bağlandığı adresi (Docker'da bu genellikle 172.16.0.0/12 köprü aralığıdır) ekleyin ve proxy'nin X-Real-IP ve X-Forwarded-For başlıklarını gönderdiğinden emin olun. Kontrol etmediğiniz bir aralığı asla listeye eklemeyin; çünkü güvenilen bir ağ, herhangi bir ziyaretçinin bu başlığı ayarlamasına ve her istek için yeni bir kimlik seçmesine olanak tanır.

SearXNG sınırlayıcısı saatte kaç API isteğine izin veriyor?

IP adresi başına saatte dört istek. HTML dışındaki bir formatı talep eden her istek ayrı bir bir saatlik pencerede sayılır ve bu sınır limiter.toml yerine searx/botdetection/ip_limit.py içinde belirlenmiştir; bu nedenle yapılandırma dosyasından artırılamaz. Bir aracı veya betik bunu tek bir görevde gerçekleştirir. İstemcinin adresini limiter.toml içindeki pass_ip kısmına ekleyin veya örneğe, sınırlayıcının isteği hiç görmediği bir iç ağ üzerinden erişin.

Arama sonuçlarım neden 429 hatası almadan boş dönüyor?

Arama motorları kullanıcılarınızı değil, sunucunuzu reddediyor. Kendi örneğinizde /stats/errors dosyasını açın: bu dosya başarısız olan her motoru ve nedenini listeler; bir CAPTCHA veya erişim reddi girişi, o motorun sunucunuzun IP adresini engellediği anlamına gelir. SearXNG, çok fazla istek yanıtından sonra motoru bir saatliğine, CAPTCHA'dan sonra ise bir günlüğüne askıya alır. Hiçbir yerel ayar, üst kaynak tarafından uygulanan bir engeli kaldırmaz; bu nedenle adresinizi engelleyen motorları kaldırın ve yanıt verenleri tutun.

Özel bir örnekte sınırlayıcıyı etkinleştirmeli miyim?

Eğer örneğe sizden başka kimse erişmiyorsa limiter: false ayarını olduğu gibi bırakın. Bu ayar bir Valkey bağımlılığı ekler, kendi betiklerinizi engeller ve sahip olmadığınız bir trafiğe karşı koruma sağlar. Örneğe genel bir adres atandığı anda, public_instance: true ile birlikte sınırlayıcıyı etkinleştirin. Bu ikili bilinçli olarak tasarlanmıştır: public_instance: true etkinse ve çalışan bir Valkey yoksa, süreç korumasız çalışmak yerine 1 durum koduyla sonlanır.