Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nodejs/undici/llms.txt

Use this file to discover all available pages before exploring further.

Undici maintains a small set of global state that controls the default behavior of top-level functions like request, stream, and fetch. You can replace the global dispatcher to apply connection pooling, proxy routing, retry logic, or caching to every request made through undici without changing individual call sites.
The global dispatcher is stored under Symbol.for('undici.globalDispatcher.2'). A legacy mirror is kept at Symbol.for('undici.globalDispatcher.1') via Dispatcher1Wrapper for compatibility with Node.js built-in fetch, which uses the older handler contract.

setGlobalDispatcher(dispatcher)

Replaces the global dispatcher used by request, stream, pipeline, connect, upgrade, and fetch when no per-call dispatcher option is provided. The dispatcher must be an object with a dispatch method — any Dispatcher subclass qualifies (Agent, Pool, Client, ProxyAgent, etc.). When set, undici also writes a Dispatcher1Wrapper-wrapped copy of the dispatcher to Symbol.for('undici.globalDispatcher.1') so that Node.js built-in fetch continues to work via the legacy handler contract.
import { setGlobalDispatcher, Agent } from 'undici'

setGlobalDispatcher(new Agent({
  connections: 10,
  keepAliveTimeout: 30_000
}))

Parameters

dispatcher
Dispatcher
required
Any Dispatcher instance. Must expose a dispatch method. Passing a value without dispatch throws an InvalidArgumentError.

Common patterns

Caching + retry interceptors
import { setGlobalDispatcher, Agent, interceptors, cacheStores } from 'undici'
const { cache, retry } = interceptors

setGlobalDispatcher(
  new Agent().compose(
    cache({
      store: new cacheStores.MemoryCacheStore({
        maxSize: 50 * 1024 * 1024 // 50 MB
      })
    }),
    retry({ maxRetries: 3 })
  )
)

Compatibility with Node.js built-in fetch

Undici stores the active dispatcher under two symbols to ensure compatibility:
SymbolConsumer
Symbol.for('undici.globalDispatcher.2')undici request, stream, fetch, etc.
Symbol.for('undici.globalDispatcher.1')Node.js built-in fetch (legacy handler contract)
setGlobalDispatcher writes to both automatically. If you need to expose a custom dispatcher only to legacy consumers, wrap it manually:
Exposing a custom dispatcher to legacy consumers
import { Agent, Dispatcher1Wrapper } from 'undici'

const legacyDispatcher = new Dispatcher1Wrapper(new Agent())
// Use legacyDispatcher where the v1 handler API (onConnect/onHeaders/...) is expected

getGlobalDispatcher()

Returns the current global dispatcher. The default value is a shared Agent instance created at module load time.
Inspecting the global dispatcher
import { getGlobalDispatcher } from 'undici'

const dispatcher = getGlobalDispatcher()
console.log(dispatcher.constructor.name) // 'Agent' by default

Return value

dispatcher
Dispatcher
The active global dispatcher. Returns an Agent instance unless overridden with setGlobalDispatcher.

setGlobalOrigin(origin)

Sets the base URL resolved against when fetch receives a relative URL path. Once set, you can call fetch('/api/ping') instead of specifying the full URL. Only http: and https: origins are accepted. Passing any other protocol throws a TypeError. Pass undefined to clear the global origin and revert to requiring absolute URLs.
import { setGlobalOrigin, fetch } from 'undici'

setGlobalOrigin('http://localhost:3000')

// Now relative paths resolve against http://localhost:3000
const response = await fetch('/api/health')
const data = await response.json()

Parameters

origin
string | URL | undefined
required
The base origin to set. Must be an http: or https: URL. Only the origin portion (protocol + host + port) is used — any path, query, or fragment is discarded.Pass undefined to reset the global origin. After resetting, relative URLs passed to fetch throw a TypeError.

Example — resetting the origin

Resetting the global origin
import { setGlobalOrigin, fetch } from 'undici'

setGlobalOrigin('http://localhost:3000')

// ... later, during teardown or test cleanup:
setGlobalOrigin(undefined)

// This will now throw TypeError: Failed to parse URL
await fetch('/api/ping')
setGlobalOrigin only affects fetch with relative URLs. Top-level dispatch functions (request, stream, etc.) always require an absolute URL.

getGlobalOrigin()

Returns the currently configured global origin, or undefined if none has been set.
Reading the global origin
import { setGlobalOrigin, getGlobalOrigin } from 'undici'

setGlobalOrigin('https://api.example.com')

const origin = getGlobalOrigin()
console.log(origin.href) // 'https://api.example.com/'
console.log(origin instanceof URL) // true

Return value

origin
URL | undefined
The global origin as a URL object, or undefined if not set.

install()

Installs undici’s web API implementations onto globalThis, making them available globally without explicit imports. This is useful for polyfilling environments, ensuring consistent fetch behavior across Node.js versions, or satisfying third-party libraries that expect standard browser globals. After calling install(), all listed globals come from undici’s implementation. They form a matched set, so FormData and fetch are guaranteed to be compatible.
import { install } from 'undici'

install()

// All of the following are now undici's implementations:
const response = await fetch('https://api.example.com')
const headers = new Headers({ 'content-type': 'application/json' })
const form = new FormData()
const ws = new WebSocket('wss://ws.example.com')
const es = new EventSource('https://sse.example.com/events')

Installed globals

install() assigns the following properties on globalThis:
GlobalTypeDescription
fetchfunctionWHATWG Fetch function
HeadersclassHTTP headers container
ResponseclassHTTP response representation
RequestclassHTTP request representation
FormDataclassMultipart form data builder
WebSocketclassWebSocket client
CloseEventclassWebSocket close event
ErrorEventclassWebSocket error event
MessageEventclassWebSocket/EventSource message event
EventSourceclassServer-sent events client
install() overwrites any existing globals with the same names, including Node.js built-in implementations. The replacement persists for the lifetime of the process. Call it once, early in your application’s startup.

When to use install()

Node.js added built-in fetch in v18 (unflagged in v21). If you need undici’s implementation on older runtimes, or you want undici’s latest features regardless of the Node.js version:
Conditional install
import { install } from 'undici'

if (typeof globalThis.fetch === 'undefined') {
  install()
}
The safest pattern when using FormData with fetch is to ensure both come from the same implementation. install() guarantees this:
After install(), FormData and fetch are always paired
import { install } from 'undici'

install()

const body = new FormData()
body.append('field', 'value')

// Both FormData and fetch come from undici — safe to use together
await fetch('https://example.com/upload', { method: 'POST', body })
Alternatively, import both directly from undici without calling install():
Direct import — no globals needed
import { fetch, FormData } from 'undici'

const body = new FormData()
await fetch('https://example.com/upload', { method: 'POST', body })
When you need deterministic fetch behavior in tests regardless of the Node.js version or environment:
Test setup file
import { install } from 'undici'

// Run once in global test setup
install()
Some libraries (e.g. SDKs that target both browser and Node.js) rely on globally available fetch, Headers, Request, and Response. Calling install() satisfies those expectations without patching the libraries.

Build docs developers (and LLMs) love