Degoog Transports
Custom HTTP fetch strategies for your outgoing search requests.
What transports are
A transport controls exactly how Degoog makes its outgoing HTTP requests to search engines. You can select a specific transport for each engine by navigating to Settings then Engines then Configure then Advanced.
We include three built in transports out of the box:
| Name | Behaviour |
|---|---|
fetch |
The native Bun fetch implementation with full SOCKS 5 and HTTP proxy support. This is the default for all engines. |
curl |
Shells out directly to your system curl binary. This uses a different TLS stack which helps immensely when a website tries to block the default Bun fingerprint. |
auto |
Tries fetch first. If the server responds with a 403, 429, 502, or 503 error, it automatically retries the request using curl. |
You can install additional transports like FlareSolverr straight
from the
Store or place them manually inside your
data/transports/ directory.
Where transports live
Your custom transports belong in data/transports/ or
whatever path you set for DEGOOG_TRANSPORTS_DIR. Each
transport is just a file or folder containing an entry file that
exports a class or object implementing the transport contract.
Transport contract
Required properties:
- name: A unique identifier written in lowercase with no spaces.
-
available(): Return
trueor a Promise resolving totruewhen your transport is ready to use. If you returnfalse, the transport will be hidden from the engine dropdown menus. -
fetch(url, options, context) (async): Perform the
actual HTTP request and return a standard
Responseobject.
Optional properties:
- displayName: The friendly name shown in Settings then Transports.
- description: A short description displayed in Settings then Transports.
-
settingsSchema and
configure(settings): These follow the exact same
pattern as engines and plugins. A Configure button will appear in
Settings then Transports, and your values are stored safely in
data/plugin-settings.jsonundertransport-<name>.
Arguments
options
| Field | Type | Description |
|---|---|---|
method |
string |
The HTTP method which defaults to "GET". |
headers |
Record<string, string> |
Your request headers. |
body |
string |
The request body. |
redirect |
RequestRedirect |
The redirect mode which defaults to "follow".
|
signal |
AbortSignal |
The abort signal used for cancellation. |
context
| Field | Type | Description |
|---|---|---|
proxyUrl |
string | undefined |
The proxy URL configured in Settings then Server then Proxy.
This comes already rotated. It will be
undefined when proxies are disabled.
|
fetch |
(url, init?) => Promise<Response> |
A proxy aware fetch function. Always use this for all your outbound requests so the user proxy settings like SOCKS 5 or HTTP CONNECT are respected automatically. |
Proxies
When a user enables a proxy in Settings then Server,
context.proxyUrl is populated and
context.fetch
routes through it automatically. Your transport should always use
context.fetch for any outbound HTTP calls so proxy
routing just works effortlessly:
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 your data/transports/ directory or set your
DEGOOG_TRANSPORTS_DIR. Add a single file like
my-transport.js or create a folder with an
index.js file. Your transport settings ID will
automatically become transport-<name>.
How settings work
-
Declare your
settingsSchemaso a Configure button appears in Settings then Transports. -
When the user saves, the values go into
data/plugin-settings.jsonundertransport-<name>. -
Your
configure(settings)function is called right after saving and every time the server restarts if settings exist. -
Return
falsefromavailable()when required settings are missing so the transport does not show up in engine dropdowns until it is fully configured. - Users can easily disable configurable transports using the toggle switch in Settings then 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
lets you bypass Cloudflare challenges via a FlareSolverr instance.
It correctly uses
context.fetchso all proxy settings are respected.
If you are distributing your transport through the
Store, just add it under the
transports/ directory in your repository and list it in
the transports array inside your
package.json.