Reference

API Reference

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 ProxylineError with code MANAGED_PROXY_URL_REQUIRED if mode: "managed" is used without a proxyUrl.
  • Throws ProxylineError with code UNSUPPORTED_PROXY_PROTOCOL if managed-mode proxyUrl is not http:// or https://.
  • Throws ProxylineError with code RUNTIME_ALREADY_ACTIVE if another Proxyline runtime is already installed and ifActive is 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.globalAgent and https.globalAgent with Proxyline's HTTP/HTTPS Node agent.
  • Calls undici.setGlobalDispatcher with a ProxyAgent (managed) or Proxyline's ambient dispatcher (ambient), and patches globalThis.fetch plus Request, Response, Headers, and FormData to 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_REQUIREDmode: "managed" was used without proxyUrl.
  • UNSUPPORTED_PROXY_PROTOCOL — proxy URL scheme is not http:// or https://.
  • RUNTIME_ALREADY_ACTIVE — another Proxyline runtime is already installed.
  • CONNECT_FAILEDopenProxyConnectTunnel failed (bad response, timeout, header overrun, or socket error).
  • INVALID_CONNECT_TARGETopenProxyConnectTunnel received 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 be http:// or https://.
  • 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 every ProxylineEvent.
  • 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, but bypassPolicy intentionally 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 matched NO_PROXY.
  • "runtime-stopped"explain() was called after stop().

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.
  • activetrue when the runtime is installed and forcing/respecting a proxy.
  • proxyUrl — redacted proxy URL string when active.
  • createNodeAgent() — proxy-aware http.Agent for ad-hoc node:http(s) use. Returns a direct agent when inactive or after stop().
  • createUndiciDispatcher() — proxy-aware undici Dispatcher. Returns a direct UndiciAgent() when ambient-inactive or after stop().
  • createWebSocketAgent() — same as createNodeAgent() but typed for WebSocket clients.
  • explain(url, options?) — returns a ProxylineDecision and emits a decision event.
  • registerBypass({ url, surface? }) — managed-mode process-wide bypass. Returns an unregister callback. When surface is 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, emits runtime.stopped. Idempotent.
  • withBypass(registration, run) — applies a bypass only to run() 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;
}>;
  • proxyUrlhttp:// or https://. Userinfo becomes a Proxy-Authorization: Basic header.
  • 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 to 30000 when omitted. Pass 0 for 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">
>;
  • lookup resolves only the proxy hostname. It never resolves the destination
  • named in a CONNECT request.

  • TLS fields apply only to an HTTPS proxy. ca takes precedence over the
  • existing proxyTls.ca/caFile default. Other TLS fields keep Node's defaults when omitted; destination TLS remains request-owned.

  • The proxy URL always owns the socket host and port. Extra JavaScript properties
  • such as host, port, path, socket, or ALPNProtocols are ignored. HTTPS proxy connections negotiate HTTP/1.1.

  • No operation signal is cached in these options. Node request cancellation and
  • openProxyConnectTunnel's existing handshake signal keep their own lifetimes.