Overview
ofetch supports proxy configuration across different JavaScript runtimes, with each runtime having its own approach to proxy handling.
Environment Variables: Bun and Deno respect HTTP_PROXY and HTTPS_PROXY environment variables automatically. Node.js requires setting NODE_USE_ENV_PROXY=1 to enable built-in proxy support.
Environment Variables
All runtimes support standard proxy environment variables:
export HTTP_PROXY=http://localhost:3128
export HTTPS_PROXY=http://localhost:3128
export NO_PROXY=localhost,127.0.0.1
Node.js requires an additional environment variable:NODE_USE_ENV_PROXY=1 node app.js
Bun respects proxy environment variables automatically: Deno respects proxy environment variables automatically:deno run --allow-net app.js
Node.js Proxy Configuration
Node.js (>= 18) uses undici’s ProxyAgent for proxy support.
Basic Usage
import { ofetch } from 'ofetch'
import { ProxyAgent } from 'undici'
const proxyAgent = new ProxyAgent('http://localhost:3128')
await ofetch('https://icanhazip.com', { dispatcher: proxyAgent })
Global Proxy
Set a proxy for all requests:
import { ProxyAgent, setGlobalDispatcher } from 'undici'
setGlobalDispatcher(new ProxyAgent('http://localhost:3128'))
// All requests now use the proxy
await ofetch('https://icanhazip.com')
Per-Instance Proxy
Create a fetch instance with a proxy:
import { ofetch } from 'ofetch'
import { ProxyAgent } from 'undici'
const proxyFetch = ofetch.create({
dispatcher: new ProxyAgent('http://localhost:3128')
})
await proxyFetch('https://icanhazip.com')
Authenticated Proxy
import { ProxyAgent } from 'undici'
const proxyAgent = new ProxyAgent({
uri: 'http://localhost:3128',
auth: 'username:password'
})
await ofetch('https://icanhazip.com', { dispatcher: proxyAgent })
Proxy from Environment
import { ProxyAgent } from 'undici'
const proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY
if (proxyUrl) {
const proxyAgent = new ProxyAgent(proxyUrl)
await ofetch('https://icanhazip.com', { dispatcher: proxyAgent })
}
Bun Proxy Configuration
Bun has native proxy support through the proxy option.
Basic Usage
import { ofetch } from 'ofetch'
await ofetch('https://icanhazip.com', {
proxy: 'http://localhost:3128'
})
With Authentication
await ofetch('https://icanhazip.com', {
proxy: 'http://username:password@localhost:3128'
})
Per-Instance Proxy
const proxyFetch = ofetch.create({
proxy: 'http://localhost:3128'
})
await proxyFetch('https://icanhazip.com')
Deno Proxy Configuration
Deno can use environment variables or undici with npm specifiers.
Using Environment Variables
HTTP_PROXY=http://localhost:3128 deno run --allow-net app.ts
Using Undici (Programmatic)
import { ofetch } from 'npm:ofetch'
import { ProxyAgent } from 'npm:undici'
const proxyAgent = new ProxyAgent('http://localhost:3128')
await ofetch('https://icanhazip.com', { dispatcher: proxyAgent })
Complete Example from Source
From examples/proxy.mjs:
import { ofetch } from "ofetch";
// Node.js: Use undici ProxyAgent with dispatcher option
// import { ProxyAgent } from "undici";
// const proxyAgent = new ProxyAgent("http://localhost:3128");
// Bun: Use native proxy option
// const proxy = "http://localhost:3128";
// Deno: Set HTTP_PROXY environment variable or use undici with npm specifier
// HTTP_PROXY=http://localhost:3128 deno run --allow-net proxy.mjs
const data = await ofetch("https://icanhazip.com", {
// dispatcher: proxyAgent, // Node.js
// proxy, // Bun
});
console.log(data);
Self-Signed Certificates
Allowing self-signed certificates makes fetch vulnerable to MITM attacks. USE AT YOUR OWN RISK!
Node.js (undici Agent)
import { Agent } from 'undici'
// Note: This makes fetch insecure against MITM attacks. USE AT YOUR OWN RISK!
const unsecureAgent = new Agent({
connect: { rejectUnauthorized: false }
})
await ofetch('https://self-signed.example.com/', {
dispatcher: unsecureAgent
})
Combined Proxy + Self-Signed Cert
import { ProxyAgent } from 'undici'
const proxyAgent = new ProxyAgent({
uri: 'http://localhost:3128',
connect: { rejectUnauthorized: false }
})
await ofetch('https://self-signed.example.com/', {
dispatcher: proxyAgent
})
Dispatcher Type Definition
From src/types.ts:50-54:
/**
* Only supported in Node.js >= 18 using undici
*
* @see https://undici.nodejs.org/#/docs/api/Dispatcher
*/
dispatcher?: InstanceType<typeof import("undici").Dispatcher>;
The dispatcher option:
- Only available in Node.js >= 18
- Uses undici’s Dispatcher interface
- Supports
ProxyAgent, Agent, and other dispatcher types
Runtime Detection Example
import { ofetch } from 'ofetch'
const proxyUrl = 'http://localhost:3128'
if (typeof Bun !== 'undefined') {
// Bun
await ofetch('https://icanhazip.com', {
proxy: proxyUrl
})
} else if (typeof Deno !== 'undefined') {
// Deno - use environment variable
Deno.env.set('HTTP_PROXY', proxyUrl)
await ofetch('https://icanhazip.com')
} else {
// Node.js
const { ProxyAgent } = await import('undici')
await ofetch('https://icanhazip.com', {
dispatcher: new ProxyAgent(proxyUrl)
})
}
TypeScript Interface
import type { FetchOptions } from 'ofetch'
import type { Dispatcher } from 'undici'
const options: FetchOptions = {
dispatcher: proxyAgent, // Node.js only
// @ts-expect-error - proxy is Bun-specific
proxy: 'http://localhost:3128' // Bun only
}
Testing Proxy Connection
async function testProxy(proxyUrl: string) {
try {
const { ProxyAgent } = await import('undici')
const proxyAgent = new ProxyAgent(proxyUrl)
const ip = await ofetch('https://icanhazip.com', {
dispatcher: proxyAgent
})
console.log('Proxy working! IP:', ip.trim())
return true
} catch (error) {
console.error('Proxy failed:', error.message)
return false
}
}
await testProxy('http://localhost:3128')