Degoog API reference
The endpoints worth calling from outside the browser, and how to authenticate against them.
Basics
Everything lives on the same host and port as the UI,
http://localhost:4444 by default. Responses are JSON unless
noted. Most of Degoog's HTTP surface is internal plumbing for the web UI; what
follows is the part that is genuinely useful to call yourself.
The rate limits you set in Server settings apply to API callers exactly as they do to browsers.
Authentication
By default the search and suggestion endpoints are open. In Settings, Server, API Key you can require authentication on either group independently:
-
Protect search routes covers
/api/search,/api/search/stream, and/api/search/retry. -
Protect suggestion routes covers
/api/suggestand/api/suggest/opensearch.
When protection is on, an unauthenticated request gets 401 with:
{ "error": "You shall not pass!" }
External callers authenticate with the instance's API key as a bearer token.
Reveal or regenerate it in the same settings section. That section only
appears once DEGOOG_SETTINGS_PASSWORDS is set, since otherwise
nothing would be protecting the key itself.
curl -H "Authorization: Bearer YOUR_API_KEY" \
"http://localhost:4444/api/search?q=adam+sandler"
The web UI does not use that header. It receives a short-lived signed nonce
with the page and sends it as x-search-nonce and
x-search-sig headers (or searchNonce and
searchSig query parameters). Either mechanism satisfies the
guard, so turning protection on does not break normal browsing.
GET /api/search
Runs a search and returns merged, scored, deduplicated results.
| Parameter | Description |
|---|---|
q |
Required. The query. |
type |
Search type. Defaults to web. Valid values depend entirely
on which engines you have installed.
GET /api/search-tabs lists the ones your instance can
serve.
|
page |
Starts at 1, capped at 10. |
time |
any, hour, day,
week, month, year, or
custom. With custom, pass
dateFrom and dateTo as
YYYY-MM-DD.
|
lang |
Language code. Overrides DEGOOG_DEFAULT_SEARCH_LANGUAGE for
this request.
|
imgSize, imgColor, imgType,
imgLayout
|
Image filters. Ignored unless the engines you are querying support them. |
safeMode |
Safe search level. imgNsfw is accepted as a legacy alias.
|
| Engine ids |
Pass any engine id as a parameter set to true or
false to override which engines run. Omit them all to use
the instance defaults. Ids come from
GET /api/extensions?type=engine.
|
curl "http://localhost:4444/api/search?q=adam+sandler"
Response:
{
"results": [
{
"title": "...",
"url": "https://...",
"snippet": "...",
"content": "...",
"source": "Brave",
"score": 92,
"sources": ["Brave", "DuckDuckGo"],
"favicon": "/api/proxy/favicon?domain=example.com&sig=...&s=64"
}
],
"query": "rust lifetimes",
"type": "web",
"totalTime": 812,
"engineTimings": [{ "name": "Brave", "time": 540, "resultCount": 10 }],
"relatedSearches": ["rust lifetime elision"]
}
content mirrors snippet. It exists so that Open
WebUI, which expects that field name, works without a custom tool.
favicon is a signed URL on your instance, or an empty string
when no favicon provider is enabled and the favicon store is off. See
Favicons.
SearXNG-shaped responses
Turn on Serve the SearXNG API shape in
Settings, Server and /api/search starts honouring a
format=json parameter, answering those requests with a
SearXNG-shaped document. Requests without the parameter are completely
unchanged.
This is what makes clients such as Open WebUI and local-deep-research work
with no glue code: they already send format=json.
The toggle is off by default. If a SearXNG-compatible client is getting the wrong response shape from Degoog, this is the switch you are missing.
POST /api/search
Same behaviour with a JSON body, which is easier when you want to restrict a long list of engines. Form-encoded bodies are also accepted.
curl -X POST http://localhost:4444/api/search \
-H "Content-Type: application/json" \
-d '{
"query": "rust lifetimes",
"type": "web",
"page": 1,
"lang": "en",
"engines": ["degoog-org-official-extensions-brave-engine"]
}'
engines is a list of engine ids to enable; anything not listed is
disabled for that request. Omit it entirely to use the instance defaults.
GET /api/search/stream
The server-sent events variant. Same query parameters as
GET /api/search. It emits two event types:
-
engine-resultfires as each engine answers. Its payload carriesengine, that engine'stiming, the running mergedresultslist, and retry metadata. Becauseresultsis the full merged list each time, a lazy consumer can keep the last one. -
doneis the final event, withtotalTime,engineTimings, andrelatedSearches.
curl -N "http://localhost:4444/api/search/stream?q=adam+sandler"
GET and POST /api/search/retry
Re-runs a single engine for a query that already ran. Requires
q and engine (or query and
engine in a JSON body), and accepts the same type, page, time,
and language parameters. This is what the retry links in the results sidebar
call.
GET /api/suggest
Autocomplete suggestions merged from every enabled provider. Returns an array of objects, not plain strings:
[
{ "text": "rust lifetimes", "source": "Google Autocomplete" },
{ "text": "rust lifetime elision", "source": "Google Autocomplete" }
]
A rich object is included when the provider supplies an entity
card and rich suggestions are enabled for it.
POST /api/suggest takes { "query": "..." } and
behaves identically.
Returns an empty array when no autocomplete provider is installed, which is the default state.
GET /api/suggest/opensearch
The same suggestions in the OpenSearch format browsers expect, served as
application/x-suggestions+json:
["rust", ["rust lifetimes", "rust lifetime elision"]]
GET /api/lucky
Runs a web search for q and redirects straight to the first
result. Returns 404 with a JSON error if nothing was found.
GET /api/extensions
Lists what is installed, grouped into engines,
plugins, themes, transports,
autocomplete, favicon and shortcuts. Each entry includes the
id. Engine IDs are the ones you pass to restrict a search.
Favicon providers can't be picked per search. Their order comes from
Settings, Favicons.
Add ?type= to fetch one group: engine,
plugin, theme, transport,
autocomplete, favicon or shortcut. An unknown type returns
400.
curl "http://localhost:4444/api/extensions?type=engine"
Extension settings are redacted from the response unless the caller is authenticated to the settings area, so you will see the extensions but not their configured API keys.
Favicons
GET /api/proxy/favicon
Returns the icon for domain from the
favicon providers.
Parameters are domain, sig, s and an
optional v cache buster. The server ignores s,
currently 64. It only changes the URL so browsers drop icons
cached at the old size.
sig is required, and the URLs in search results already carry
it. A request without a valid sig gets 403.
| Status | Meaning |
|---|---|
200 |
The icon as PNG, ICO, GIF, JPEG or WebP. Browsers cache it for a day. |
400 |
domain is not a valid hostname. |
403 |
sig is missing or does not match the domain. |
404 |
No provider found an icon, or no provider is installed. |
503 |
Too many favicon requests at once. Honour the
Retry-After header.
|
POST /api/favicon/refresh
Drops the cached and stored icon for one domain and asks the providers again. The Refresh favicon result action calls it. It needs a settings session and is rate limited.
{ "domain": "example.com" }
The response is { "url": "..." } with a fresh signed URL, or
{ "url": null } when no provider had an icon.
Other useful endpoints
| Endpoint | What it returns |
|---|---|
GET /api/search-tabs |
The result tabs this instance can serve, which is the authoritative list
of valid type values.
|
GET /api/tab-search?tab=&q=&page= |
Results for one specific tab. |
GET /api/engines |
The engine list in the shape the UI uses. |
GET /api/commands |
Every available bang command with its triggers, aliases, natural language phrases, and category. |
GET /api/command?q=!uuid |
Executes a bang command and returns its rendered output. |
GET /opensearch.xml |
The OpenSearch descriptor browsers use to add Degoog as a search engine. |
GET /health, /healthz, /ready,
/readyz
|
Liveness and readiness checks. All four exist for the lolz. |
Wiring Degoog into Open WebUI
- In Degoog, enable Serve the SearXNG API shape in Settings, Server.
- In Open WebUI, open the Admin Panel, then Settings, then Web Search, and enable it.
- Set Web Search Engine to
searxng. -
Set the SearxNG Query URL to your instance followed by
/api/search, for examplehttp://127.0.0.1:4444/api/search.
No custom tool required. If you enabled API key protection for search routes,
your client needs to send the Authorization: Bearer header, so
check it supports custom headers before turning that on.
Model Context Protocol
degoog-mcp is a small TypeScript sidecar that exposes Degoog to
MCP-capable clients over Streamable HTTP at /mcp, listening on
port 4443 by default. It offers eight tools, and these two do
most of the work:
-
searchreturns model-readable results plus structured URLs, snippets, engine timings, and source overlap. -
scrapefetches URLs concurrently and returns clean Markdown, with explicit error rows for failures. It accepts onlyhttpandhttps, resolves DNS before dialing, and blocks private and local IP ranges, rechecking on redirects.
The rest are bundle_search (search and read the sources in one
go, the one to point small models at), deep_search,
discover, retry_engine, command and
health.
It is configured through the mcp.yml it writes to
/data on first run and DEGOOG_MCP_* environment
variables, including an optional inbound bearer token, per-call result caps,
and an engine allowlist. The mcp.yml compose example runs it
alongside Degoog. Full details are in the
degoog-mcp README.
degoog-mcp is still in beta and not intended for production use yet.