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:
- name — Unique identifier (lowercase, no spaces).
-
available() — Return
true(or a Promise resolving totrue) when the transport is ready to use. Returnfalseto hide it from engine transport dropdowns. -
fetch(url, options, context) (async) —
Perform the HTTP request and return a
Response.
Optional:
- displayName — Friendly name shown in Settings → Transports.
- description — Short description shown in Settings → Transports.
-
settingsSchema,
configure(settings) — Same pattern as engines
and plugins. A Configure button appears in Settings →
Transports; values are stored in
data/plugin-settings.jsonundertransport-<name>.
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
-
Declare
settingsSchema— a Configure button appears in Settings → Transports. -
User saves; values go to
data/plugin-settings.jsonundertransport-<name>. -
configure(settings)is called after save and on server restart if settings exist. -
Return
falsefromavailable()when required settings are missing — the transport won't appear in engine dropdowns until configured. - 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
-
FlareSolverr
— bypass Cloudflare challenges via a FlareSolverr instance.
Uses
context.fetchso proxy settings are respected.
When distributing via the Store, add your
transport under transports/ in the repo and list it in
the transports array in package.json.