API Reference
Every public export, with the exact shape from src/index.ts, src/connect.ts, src/node-http.ts, and src/proxy-socket.ts.
#Functions
#installProxyline(options): ProxylineHandle
Aliased as installGlobalProxy. Installs the runtime and returns a handle.
- Throws
ProxylineErrorwith codeMANAGED_PROXY_URL_REQUIREDifmode: "managed"is used without aproxyUrl. - Throws
ProxylineErrorwith codeUNSUPPORTED_PROXY_PROTOCOLif managed-modeproxyUrlis nothttp://orhttps://. - Throws
ProxylineErrorwith codeRUNTIME_ALREADY_ACTIVEif another Proxyline runtime is already installed andifActiveis omitted or cannot safely reuse the active runtime.
In managed mode (and active ambient mode), installProxyline:
- Captures originals for
http.request,http.get,http.globalAgent,https.request,https.get,https.globalAgent. - Captures the current undici global dispatcher and fetch globals.
- Installs patched
http.request/get,https.request/get. - Replaces
http.globalAgentandhttps.globalAgentwith Proxyline's HTTP/HTTPS Node agent. - Calls
undici.setGlobalDispatcherwith aProxyAgent(managed) or Proxyline's ambient dispatcher (ambient), and patchesglobalThis.fetchplusRequest,Response,Headers, andFormDatato use that dispatcher-compatible fetch stack. - Emits
runtime.installed.
In inactive ambient mode (no supported proxy env variables), no patches are installed; the handle returns a passive observer with active: false.
#openProxyConnectTunnel(options): Promise<net.Socket | tls.TLSSocket>
Opens a one-shot HTTP CONNECT tunnel through a proxy. See Surfaces — HTTP CONNECT tunnel.
#hasAmbientNodeProxyConfigured(options?): boolean
Returns true when the ambient proxy environment would proxy a probe URL for the requested protocol. Defaults to protocol: "https".
hasAmbientNodeProxyConfigured({ protocol: "https" });
#createAmbientNodeProxyAgent(options?): http.Agent | undefined
Returns a Proxyline-backed Node agent when ambient env proxy settings apply, or undefined when no proxy is configured for the requested protocol. This is for libraries that accept a Node agent option but should stay direct when the operator has no proxy env configured.
const agent = createAmbientNodeProxyAgent({
protocol: "https",
proxyTls: { caFile: "/etc/proxy-ca.pem" },
});
Supply resolveProxyConnectOptions when the application has already approved a proxy's DNS lookup or needs client certificates or an explicit TLS server name. The resolver receives the selected proxy URL as a string. Its returned properties are copied once per cached proxy URL and transport (HTTP-forward or CONNECT). Keep referenced certificate and key buffers unchanged for the agent's lifetime. Direct requests do not call the resolver. Treat the URL as sensitive when it contains proxy credentials; use redactProxyUrl before logging it.
The resolver is synchronous: finish asynchronous policy checks and DNS planning before making the request. Request cancellation still belongs to the Node ClientRequest; destroy the request or agent to close pending connections.
#redactProxyUrl(value: string | URL): string
Strips userinfo, search, and fragment from a URL. Used internally to keep events and decisions free of credentials. Safe to use on log lines you build yourself.
redactProxyUrl("https://user:secret@proxy.example:8443/path?q=1#frag");
// → "https://proxy.example:8443/path"
#resolveProxyTlsCa(options): string | undefined
Resolves a ProxylineTlsOptions value to a PEM string by reading caFile from disk if needed. Returns undefined when no CA material is supplied. Exposed so callers can pre-resolve before passing values into their own TLS-using code.
#Classes
#ProxylineError extends Error
class ProxylineError extends Error {
readonly code: string;
readonly name: "ProxylineError";
}
Codes:
MANAGED_PROXY_URL_REQUIRED—mode: "managed"was used withoutproxyUrl.UNSUPPORTED_PROXY_PROTOCOL— proxy URL scheme is nothttp://orhttps://.RUNTIME_ALREADY_ACTIVE— another Proxyline runtime is already installed.CONNECT_FAILED—openProxyConnectTunnelfailed (bad response, timeout, header overrun, or socket error).INVALID_CONNECT_TARGET—openProxyConnectTunnelreceived an empty or unsafe target host, invalid bracket syntax, or an invalid target port.
#Types
#ProxylineMode
type ProxylineMode = "managed" | "ambient";
See Modes.
#ProxylineSurface
type ProxylineSurface =
| "node-http"
| "node-https"
| "undici"
| "websocket"
| "connect"
| "unknown";
Used in explain() decisions and event payloads to identify which network surface a decision is for. Pass it via explain(url, { surface }).
#ProxylineOptions
type ProxylineOptions = Readonly<{
mode: ProxylineMode;
proxyUrl?: string | URL;
proxyTls?: ProxylineTlsOptions;
bypassPolicy?: ProxylineBypassPolicy;
ifActive?: "error" | "reuse-compatible" | "replace";
onEvent?: (event: ProxylineEvent) => void;
undici?: ProxylineUndiciOptions;
}>;
mode— required."managed"or"ambient".proxyUrl— required in managed mode, ignored in ambient mode. Managed-mode URLs must behttp://orhttps://.proxyTls— CA trust scoped to the proxy endpoint. See Proxy TLS.bypassPolicy— managed-mode escape hatch for trusted traffic that should go direct. Ignored in ambient mode.ifActive— process singleton behavior when Proxyline is already active. Defaults to"error"."reuse-compatible"returns the active handle when mode/proxy/TLS/bypass/undici settings match; ambient mode also requires the captured proxy env snapshot to match."replace"stops the active runtime before installing the new one.onEvent— callback fired with everyProxylineEvent.undici— default options for Proxyline-owned undici dispatchers.
#ProxylineUndiciOptions
type ProxylineUndiciOptions = Readonly<{
allowH2?: boolean;
bodyTimeout?: number;
headersTimeout?: number;
connect?: Readonly<{
autoSelectFamily?: boolean;
autoSelectFamilyAttemptTimeout?: number;
}>;
}>;
These options apply to the global dispatcher installed by installGlobalProxy() and to dispatchers returned by createUndiciDispatcher().
#ProxylineTlsOptions
type ProxylineTlsOptions = Readonly<{
ca?: string; // PEM string
caFile?: string; // path read with fs.readFileSync(..., "utf8")
}>;
When both are provided, ca wins.
#ProxylineDecision
type ProxylineDecision = Readonly<{
kind: "proxied" | "direct" | "blocked";
reason: string;
surface: ProxylineSurface;
url: string;
proxyUrl?: string; // redacted
}>;
Known reason values:
"managed-proxy-active"— managed mode applied."managed-proxy-bypass-policy"— managed mode was active, butbypassPolicyintentionally sent the URL direct."managed-proxy-unsupported-url-scheme"— managed mode is active, but the URL scheme is not one Proxyline can proxy."ambient-proxy-active"— ambient mode resolved a proxy from env."ambient-proxy-not-configured"— ambient mode has no proxy env set, or the URL scheme is unsupported."no-proxy-match"— the URL matchedNO_PROXY."runtime-stopped"—explain()was called afterstop().
kind: "blocked" is reserved for future explicit deny rules; the current implementation does not produce blocked decisions.
#ProxylineBypassRequest
type ProxylineBypassRequest = Readonly<{
surface: ProxylineSurface;
url: string;
}>;
#ProxylineBypassPolicy
type ProxylineBypassPolicy = (request: ProxylineBypassRequest) => boolean;
Return true to send that managed-mode request direct. Use this only for explicitly trusted destinations such as loopback control-plane endpoints.
#ProxylineEvent
type ProxylineEvent =
| Readonly<{ type: "runtime.installed"; mode: ProxylineMode; active: boolean; proxyUrl?: string }>
| Readonly<{ type: "runtime.stopped"; mode: ProxylineMode }>
| Readonly<{ type: "decision"; decision: ProxylineDecision }>
| Readonly<{ type: "warning"; code: string; message: string }>;
decision events fire from inside explain(). runtime.installed and runtime.stopped fire from installProxyline and handle.stop() respectively. warning is reserved for future runtime diagnostics.
#ExplainOptions
type ExplainOptions = Readonly<{
surface?: ProxylineSurface;
}>;
#ProxylineHandle
type ProxylineHandle = Readonly<{
mode: ProxylineMode;
active: boolean;
proxyUrl?: string;
createNodeAgent: () => http.Agent;
createUndiciDispatcher: () => Dispatcher;
createWebSocketAgent: () => http.Agent;
explain: (url: string | URL, options?: ExplainOptions) => ProxylineDecision;
registerBypass: (registration: ProxylineBypassRegistration) => () => void;
stop: () => void;
withBypass: <T>(registration: ProxylineBypassRegistration, run: () => T) => T;
}>;
mode— the mode this handle was installed with.active—truewhen the runtime is installed and forcing/respecting a proxy.proxyUrl— redacted proxy URL string when active.createNodeAgent()— proxy-awarehttp.Agentfor ad-hoc node:http(s) use. Returns a direct agent when inactive or afterstop().createUndiciDispatcher()— proxy-aware undiciDispatcher. Returns a directUndiciAgent()when ambient-inactive or afterstop().createWebSocketAgent()— same ascreateNodeAgent()but typed for WebSocket clients.explain(url, options?)— returns aProxylineDecisionand emits adecisionevent.registerBypass({ url, surface? })— managed-mode process-wide bypass. Returns an unregister callback. Whensurfaceis omitted, the bypass matches any surface for that exact URL.stop()— restores the captured Node HTTP(S) stack, undici dispatcher, and fetch globals, destroys Proxyline-owned runtime agents/dispatchers, emitsruntime.stopped. Idempotent.withBypass(registration, run)— applies a bypass only torun()and async work created inside that callback.
#Dispatcher Detection
isProxylineDispatcher(dispatcher: unknown): boolean;
Returns true for Proxyline-owned managed and ambient undici dispatchers. Use this instead of constructor-name checks when integrating with code that also manages undici globals. Import from @openclaw/proxyline/dispatcher-brand when detection must not load Proxyline's full runtime.
#OpenProxyConnectTunnelOptions
type OpenProxyConnectTunnelOptions = Readonly<{
proxyUrl: string | URL;
proxyTls?: ProxylineTlsOptions;
proxyConnect?: ProxyConnectOptions;
targetHost: string;
targetPort: number;
timeoutMs?: number;
signal?: AbortSignal;
}>;
proxyUrl—http://orhttps://. Userinfo becomes aProxy-Authorization: Basicheader.proxyTls— CA trust for HTTPS proxies. See Proxy TLS.proxyConnect— prepared connection controls for this proxy hop; see below.targetHost/targetPort— what to ask the proxy to connect to.timeoutMs— overall budget for the CONNECT handshake. Defaults to30000when omitted. Pass0for no timeout.signal— optional caller cancellation; aborting rejects the handshake and destroys its active proxy socket.
#AmbientNodeProxyAgentOptions
type AmbientNodeProxyAgentOptions = {
env?: ProxyEnvSnapshot;
protocol?: "http" | "https";
proxyTls?: ProxylineTlsOptions;
resolveProxyConnectOptions?: (proxyUrl: string) => ProxyConnectOptions;
};
env— optional env snapshot. Defaults to reading process env.protocol— probe protocol, defaulting to"https".proxyTls— CA trust for HTTPS proxy endpoints. See Proxy TLS.resolveProxyConnectOptions— resolves prepared connection controls for each cached proxy child agent.
#ProxyConnectOptions
type ProxyConnectOptions = Readonly<
Pick<net.TcpNetConnectOpts, "lookup"> &
Pick<tls.ConnectionOptions,
"ca" | "cert" | "key" | "passphrase" | "servername" | "rejectUnauthorized">
>;
lookupresolves only the proxy hostname. It never resolves the destination- TLS fields apply only to an HTTPS proxy.
catakes precedence over the - The proxy URL always owns the socket host and port. Extra JavaScript properties
- No operation signal is cached in these options. Node request cancellation and
named in a CONNECT request.
existing proxyTls.ca/caFile default. Other TLS fields keep Node's defaults when omitted; destination TLS remains request-owned.
such as host, port, path, socket, or ALPNProtocols are ignored. HTTPS proxy connections negotiate HTTP/1.1.
openProxyConnectTunnel's existing handshake signal keep their own lifetimes.