SSD Nodes Learn Hosting plans →
Guides Matt ConnorBy Matt Connor

SearXNG engines to enable and disable on a VPS

Which SearXNG engines survive a datacenter IP and which get CAPTCHAs, plus the settings.yml keys (disabled, timeout, weight, suspended_times) that act on it.

Which SearXNG engines to keep on a VPS

Keep the SearXNG engines that call a public API (application programming interface), and treat every engine that scrapes a consumer search page as optional. As of September 2026, Wikipedia, Wikidata, GitHub, the Arch Linux wiki and Docker Hub answer a datacenter address the same way they answer a laptop. Google, Bing, Yahoo and Qwant ship with disabled: true in the upstream settings.yml, and Startpage and Mojeek ship with inactive: true, so the project has already made most of this call for you. DuckDuckGo and Brave are on by default, and they are the two engines most likely to show Suspended on a busy VPS.

That ranking changes monthly, because it describes how other companies treat hosting IP ranges rather than anything inside SearXNG. So this guide does two jobs. It shows where your instance records what each engine did from your address, and it explains the settings.yml keys you edit once you have read that record. The per-engine repairs live in their own posts: clearing a CAPTCHA on one engine and dealing with 429 errors and the limiter. If you have not installed SearXNG yet, start with running SearXNG on a VPS with Docker and come back with a working instance.

Why a datacenter IP changes the answer

SearXNG has no index of its own. Each query fans out to every enabled engine, and every engine is one of two kinds. An API engine calls an endpoint that was built for programs and has a published quota. A scraper engine fetches the same HTML page a browser would, sends browser-like headers, and parses results out of the page.

Scrapers are the problem on a VPS. A consumer search site scores each request on how much it looks like a bot. A request from a hosting provider's address range, with no browser session behind it, scores badly. The site answers with a CAPTCHA (a "prove you are human" page) or with an error status, usually HTTP 429 (too many requests) or 403 (forbidden). SearXNG cannot solve a CAPTCHA, so it turns each of those answers into an exception, and the exception into a suspension. The same instance on a home connection often sees none of this, which is why "works fine for me" in a forum thread can be true and still tell you nothing about your address.

Two things follow. A list of good and bad engines cannot be permanent, so every claim below carries a date and a source. And your instance already holds the only evidence that matters: its own error counts per engine, from your own IP.

Read what your instance already knows

SearXNG records engine failures in three places. Read them before you edit anything.

The results page. A failed engine is named in the error line above the results. A suspended one carries the prefix Suspended:, so the line reads google (Suspended: CAPTCHA), duckduckgo (Suspended: too many requests) or bing (Suspended: access denied). Those three suffixes are the user-facing names of the three exception classes described in the next section.

The stats pages. /stats lists every engine with its error rate and response times, and /stats/errors returns the same data as JSON, keyed by engine name. Both are on by default (general: enable_metrics: true). Run these on the VPS, against the port your compose file publishes:

sudo apt install -y jq
curl -s http://127.0.0.1:8080/stats/errors | jq 'keys'
curl -s http://127.0.0.1:8080/stats/errors | jq '.duckduckgo[] | {exception_classname, percentage}'

The first command prints the engines that have failed at least once since the process started. The second prints each error class for one engine, with percentage being the share of queries sent to that engine that ended in this error, rounded to the nearest 5. If the engine has no errors, the second command prints Cannot iterate over null, which is the answer you want. An engine missing from the first list has not failed since the last restart, and that is the right kind of evidence for keeping it. The same numbers feed the Reliability column on the Engines tab of the Preferences page.

The container log. A CAPTCHA or a block is logged at ERROR with a traceback that ends in the exception class, so counting class names over the last day gives you a ranking:

docker compose logs --since 24h searxng | grep -oE 'SearxEngine(Captcha|TooManyRequests|AccessDenied)Exception' | sort | uniq -c

A healthy private instance prints nothing. A line like 14 SearxEngineCaptchaException tells you what to look at next. Drop the -o and add -B3 to see the ERROR:searx.engines.<name> line that names the engine.

What "Suspended" means, and why a restart does not fix it

When an engine raises one of the access exceptions, SearXNG stops sending it queries for a fixed number of seconds. A suspended engine is paused, in the memory of the running process, with an end time and a reason. It stays enabled in your settings. Every query during that window gets the Suspended: line instead of a request to the engine, and the timer runs down on its own. When it expires, the next query is sent for real. If that query is answered with another CAPTCHA, the timer starts again.

Three exception classes carry their own default durations, set under search: suspended_times: in settings.yml. SearxEngineCaptcha covers a detected CAPTCHA page. SearxEngineTooManyRequests covers the string "Too many request" and any HTTP 429. SearxEngineAccessDenied covers "Access denied" and HTTP 402 or 403. Two site-specific variants exist for Cloudflare challenge pages, cf_SearxEngineCaptcha and cf_SearxEngineAccessDenied, and one for Google's reCAPTCHA, recaptcha_SearxEngineCaptcha. A timeout or a connection error uses a different, escalating pair: ban_time_on_fail (5 seconds, multiplied by the number of consecutive failures) capped at max_ban_time_on_fail (120 seconds). A parse error is counted in the stats and does not suspend anything.

ChartDefault suspension per error class in seconds: upstream settings.yml read 2026-09-20, and the docs example
The data behind this chart
[
  {
    "label": "SearxEngineAccessDenied",
    "shipped_seconds": 180,
    "docs_example_seconds": 86400
  },
  {
    "label": "SearxEngineTooManyRequests",
    "shipped_seconds": 180,
    "docs_example_seconds": 3600
  },
  {
    "label": "SearxEngineCaptcha",
    "shipped_seconds": 3600,
    "docs_example_seconds": 86400
  },
  {
    "label": "cf_SearxEngineAccessDenied",
    "shipped_seconds": 86400,
    "docs_example_seconds": 86400
  },
  {
    "label": "recaptcha_SearxEngineCaptcha",
    "shipped_seconds": 604800,
    "docs_example_seconds": 604800
  },
  {
    "label": "cf_SearxEngineCaptcha",
    "shipped_seconds": 1296000,
    "docs_example_seconds": 1296000
  }
]

The numbers to notice are the large ones. A Google reCAPTCHA parks the engine for 604800 seconds, which is seven days, and a Cloudflare CAPTCHA for 1296000 seconds, fifteen days. A plain 429 costs 180 seconds in the shipped file, and a generic CAPTCHA 3600. The documentation page for the search: section shows a different example, with 86400 seconds for access denied. The shipped file is what loads when you set use_default_settings: true, so trust the settings.yml in the repository at the tag you run, and expect these values to move.

Why a restart does not help. The timer lives in process memory, so a restart does clear it. That is the trap. The first query after the restart goes to the engine for real, the engine answers with the same CAPTCHA, because your IP is still the IP it blocked, and the engine is suspended again within one search. You see a working instance for a few seconds and then the same line. The block is on the engine's side, keyed to your address. Only two things change it: time, or a different egress address. A third case, a block that SearXNG's own request headers triggered, needs an image upgrade rather than a restart. That is why the CAPTCHA post is about SSH tunnels and upgrades, and why docker compose restart is not in it. One more detail: SearXNG keys the timer by network, so engines that share a network: setting in settings.yml share one suspension.

Engines that CAPTCHA or throttle from a datacenter, September 2026

Each entry names its evidence. "Upstream" means the searx/settings.yml on the project's master branch, read on 2026-09-20.

  • Google. Upstream ships disabled: true. The Google engine documentation lists three ways Google blocks a request: a redirect to sorry.google.com, an HTTP 302 to /sorry/index on the same host, and a short HTML stub containing /sorry/. Each raises the reCAPTCHA exception, and the shipped default parks the engine for a week. The tracker adds a quieter failure. Issue #6171, closed 2026-09-13, describes Google returning a normal HTTP 200 page with zero parsed results, so nothing is suspended and nothing is logged as an error. Issue #6567, open since 2026-08-22, proposes a solver that runs in the user's browser, which tells you the maintainers do not expect a server-side fix.
  • DuckDuckGo. Upstream ships it enabled. The DuckDuckGo engine documentation is blunt: the bot blocker blocks the IP, not a session, and the documented way to unblock is to run a DuckDuckGo query in a real browser from that IP. Issue #6596, opened 2026-08-30 and closed 2026-09-04, is the recent example. Instances started getting SearxEngineCaptchaException from DuckDuckGo, the cause was on SearXNG's side (the order of the request headers it sent), and the fix arrived with the curl-impersonate work in the image. The cure was docker compose pull, not a settings change.
  • Brave. Upstream ships it enabled. The Brave engine documentation caps paging at 10 and warns that asking for more "won't return any result and you will most likely be flagged as a bot". Do not let an automated client page deep into it.
  • Qwant. Upstream ships disabled: true. The admin documentation has a page titled Answer CAPTCHA from server's IP, and Qwant is the engine it names, with an SSH SOCKS proxy as the workaround.
  • Startpage. Upstream ships inactive: true, which is stronger than disabled: the engine is not loaded at all. The reason is cost rather than a block. The Startpage engine documentation says Startpage "requires solving an Anubis POW captcha (difficulty 4)", a proof-of-work challenge, and "solving it requires a lot of CPU, so the engine is set inactive by default". On a small VPS that CPU is your web server's CPU.
  • Bing, Yahoo and Mojeek. In the same read, Bing and Yahoo ship disabled: true and Mojeek ships inactive: true. The file does not say why. When you want this month's reason, search the tracker for the engine name and sort by recently updated.

Engines that hold up from a datacenter

The engines that survive are the ones talking to an API with a published quota. When you exceed the quota you get a status code, and SearXNG's short 429 suspension handles it without your help.

  • Wikipedia and Wikidata. Both on by default, and upstream gives Wikidata weight: 2 and timeout: 3.0. Wikimedia asks API clients to identify themselves, and outgoing: useragent_suffix: exists for exactly this. The settings documentation says contact info there "may be useful to avoid an engine blocking you". It only applies to engines that send SearXNG's own User-Agent, which is the API group; scrapers send a browser string.
  • GitHub. On by default. GitHub's REST documentation puts unauthenticated requests at 60 per hour per address and answers with a 403 or a 429 above that. In SearXNG terms that is access denied or too many requests, each 180 seconds in the shipped defaults, after which the engine recovers on its own. A private instance with a few people will not reach 60 an hour. An instance wired to an AI agent that searches on every step can reach it in minutes.
  • Arch Linux wiki, Docker Hub, Stack Overflow, OpenStreetMap and currency. All on by default, all API-backed. These are the engines a self-hoster actually wants from a search box on a server. If one of them appears in /stats/errors, read the error class before assuming a block: an API engine failing with a timeout is a timeout problem, and the per-engine key below fixes it.

use_default_settings: how your overrides merge

SearXNG loads settings.yml from the path in SEARXNG_SETTINGS_PATH, or from /etc/searxng/settings.yml, which is where the Docker setup mounts the file that sits beside your compose file. The first line of that file matters most:

use_default_settings: true

With that line, your file is a set of overrides on top of the file the image ships. For most sections that means key-by-key replacement. For engines: it means a merge by name: an entry in your file is matched to the upstream entry with the same name, and only the keys you write are changed. You never copy the whole list of several hundred engines, and an image upgrade that adds or fixes engines reaches you without an edit.

use_default_settings: true

engines:
  - name: google
    disabled: true
  - name: duckduckgo
    timeout: 4.0
  - name: arch linux wiki
    weight: 2

Two list forms change what is loaded rather than what is on by default. remove: drops the named engines completely, and keep_only: drops everything except the named ones. They live under use_default_settings itself, and the rest of the file stays the same:

use_default_settings:
  engines:
    remove:
      - google
      - google images
      - google videos

engines:
  - name: duckduckgo
    timeout: 4.0

Without use_default_settings, no merge happens. A file that omits the key and then lists three engines gives you an instance with those three engines and nothing else, which is a surprise the first time and a feature for a locked-down private instance.

disabled, inactive, timeout and weight

The engine settings reference documents every per-engine key. Four of them do the work here.

disabled: true keeps the engine loaded but off by default. A user can switch it on in Preferences, and a !go bang still selects it explicitly. Use it for an engine you want to reach on purpose, but not on every query.

inactive: true removes the engine from the instance. It does not load, it does not appear in Preferences, and it has no bang. Engines that need an api_key ship inactive, and so does Startpage. remove: under use_default_settings has the same effect from your side of the file.

timeout overrides outgoing: request_timeout for one engine, and the shipped default for that global value is 3.0 seconds. A slow but honest API deserves a longer timeout rather than a suspension every time it is busy. Raising a scraper's timeout does not help with a CAPTCHA, which arrives as a fast, successful HTTP response.

weight multiplies the score of that engine's results when SearXNG merges the lists. The default is 1, and Wikidata ships with 2. Give a trusted API engine weight: 2 to push it up, or a noisy one weight: 0.5 to push it down, and leave the rest alone: a weight only moves results within the merged list, and a suspended engine has no results to move.

Tuning suspended_times

The block itself is plain YAML under search:. Each key takes seconds, and the documentation notes that 0 disables suspension for that class.

search:
  suspended_times:
    SearxEngineTooManyRequests: 600
    SearxEngineCaptcha: 7200

Raise a value when an engine's block is known to last longer than the default, so SearXNG stops poking it. Do not set a value to 0 on a public instance. Every query then makes a doomed request, waits for the CAPTCHA page, and shows the user an error, while the engine sees a steady stream of requests from your address. Whether the answer is a longer suspension or fewer queries is the subject of the 429 post, which also covers SearXNG's own limiter, the one that protects your instance rather than the engines.

A settings.yml for a private instance on a VPS

Put the pieces together. Keep whatever server: and redis: blocks your install already has, and add or edit these:

use_default_settings: true

search:
  suspended_times:
    SearxEngineTooManyRequests: 600

outgoing:
  request_timeout: 3.0
  useragent_suffix: "admin@example.com"

engines:
  - name: google
    disabled: true
  - name: duckduckgo
    timeout: 4.0
  - name: brave
    timeout: 4.0
  - name: arch linux wiki
    weight: 2

Restart the container and confirm the merge landed. /config returns the running configuration as JSON, with one object per loaded engine, and enabled there is the inverse of disabled:

docker compose restart searxng
docker compose ps
curl -s http://127.0.0.1:8080/config | jq -c '.engines[] | select(.name == "google" or .name == "duckduckgo") | {name, enabled, timeout}'

You should see "enabled":false on the google object and "timeout":4.0 on the duckduckgo object. An engine you removed or set inactive is absent from the list entirely. If the container is not running after the restart, the log shows the YAML parser's error with a line number; two-space indentation and a space after every colon fix most of those.

If the instance is reachable from the internet, engine choice is the smaller half of the job, and hardening a public SearXNG instance covers the limiter, the bot detection and the reverse proxy in front of it.

FAQ

Why does SearXNG say an engine is "Suspended", and how long does it last?

An engine answered with a CAPTCHA, an HTTP 429, or an HTTP 403, and SearXNG paused it so that later queries do not repeat the failure. The pause length comes from search: suspended_times: in settings.yml, per error class. In the upstream file read on 2026-09-20 a 429 pauses an engine for 180 seconds, a generic CAPTCHA for 3600, a Cloudflare CAPTCHA for 1296000, and a Google reCAPTCHA for 604800. The results page shows the reason in the error line, as google (Suspended: CAPTCHA), and /stats/errors shows the count per class.

Does restarting the SearXNG container clear a suspended engine?

It clears the timer, because the timer lives in the memory of the running process. It does not clear the block, because the block belongs to the engine and is keyed to your server's IP address. The first query after the restart is sent to the engine for real, answered with the same CAPTCHA, and the engine goes back into suspension within one search. Changing that needs time, a different egress address, or, when the block was caused by the headers SearXNG sent, a newer image.

What is the difference between disabled: true, inactive: true and remove:?

disabled: true loads the engine but leaves it switched off by default; users can enable it in Preferences and a !bang still reaches it. inactive: true does not load the engine at all, so it has no Preferences entry and no bang. remove: under use_default_settings: engines: does the same as inactive from your override file, without touching the upstream entry. keep_only: is the inverse: it drops every engine except the ones you list.

Should I enable Google in SearXNG on a VPS?

Leave it off unless your instance's own /stats/errors shows it working from your address. As of September 2026 the upstream settings.yml ships Google with disabled: true, the engine documentation lists three block responses that all lead to a reCAPTCHA suspension of 604800 seconds, and the open feature request for a browser-side solver shows the project does not expect a server-side fix. Users who want it can still reach it with the !go bang while it stays disabled.

Which SearXNG engines work from a datacenter IP without CAPTCHAs?

The API-backed ones: Wikipedia, Wikidata, GitHub, the Arch Linux wiki, Docker Hub, Stack Overflow and OpenStreetMap. They enforce a published quota with a status code rather than a bot score with a CAPTCHA, and when a quota is hit SearXNG suspends the engine for 180 seconds and then recovers on its own. Set outgoing: useragent_suffix: to a contact address so those APIs can identify your instance, and check your own instance's error stats before trusting any list, including this one.

#searxng#self-hosted-search#settings-yml#captcha#rate-limits#self-hosting