SSD Nodes Learn 🎉 VPS dari $5.50/bln
Panduan Matt ConnorOleh Matt Connor

Cara Selesaikan Ralat 429 dan Rate Limit SearXNG

Ralat 429 pada SearXNG berpunca daripada pengehad tempatan atau sekatan IP oleh enjin carian. Semak log untuk mengenal pasti punca sebenar dan elakkan konfigurasi yang salah.

Mengapa SearXNG memberikan ralat 429

Instans SearXNG yang dihoskan sendiri memberikan ralat 429 atas dua sebab yang tidak berkaitan, dan had kadar (rate limit) yang perlu anda betulkan biasanya bukan yang anda sangkakan. Sebab pertama adalah tempatan: pengehad (limiter) SearXNG sendiri memutuskan bahawa permintaan datang daripada bot dan menjawab Too Many Requests dengan status 429. Sebab kedua adalah hulu (upstream): enjin carian menolak alamat IP pelayan anda, yang sampai kepada pengguna anda sebagai halaman hasil carian dengan maklumat yang hilang, bukannya sebagai ralat 429.

Kedua-dua kes ini tidak mempunyai penyelesaian yang sama. Pengehad tersebut adalah milik anda, jadi anda boleh mengubahnya. Sekatan hulu berlaku di pihak Google, jadi tiada apa-apa dalam settings.yml anda yang akan melonggarkannya. Log akan memberitahu anda yang mana satu masalah anda dalam masa kira-kira seminit, jadi mulakan dari situ.

Panduan ini mengandaikan pemasangan kontena yang diterangkan dalam instans SearXNG yang dihoskan sendiri pada VPS anda sendiri. Setiap nama tetapan di bawah datang daripada dokumentasi dan sumber hulu semasa, yang disemak pada Ogos 2026.

Baca log sebelum anda menukar tetapan

Ulangi masalah tersebut dengan tetingkap log dibuka.

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

Mesej pengehad (limiter) datang daripada logger bernama searx.limiter dan ia menamakan alamat IP. Padanan senarai sekat (blocklist) dibaca sebagai BLOCK 203.0.113.10: matched BLOCKLIST, manakala padanan senarai izin (allowlist) dibaca sebagai PASS 203.0.113.10: matched PASSLIST. Jika pengehad tidak dapat mencapai stor pembilangnya, log akan memaparkan The limiter requires Valkey, please consult the documentation, yang bermaksud tiada apa-apa yang sedang dikira.

Setiap semakan bot individu direkodkan pada tahap debug, jadi anda tidak akan melihatnya secara lalai. Hidupkan debug untuk satu ujian dalam settings.yml:

general:
  debug: true

Log kemudian akan menambah baris berbentuk NOT OK (http_accept_language) bersebelahan dengan rangkaian klien, menamakan semakan yang gagal. Matikan semula selepas itu, kerana pihak hulu (upstream) menasihatkan anda untuk tidak menjalankan instans yang telah diatur cara dengan debug dihidupkan.

Kegagalan enjin tidak kelihatan seperti itu. Ia menamakan enjin dan bukannya IP, dan yang paling biasa ialah tamat masa (timeout):

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

Terdapat juga halaman untuk perkara ini. Dengan enable_metrics dibiarkan pada tetapan lalai true, instans anda merekodkan ralat enjin pada /stats/errors, dan /preferences menyenaraikan enjin yang sedang menjawab. Jika /stats/errors penuh dan log tidak mengandungi baris searx.limiter, masalahnya bukan pada pengehad.

Tetapkan versi sebelum anda menyahpepijat apa-apa

Persediaan kontena huluan terdiri daripada dua fail.

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

Fail compose menarik docker.io/searxng/searxng:${SEARXNG_VERSION:-latest}. Pemboleh ubah yang tidak ditetapkan bermakna latest, dan latest bermakna instans berubah tanpa pengetahuan anda pada docker compose pull seterusnya, jadi tetapan yang berfungsi minggu lepas boleh berhenti sepadan dengan kod yang membacanya. Tag SearXNG membawa tarikh dan commit. Tag contoh dalam .env.example huluan setakat Ogos 2026 ialah 2026.3.25-541c6c3cb, jadi tetapkan tag sebenar dalam .env:

SEARXNG_VERSION=2026.3.25-541c6c3cb

Semak tag yang diterbitkan dan tetapkan versi keluaran yang anda benar-benar uji, kemudian nyahpepijat terhadap sasaran yang tetap. Fail .env yang sama menyimpan kunci rahsia anda, jadi baca bagaimana fail env dan rahsia berfungsi dalam Docker Compose sebelum anda melakukan commit direktori tersebut ke mana-mana.

Limiter memerlukan Valkey untuk beroperasi

Limiter mengira permintaan bagi setiap klien, dan kiraan tersebut perlu dikongsi merentasi proses pekerja. Storan tersebut ialah Valkey, iaitu fork Redis yang diselenggara. Panduan SearXNG yang lebih lama memanggil tetapan ini redis:. Keluaran semasa membaca valkey:, jadi salin nama kunci daripada dokumentasi semasa dan bukannya daripada catatan lama.

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

Fail compose hulu sudah menjalankan servis searxng-valkey pada imej docker.io/valkey/valkey:9-alpine, jadi nama hos tersebut diselesaikan di dalam rangkaian compose. Nilai yang sama boleh ditetapkan dengan pemboleh ubah persekitaran SEARXNG_VALKEY_URL, dan URL soket Unix (unix:///path/to/socket.sock?db=0) berfungsi apabila SearXNG dan Valkey berkongsi hos yang sama.

Perkara yang berlaku apabila storan tiada bergantung pada satu lagi kunci. Dengan public_instance: false, limiter mencatat ralat Valkey dan berhenti, jadi instans terus beroperasi tanpa sebarang pengehadan kadar. Dengan public_instance: true, proses memanggil sys.exit(1) sebaliknya, kerana instans terbuka dengan perlindungan bot yang rosak akan mengumpul CAPTCHA (ujian Turing awam automatik sepenuhnya untuk membezakan komputer dan manusia) daripada setiap enjin dalam masa sehari. Kontena yang dimulakan semula dalam gelung sejurus selepas anda menetapkan public_instance: true adalah disebabkan perkara ini, dan baris terakhir sebelum setiap keluar menamakan Valkey.

Perkara yang sebenarnya dikira oleh pengehad

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

Pelanggan biasa mendapat 15 permintaan dalam tetingkap lonjakan 20 saat dan 150 dalam tetingkap 10 minit. Sebaik sahaja sesuatu permintaan ditandakan sebagai mencurigakan, pelanggan yang sama akan turun kepada 2 bagi setiap tetingkap lonjakan. Baris terakhir adalah yang paling tegas: selepas 3 permintaan ditandakan dalam tetingkap 30 hari, alamat tersebut akan dihalakan semula ke halaman mula dan bukannya melakukan carian, dan log akan memaparkan BLOCK: too many request from ... in SUSPICIOUS_IP_WINDOW (redirect to /).

Nombor-nombor ini merupakan pemalar dalam searx/botdetection/ip_limit.py. Ia bukanlah tetapan, dan limiter.toml tidak mendedahkannya, jadi mengubahnya bermakna menyunting kod sumber. Perkara yang dikawal oleh /etc/searxng/limiter.toml ialah awalan alamat yang digunakan untuk mengumpulkan pelanggan, senarai proksi yang dipercayai, semakan token pautan pilihan, serta senarai lulus dan senarai sekat.

Sesuatu permintaan ditandakan sebagai mencurigakan melalui semakan pengepala (header), dan setiap semakan mempunyai nama yang akan anda lihat dalam log nyahpepijat (debug log):

  • http_accept: pengepala Accept tidak mengandungi text/html.
  • http_accept_encoding: pengepala Accept-Encoding tidak menamakan gzip mahupun deflate.
  • http_accept_language: tiada pengepala Accept-Language.
  • http_connection: pengepala Connection ditetapkan kepada close.
  • http_user_agent: User-Agent tiada atau sepadan dengan corak bot yang diketahui.
  • http_sec_fetch: pengepala Sec-Fetch-Mode atau Sec-Fetch-Dest bukan seperti yang dihantar oleh pelayar web.

Pelayar web menghantar semua ini. Panggilan curl biasa hampir tidak menghantar mana-mana daripadanya, jadi permintaan ujian yang ditulis secara manual akan ditandakan pada percubaan pertama, manakala carian yang sama berfungsi dalam tab pelayar web. Itulah sebabnya "ia berfungsi dalam pelayar web saya, tetapi skrip saya mendapat 429" adalah hasil yang biasa dan bukannya satu misteri.

Di sebalik reverse proxy, pengehad menyekat semua orang serentak

Ini merupakan cara paling lazim yang menyebabkan instans yang berfungsi terhenti. SearXNG mengambil alamat klien daripada IP tidak dipercayai yang pertama dalam X-Forwarded-For, kembali kepada X-Real-IP, dan seterusnya kembali kepada alamat yang membuka sambungan tersebut. Sama ada pengepala (header) tersebut dipercayai atau tidak ditentukan oleh trusted_proxies dalam limiter.toml.

Jika alamat proksi anda tiada dalam senarai tersebut, pengepala akan diabaikan dan setiap pelawat akan muncul dengan alamat proksi tersebut. Mereka kemudian berkongsi satu pembilang, jadi keseluruhan tapak akan disekat serentak sebaik sahaja jumlahnya melebihi 150 permintaan dalam 10 minit. Seorang pengguna yang memuat semula halaman hasil carian beberapa kali akan menyebabkan semua orang terputus akses.

Terlalu mempercayai adalah lebih buruk. Jika julat awam disenaraikan, mana-mana pelawat boleh menghantar pengepala X-Forwarded-For mereka sendiri dan memilih identiti baharu bagi setiap permintaan, yang akan mematikan pengehad bagi sesiapa yang tahu cara mencubanya. Senaraikan hanya alamat yang disambungkan oleh proksi anda sendiri. Dalam Docker, ini biasanya merupakan rangkaian bridge di dalam 172.16.0.0/12, dan baris tersebut dihantar dalam keadaan dikomen.

[botdetection]
ipv4_prefix = 32
ipv6_prefix = 48

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

Proksi juga perlu menghantar pengepala tersebut. Nginx tidak menambah mana-mana daripadanya secara automatik:

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 dan Traefik menetapkan pengepala forwarded untuk anda, jadi dengan perisian tersebut anda hanya perlu melakukan bahagian trusted_proxies bagi tugasan ini. Pertukaran (trade-off) bagi setiap pilihan diliputi dalam memilih reverse proxy untuk servis self-hosted. Untuk mengesahkan mana-mana persediaan, hidupkan debug, lakukan satu carian daripada telefon anda menggunakan data mudah alih, dan pastikan rangkaian dalam baris log adalah alamat telefon anda dan bukannya alamat proksi.

Ejen anda menerima empat permintaan API setiap jam

Output JSON dinyahdayakan secara lalai, jadi ejen perlu ditambah untuk menggunakannya:

search:
  formats:
    - html
    - json

Sekarang baca semula baris carta tersebut. Sebarang permintaan yang meminta format selain HTML akan dikira dalam tetingkapnya sendiri: 4 permintaan bagi setiap 1 hour, bagi setiap alamat. Ejen penyelidikan akan menghabiskan kuota tersebut dalam satu tugas, dan setiap panggilan selepas itu akan mengembalikan ralat 429. Meningkatkan had bukanlah pilihan, kerana nombor tersebut ditetapkan dalam kod sumber.

Penyelesaian yang kemas adalah dengan memberitahu pengehad (limiter) bahawa klien ini bukan orang asing. Tambahkan alamatnya ke dalam senarai laluan (pass list) dalam limiter.toml:

[botdetection.ip_lists]
block_ip = []

pass_ip = [
  '10.8.0.0/24',
]

pass_searxng_org = true

pass_ip mempunyai keutamaan melebihi setiap kaedah lain, jadi klien yang berada dalam senarai dibenarkan (allowlist) akan melangkau pemeriksaan pengepala (header) dan panggilan curl biasa akan berfungsi. Pastikan julat tersebut sekecil yang mungkin, dan utamakan subnet VPN atau rangkaian kontena berbanding sebarang alamat yang boleh dihalakan (routable). Satu lagi penyelesaian yang kemas adalah dengan memastikan ejen tidak melalui laluan awam sama sekali: halakan ia ke alamat kontena pada rangkaian dalaman, di mana proksi dan pengehadnya tidak akan melihat trafik tersebut. Pemasangan tersebut diterangkan dalam memberikan ejen AI keupayaan carian SearXNG.

Pilihan yang perlu dielakkan adalah menghalakan ejen ke instans awam yang dikendalikan oleh orang lain. Itu adalah cara terpantas untuk menyebabkan alamat IP sukarelawan disekat oleh enjin huluan, dan itulah sebabnya format JSON dinyahdayakan secara lalai pada mulanya.

Apabila enjin menyekat anda pula

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

Apabila sesuatu enjin menjawab dengan 429 miliknya sendiri atau dengan halaman CAPTCHA, SearXNG akan membangkitkan exception bernama dan berhenti meminta enjin tersebut untuk seketika. Jawapan "terlalu banyak permintaan" (too-many-requests) akan menggantungnya selama 3600 saat. CAPTCHA biasa atau jawapan "akses dinafikan" (access-denied) menggantungnya selama 1 day. CAPTCHA yang dihidangkan melalui Cloudflare menggantungnya selama 15 days, tempoh lalai paling lama dalam senarai, kerana jawapan tersebut bermaksud sekatan berada di peringkat edge dan percubaan semula tidak akan membantu.

Kegagalan biasa menggunakan tetapan yang berbeza. Timeout atau ralat penghuraian (parse error) menggantung enjin untuk tempoh singkat yang diperoleh daripada search.ban_time_on_fail, yang secara lalainya adalah 5 saat dan dihadkan oleh search.max_ban_time_on_fail pada 120 saat. Jadi, enjin yang perlahan akan pulih sendiri dalam masa beberapa minit, manakala enjin yang disekat akan hilang selama berjam-jam. Perbezaan itu menjelaskan simptom yang dilaporkan pengguna sebagai rawak: hasil carian adalah baik, kemudian hasil daripada satu enjin hilang sepanjang petang.

Timeout perlu dibaiki sebelum anda menyalahkan sesiapa. Nilai lalai request_timeout ialah 2.0 saat, yang agak ketat untuk VPS kecil yang terletak jauh dari pelayan edge terdekat enjin tersebut.

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

request_timeout ialah nilai lalai untuk setiap enjin, max_request_timeout ialah had maksimum, dan satu enjin boleh membawa timeout miliknya sendiri. Meningkatkan nilai ini mengorbankan kependaman (latency) halaman demi mengurangkan kegagalan, jadi buat perubahan dalam gandaan setengah saat dan perhatikan /stats/errors dan bukannya terus melompat ke 10.

Bagi enjin yang benar-benar menyekat alamat anda, buang enjin tersebut. Setiap carian menunggu enjin yang paling perlahan, jadi mengekalkan enjin yang digantung secara kekal hanya merugikan kependaman dan tidak memberikan apa-apa hasil.

use_default_settings:
  engines:
    remove:
      - google

Gunakan perubahan dengan docker compose restart searxng-core, kemudian jalankan beberapa carian dan muat semula /stats/errors. Halaman yang kosong selepas lima minit penggunaan sebenar bermakna perubahan tersebut berjaya.

IP pusat data akan dianggap sebagai bot

Alamat VPS anda tergolong dalam julat pengehosan, dan enjin carian utama memberikan skor kepada julat tersebut sebagai automasi. Sesetengah enjin menghantar CAPTCHA kepada setiap permintaan daripada alamat sedemikian, tidak kira betapa sopan pengepala (headers) anda atau betapa perlahan kadar permintaan anda. Tiada tetapan dalam settings.yml yang boleh mengubah penilaian tersebut.

Perkara yang boleh anda ubah ialah enjin yang anda gunakan dan sama ada instans anda disenaraikan secara awam. Instans peribadi yang digunakan oleh satu isi rumah jarang mencetuskan sebarang sekatan. Instans awam pada IP pengehosan akan mengumpul penggantungan (suspensions) pada enjin yang paling ketat, dan ini merupakan keadaan biasa bagi perisian tersebut dan bukannya ralat dalam konfigurasi anda. SearXNG boleh menghalakan permintaan enjin melalui proksi dengan outgoing.proxies atau outgoing.using_tor_proxy, yang memindahkan trafik ke alamat yang berbeza. Exit node dan kumpulan proksi murah mempunyai skor yang lebih buruk daripada julat pengehosan, jadi jangkakan langkah tersebut akan memburukkan lagi hasil carian.

Pantau instans supaya anda mendapat makluman awal

SearXNG menjawab pada portnya walaupun semua enjin digantung, jadi semakan uptime yang hanya memantau kod status akan kekal hijau walaupun instans tidak memulangkan sebarang hasil. Periksa kandungan sebaliknya: buat carian sebenar dan padankan perkataan yang anda jangkakan dalam badan respons. Pemantauan kata kunci Uptime Kuma melakukan perkara tersebut tanpa memerlukan alatan tambahan. Pantau /stats/errors selepas setiap peningkatan versi juga, kerana enjin menukar HTML mereka dan parser akan rosak tanpa melibatkan sebarang had kadar (rate limit).

FAQ

Mengapakah SearXNG memulangkan ralat 429 kepada setiap pelawat selepas saya meletakkannya di belakang reverse proxy?

Ini kerana pengehad (limiter) mengira proksi sebagai pelanggan. SearXNG hanya membaca X-Forwarded-For apabila alamat penyambung disenaraikan dalam trusted_proxies di dalam /etc/searxng/limiter.toml. Jika ia tidak disenaraikan, setiap pelawat berkongsi satu pembilang dan mereka semua melepasi had 150 permintaan setiap 10 minit secara serentak. Tambahkan alamat yang digunakan oleh proksi anda untuk menyambung, yang dalam Docker biasanya merupakan julat bridge 172.16.0.0/12, dan pastikan proksi menghantar X-Real-IP dan X-Forwarded-For. Jangan sekali-kali menyenaraikan julat yang tidak anda kawal, kerana rangkaian yang dipercayai membolehkan mana-mana pelawat menetapkan header tersebut dan memilih identiti baharu untuk setiap permintaan.

Berapakah jumlah permintaan API sejam yang dibenarkan oleh pengehad SearXNG?

Empat bagi setiap alamat IP sejam. Sebarang permintaan yang meminta format selain HTML dikira dalam tetingkap satu jam yang berasingan, dan had tersebut ditetapkan dalam searx/botdetection/ip_limit.py dan bukannya dalam limiter.toml, jadi ia tidak boleh ditingkatkan melalui konfigurasi. Ejen atau skrip melepasi had ini dalam satu tugasan. Tambahkan alamat pelanggan ke pass_ip dalam limiter.toml, atau capai instans tersebut melalui rangkaian dalaman di mana pengehad tidak pernah melihat permintaan tersebut.

Mengapakah hasil carian saya kembali kosong tanpa ralat 429?

Enjin carian menolak pelayan anda, bukan pengguna anda. Buka /stats/errors pada instans anda sendiri: ia menamakan setiap enjin yang gagal dan sebabnya, dan entri CAPTCHA atau access-denied bermakna enjin tersebut menyekat alamat IP pelayan anda. SearXNG kemudiannya menggantung enjin tersebut, selama sejam selepas jawapan terlalu banyak permintaan dan selama sehari selepas CAPTCHA. Tiada tetapan tempatan yang boleh membatalkan sekatan hulu (upstream), jadi buang enjin yang menyekat alamat anda dan kekalkan enjin yang memberikan jawapan.

Patutkah saya mendayakan pengehad pada instans peribadi?

Jika tiada apa-apa yang mencapai instans tersebut kecuali anda, biarkan limiter: false. Ia menambah dependency Valkey dan menyekat skrip anda sendiri, serta ia melindungi daripada trafik yang tidak anda miliki. Dayakan ia sebaik sahaja instans tersebut mendapat alamat awam, bersama-sama dengan public_instance: true. Pasangan itu adalah disengajakan: dengan public_instance: true dan Valkey tidak berfungsi, proses akan keluar dengan status 1 dan bukannya berjalan tanpa perlindungan.