Degoog — Transports

Custom HTTP fetch strategies for outgoing search requests.

What transports are

A transport controls how degoog makes outgoing HTTP requests to search engines. Each engine can pick its transport in Settings → Engines → Configure → Advanced.

Three transports are built in:

Name Behaviour
fetch Bun's native fetch with SOCKS 5 / HTTP proxy support. Default for all engines.
curl Shells out to the system curl binary. Uses a different TLS stack, which helps when a site blocks Bun's fingerprint.
auto Tries fetch first; if the response is 403 / 429 / 502 / 503, retries with curl.

Additional transports (e.g. FlareSolverr) can be installed from the Store or placed manually in data/transports/.

Where transports live

Custom transports live in data/transports/ (or DEGOOG_TRANSPORTS_DIR). Each transport is a file or folder with an entry file that exports a class or object implementing the transport contract.

Transport contract

Required:

Optional:

Arguments

options

Field Type Description
method string HTTP method (default "GET").
headers Record<string, string> Request headers.
body string Request body.
redirect RequestRedirect Redirect mode (default "follow").
signal AbortSignal Abort signal for cancellation.

context

Field Type Description
proxyUrl string | undefined The proxy URL from Settings → Server → Proxy, already rotated. undefined when proxies are disabled.
fetch (url, init?) => Promise<Response> A proxy-aware fetch function. Use this for all outbound requests so the user's proxy settings are respected automatically (SOCKS 5, HTTP CONNECT, or direct).

Proxies

When the user enables a proxy in Settings → Server, context.proxyUrl is set and context.fetch routes through it automatically. Your transport should use context.fetch for any outbound HTTP call so that proxy routing just works:

async fetch(url, options, context) {
  const doFetch = context.fetch;
  const res = await doFetch("https://my-service.example.com/api", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ target: url }),
    signal: options.signal,
  });
  // transform and return a Response
}

Setup

Create data/transports/ (or set DEGOOG_TRANSPORTS_DIR). Add a single file (e.g. my-transport.js) or a folder with index.js (or .ts, .mjs, .cjs). The transport settings id is transport-<name>.

How settings work

  1. Declare settingsSchema — a Configure button appears in Settings → Transports.
  2. User saves; values go to data/plugin-settings.json under transport-<name>.
  3. configure(settings) is called after save and on server restart if settings exist.
  4. Return false from available() when required settings are missing — the transport won't appear in engine dropdowns until configured.
  5. Users can disable configurable transports with the toggle in Settings → Transports.

Example: minimal transport

export default class MyTransport {
  name = "my-transport";
  displayName = "My Transport";
  description = "Example custom transport.";

  settingsSchema = [
    {
      key: "apiUrl",
      label: "API URL",
      type: "url",
      required: true,
      placeholder: "https://my-service.example.com",
    },
  ];

  _apiUrl = "";

  configure(settings) {
    this._apiUrl = (settings.apiUrl || "").trim();
  }

  available() {
    return this._apiUrl.length > 0;
  }

  async fetch(url, options, context) {
    const doFetch = context.fetch;

    const res = await doFetch(this._apiUrl, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ url, timeout: 10000 }),
      signal: options.signal,
    });

    if (!res.ok) return new Response("", { status: res.status });
    const data = await res.json();
    return new Response(data.html ?? "", {
      status: data.status ?? 200,
      headers: { "Content-Type": "text/html" },
    });
  }
}

Examples from the official store

When distributing via the Store, add your transport under transports/ in the repo and list it in the transports array in package.json.