<!-- twin of https://specstream.ai/migrate/searxng -->
# Migrate from SearXNG: one address, the same JSON, no instance to run

Compared on Nov 10, 2026. The page: https://specstream.ai/migrate/searxng

Since November 9, 2026 SpecStream answers SearXNG's JSON search at `https://api.specstream.ai/searxng`, with no instance, no Valkey and no upstream engines to keep unblocked. Each call is one search of 10 results at $0.005.

Set your instance address to `https://api.specstream.ai/searxng/<key>`. The key can also go in `key=`, in `X-API-Key`, as a Bearer token, or as the Basic password or user name.

It is the most accurate web search API in the world: 97.9 F-score on all 1,000 SimpleQA Verified questions and 64.0 item F1 on all 200 WideSearch tasks, on the [benchmarks](https://specstream.ai/benchmarks?utm_source=alternatives&utm_campaign=migrate-searxng) page.

[Get an API key](https://specstream.ai/signup?src=alternatives-migrate-searxng&utm_source=alternatives-md&utm_campaign=migrate-searxng&returnTo=%2Fworkspace%2Fsearch%3Froute%3Dsearxng) New accounts get $10 of credit, no card. It covers 2,000 searches.

## A SearXNG instance to SpecStream, parameter by parameter and field by field

| | SpecStream (`/searxng`) | SearXNG |
|---|---|---|
| Address | `https://api.specstream.ai/searxng/<key>`, or `.../searxng/<key>/search` where the setting takes the whole search address. `/searxng` and `/searxng/search` answer `GET` and a form `POST` | `GET /`, `GET /search`, `POST /` and `POST /search` on your instance |
| Key | Read in this order: a path part (`/searxng/<key>/search`), `key=` in the address, `X-API-Key`, then `Authorization` as Bearer or as HTTP Basic (the password, else the user name, so `https://<key>@api.specstream.ai/searxng` and `https://:<key>@api.specstream.ai/searxng` both work). A wrong key gets a `401` | No key. A public instance is open to everyone who has access to its URL |
| `format` | `json`, always on, and the default when the field is left out. `html`, `csv` and `rss` get a `403` with "Send format=json." | Must be listed under `search: formats` in settings.yml. An unset format returns `403 Forbidden`, and many public instances have these formats disabled |
| `q` | Read as the search, with operators such as `site:` | Passed to the external search services, with the syntax of each service |
| `pageno` | Read, default 1, in pages of 10 results. Page 1 runs the fast search; each page is $0.005. A page past the last result gets a `400` | Search page number, default 1 |
| `time_range` | Read: `day`, `week`, `month` or `year`, applied as a date filter on the search | Time range of search for engines which support it |
| `categories`, `language`, `safesearch`, `engines` | Accepted with no error. The first of `categories` is printed as each result's `category`; the others do not change the search | `categories` is a comma separated list; `language` and `safesearch` (0, 1 or 2) default from the `search:` settings |
| The reply | `query`, `number_of_results`, `results[]`, `answers` (the answer, on page 1 when the search has one), `corrections`, `infoboxes`, `suggestions` and `unresponsive_engines`, plus `specstream` with the request ID and the price | `query`, `results`, `answers`, `corrections`, `infoboxes`, `suggestions` and `unresponsive_engines` |
| Each result | `url`, `title`, `content`, `engine` (`specstream`), `engines`, `parsed_url`, `template`, `positions`, `score` (highest first), `category` and `publishedDate`, which is null on most results. `thumbnail` and `img_src` are empty | The results of each engine the instance queried, merged and ordered |
| Always empty here | `corrections`, `infoboxes`, `suggestions` and `unresponsive_engines` come back as empty lists, so a parser that reads them keeps working | `unresponsive_engines` lists the engines that failed, with their errors |
| Upstream blocking | None to manage. One account takes up to 8,800 searches a minute; a call over that gets a `429` with `Retry-After` and is not charged | An engine that answers with a CAPTCHA is suspended for 86400 seconds by default, too many requests for 3600, access denied for 86400 |
| What you run | Nothing. `GET /searxng/config` answers for clients that check the address, at no charge | Docker or Podman, a Valkey database for the limiter, and a reverse proxy that sets `X-Forwarded-For` |
| Price | $0.005 a call of 10 results, paid from a balance. $10 of credit on sign up, no card, covers 2,000 searches | Free software you host yourself |

## What changes and what stays when you move from SearXNG

### The whole migration is one address

Your client keeps SearXNG's path, its `format=json` and its parser. The instance address changes, and it carries the key, so a client with only an address field needs no other setting.

```
# Before
curl "https://searx.example.org/search?q=open+source+vector+databases&format=json"

# After: the key in the path
curl "https://api.specstream.ai/searxng/$SPECSTREAM_API_KEY/search?q=open+source+vector+databases&format=json"

# Or in a header
curl "https://api.specstream.ai/searxng/search?q=open+source+vector+databases&format=json" \
  -H "X-API-Key: $SPECSTREAM_API_KEY"
```

Tested on production on November 9, 2026: the key in the path for LobeHub, Perplexica, OpenClaw and Open WebUI, the key as the Basic password for GPT Researcher and LangChain's SearxSearchWrapper, and `/searxng/config` for Cherry Studio's check button.

### What the reply leaves out

The route serves JSON. A client that reads SearXNG's HTML page, as Khoj does, gets a `403`. `publishedDate` is null on most results, so read it as optional, and `thumbnail` and `img_src` are empty strings. `corrections`, `infoboxes`, `suggestions` and `unresponsive_engines` are empty lists.

A refusal is `{"error": ..., "code": ...}` with the HTTP status: `401` for a missing or wrong key, `402` for an empty balance, `403` for a format other than JSON, and `429` with `Retry-After` for a busy minute, which charges nothing.

### Nothing to host or keep unblocked

SearXNG's own docs say a public instance can make the external service enforce CAPTCHAs or ban the instance's IP address, and a private one needs Docker or Podman, Valkey for the limiter and a reverse proxy. SpecStream is one address: the search runs on our side, and your app gets results in SearXNG's JSON.

### $0.005 a search, with no server to pay for

Each call returns one page of 10 results and costs $0.005, the price of one search. New accounts start with $10 of credit, no card, which covers 2,000 searches, and credit you buy never expires. Every rate is on the [pricing](https://specstream.ai/pricing?utm_source=alternatives&utm_campaign=migrate-searxng) page.

### The most accurate web search API in the world

On SimpleQA Verified the SpecStream Search API scores 97.9 F-score on all 1,000 official questions, 978 of them correct. On WideSearch it scores 64.0 item F1 and 43.4 row F1 on all 200 official tasks. The Extract API scores 0.908 F1 on WCXB. Every score and its method is on the [benchmarks](https://specstream.ai/benchmarks?utm_source=alternatives&utm_campaign=migrate-searxng) page.

### About one second a search, measured under load

Every drop-in route runs the fast search unless the call asks for page text or results past the first ten. On November 9, 2026 production took 1 to 20 fast searches a second and answered 718 of 720: the median was 0.82 s at 1 search a second and 1.07 s at 20 a second, and the 95th percentile stayed between 1.09 and 1.73 s. One account takes up to 8,800 searches a minute; a call over that gets a `429` with `Retry-After` and is not charged.

### You decide what is kept, on each key

Create a key with `zero_retention` and a search made with it keeps no request text and no answer after the reply: it is not in the history, its answer is not reused for another call, and its log lines carry neither. `spend_cap_cents` is the most the key can spend.

```
curl -X POST https://api.specstream.ai/v1/account/keys \
  -H "Authorization: Bearer $SPECSTREAM_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "production", "scopes": ["account:read", "finds:spend"], "spend_cap_cents": 500000, "zero_retention": true}'
```

### Search, pages and rows on one key

The same key calls `GET /v1/web-search`, which returns up to 100 results for one search and an `answer` with the page it was read from. It reads up to 20 pages or documents a call with the [Extract API](https://specstream.ai/extract-api?utm_source=alternatives&utm_campaign=migrate-searxng) at $0.80 per 1,000 pages, and a page with no text is not charged. [Deep Search](https://specstream.ai/deep-search?utm_source=alternatives&utm_campaign=migrate-searxng) returns every match for a request in plain words as structured rows at 5¢, 15¢ or $1 a row, with a source URL on every value, and the most a run can cost is approved before it starts.

## Other hosted options in place of SearXNG

### Brave Search API

A search API on Brave's own index at $5 per 1,000 requests, with $5 in free credits every month. Your SearXNG client cannot call it without code; SpecStream answers that client at one address in SearXNG's JSON.

### Tavily

A search API at $0.008 a credit on pay as you go, where a basic search costs 1 credit. It has its own request and reply. SpecStream answers both SearXNG's call and Tavily's, at $0.005 a search.

### Exa

A search API from $4 per 1,000 requests with up to 10 results. It has its own request and reply. SpecStream keeps your SearXNG client as it is and scores 97.9 F-score on all 1,000 SimpleQA Verified questions.

## How to move from SearXNG

1. Create a key under Agents & API in the workspace. A new account gets $10 of credit, no card, which covers 2,000 searches.

2. Set the instance address to `https://api.specstream.ai/searxng/<key>`, or `https://api.specstream.ai/searxng/<key>/search` where the setting holds the whole search address. In Python:

```
import os
import requests

BASE = "https://api.specstream.ai/searxng"  # was https://searx.example.org

reply = requests.get(
    f"{BASE}/search",
    params={"q": "open source vector databases", "format": "json", "pageno": 1},
    headers={"X-API-Key": os.environ["SPECSTREAM_API_KEY"]},
).json()

for result in reply["results"]:
    print(result["title"], result["url"], result["content"])
```

In JavaScript:

```
const BASE = "https://api.specstream.ai/searxng"; // was https://searx.example.org

const params = new URLSearchParams({ q: "open source vector databases", format: "json" });
const reply = await fetch(`${BASE}/search?${params}`, {
  headers: { "X-API-Key": process.env.SPECSTREAM_API_KEY },
}).then((response) => response.json());

for (const result of reply.results) {
  console.log(result.title, result.url, result.content);
}
```

3. Keep `format=json`, `pageno` and `time_range`. Treat `publishedDate` as optional.

4. Turn off the instance when your app runs on the new address. Each reply carries the price of the call under `specstream`.

## Frequently asked questions

### What is the best SearXNG alternative for an app or an agent?

SpecStream, at $0.005 a search of 10 results. It answers SearXNG's JSON search at `https://api.specstream.ai/searxng` in the same shape, so the client keeps its setting, and it scores 97.9 F-score on all 1,000 SimpleQA Verified questions.

### Is there a SearXNG alternative I do not have to self host?

Yes. SpecStream's SearXNG address runs nothing on your side: no Docker, no Valkey and no reverse proxy. Set the instance address to `https://api.specstream.ai/searxng/<key>` and it answers in SearXNG's JSON.

### Why does SearXNG return 403 for format=json?

Because `json` is not listed under `search: formats` in the instance's settings.yml, and SearXNG returns 403 for a format that is not set. SpecStream's address always answers `format=json`.

### Where does the SpecStream key go?

In five places, read in this order: the path (`/searxng/<key>`), `key=` in the address, `X-API-Key`, a Bearer token, or HTTP Basic as the password or the user name.

### Is there a free SearXNG alternative?

New SpecStream accounts get $10 of credit with no card, which covers 2,000 searches. After that a search costs $0.005, and credit you buy never expires.

### Does SearXNG have an API rate limit?

An instance can turn on its limiter, which needs a Valkey database, and upstream engines that answer with a CAPTCHA are suspended for 86400 seconds by default. SpecStream takes up to 8,800 searches a minute on one account.

## Sources

SpecStream wrote this page. The route's behavior is read from its code; SearXNG's behavior from its own docs and source, and each other figure from that company's own page.

- [SearXNG Search API](https://docs.searxng.org/dev/search_api.html), read Nov 10, 2026
- [SearXNG settings, search](https://docs.searxng.org/admin/settings/settings_search.html), read Nov 10, 2026
- [SearXNG, why use a private instance](https://docs.searxng.org/own-instance.html), read Nov 10, 2026
- [SearXNG, installation with Docker](https://docs.searxng.org/admin/installation-docker.html), read Nov 10, 2026
- [SearXNG limiter](https://docs.searxng.org/admin/searx.limiter.html), read Nov 10, 2026
- [SearXNG source, JSON reply](https://raw.githubusercontent.com/searxng/searxng/master/searx/webutils.py), read Nov 10, 2026
- [SearXNG on GitHub](https://github.com/searxng/searxng), read Nov 10, 2026
- [Brave Search API](https://brave.com/search/api/), read Nov 9, 2026
- [Tavily API credits](https://docs.tavily.com/documentation/api-credits.md), read Nov 9, 2026
- [Exa pricing](https://exa.ai/docs/admin/pricing.md), read Nov 9, 2026
- [SpecStream benchmarks](https://specstream.ai/benchmarks), read Nov 10, 2026
- [SpecStream pricing](https://specstream.ai/pricing), read Nov 10, 2026
- [SpecStream for agents](https://specstream.ai/agents.md), read Nov 10, 2026
