Skip to main content

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

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')

Build docs developers (and LLMs) love