Degoog Docs

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/suggest and /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.

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-result fires as each engine answers. Its payload carries engine, that engine's timing, the running merged results list, and retry metadata. Because results is the full merged list each time, a lazy consumer can keep the last one.
  • done is the final event, with totalTime, engineTimings, and relatedSearches.
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

  1. In Degoog, enable Serve the SearXNG API shape in Settings, Server.
  2. In Open WebUI, open the Admin Panel, then Settings, then Web Search, and enable it.
  3. Set Web Search Engine to searxng.
  4. Set the SearxNG Query URL to your instance followed by /api/search, for example http://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:

  • search returns model-readable results plus structured URLs, snippets, engine timings, and source overlap.
  • scrape fetches URLs concurrently and returns clean Markdown, with explicit error rows for failures. It accepts only http and https, 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.