Node.js fetch and axios Proxy: NODE_USE_ENV_PROXY, SOCKS5
Four ways to give Node.js fetch and axios a proxy, with the mistakes that make them silently go direct.
Why fetch still shows your own IP
Setting HTTP_PROXY is not enough: Node's documentation says its proxy support is off until NODE_USE_ENV_PROXY=1 or --use-env-proxy is set, and the variable is read when the process starts. In our test, a Node 24.14.0 script with HTTP_PROXY set but no flag reached the test page directly.
There are three more traps. Importing the undici package at the top of the file can replace the global dispatcher: with undici 8.12.4 imported, fetch went direct even with NODE_USE_ENV_PROXY=1, while undici 7.30.2 did not do that. A dispatcher built by an installed undici can be refused by the built-in fetch when the two versions differ (we got UND_ERR_INVALID_ARG). And axios does not use Node's switch at all: it reads the same variables itself, and when a proxy option or an agent is given, that wins.
The fix for the middle one is to use fetch from the same package as the dispatcher, or to register the dispatcher globally with setGlobalDispatcher().
Built-in fetch and http/https requests, from HTTP_PROXY, HTTPS_PROXY, NO_PROXY
No: only http:// and https:// proxy URLs are documented
Node 24, or 22.21 and newer; start the process with the variable, not set it later
undici EnvHttpProxyAgent + setGlobalDispatcher
Every fetch() after it is registered, reading the same variables
Not through the variables
Register it once, early; fetch and agent versions must match
undici ProxyAgent as dispatcher
One call, or all calls when set globally
Yes: socks5: addresses (experimental warning in our test)
Use fetch from undici; the login in the URL must be percent-encoded for HTTP
axios proxy option or environment variables
axios requests only; HTTP proxies, CONNECT tunnel for https:// targets
No, not documented
proxy: false switches off both the option and the variables
axios + socks-proxy-agent
axios requests through a SOCKS5 proxy
Yes, with the agent on both httpAgent and httpsAgent
Set proxy: false so axios does not add its own
Source: Node.js, undici and axios documentation and our local test of 14 November 2026 (Node.js 24.14.0, axios 1.21.1). Version numbers are the ones we tested.
We ran each variant against a local proxy that asks for a login and logs every request. Without the flag, built-in fetch ignored HTTP_PROXY. With NODE_USE_ENV_PROXY=1 it reached the proxy with the login. EnvHttpProxyAgent registered with setGlobalDispatcher worked, as did undici's ProxyAgent with undici's own fetch. axios worked through its proxy option and through the environment variables, and also through a SocksProxyAgent against a local SOCKS5 proxy.
The test page was plain HTTP; for https:// pages the documentation says both undici and axios open a CONNECT tunnel. The numbers above change between releases, so run the same check on your versions.
# Node.js 24 (or 22.21 and newer): switch the built-in support on at start-up
NODE_USE_ENV_PROXY=1 \
HTTPS_PROXY="http://LOGIN:PASSWORD@HOST:2222" \
NO_PROXY="localhost,127.0.0.1" \
node app.js
# the same thing as a flag
HTTPS_PROXY="http://LOGIN:PASSWORD@HOST:2222" node --use-env-proxy app.js
Example only: replace LOGIN, PASSWORD and HOST with the values from My assets. Percent-encode special characters in the login.
fetch with undici: one call or the whole process
// npm i undici
import { fetch, ProxyAgent, EnvHttpProxyAgent, setGlobalDispatcher } from 'undici'
// A) one dispatcher for one call. Use fetch from the same undici package.
const login = encodeURIComponent('LOGIN')
const pass = encodeURIComponent('PASSWORD')
const agent = new ProxyAgent(`http://${login}:${pass}@HOST:2222`)
const res = await fetch('https://ipinfo.io/json', { dispatcher: agent })
console.log(await res.json())
// B) every fetch() in the process, driven by HTTPS_PROXY / NO_PROXY
// (the agent does nothing until it is registered)
setGlobalDispatcher(new EnvHttpProxyAgent())
Checked on 14 November 2026 against a local HTTP proxy with a login, using a plain-HTTP test page, with undici 8.12.4 and 7.30.2. Replace the placeholders with your own values.
axios: HTTP with the proxy option, SOCKS5 with an agent
// npm i axios socks-proxy-agent
import axios from 'axios'
import { SocksProxyAgent } from 'socks-proxy-agent'
// HTTP proxy: axios' own proxy option
const viaHttp = await axios.get('https://ipinfo.io/json', {
proxy: { protocol: 'http', host: 'HOST', port: 2222, auth: { username: 'LOGIN', password: 'PASSWORD' } },
})
console.log(viaHttp.data)
// SOCKS5 proxy: hand axios an agent and turn its own proxy handling off
const agent = new SocksProxyAgent(
`socks5h://${encodeURIComponent('LOGIN')}:${encodeURIComponent('PASSWORD')}@HOST:3333`
)
const viaSocks = await axios.get('https://ipinfo.io/json', { proxy: false, httpAgent: agent, httpsAgent: agent })
console.log(viaSocks.data)
Both variants checked on 14 November 2026 against local proxies with a login (HTTP page). Replace the placeholders; use the port that matches the protocol you bought.
SOCKS5 with a login: two details
socks-proxy-agent decodes a percent-encoded login before sending it: in our test the proxy received the plain user name and password, and with the socks5h scheme it received the host name instead of an IP. undici's ProxyAgent with a socks5: address did not decode: the proxy received %40 and %3A as written. If the password has special characters, use socks-proxy-agent, or a password without them.
Both libraries need the proxy to speak SOCKS5 on the SOCKS5 port. On Proxy302 that is port 3333, and the credential must have been created as SOCKS5; HTTP uses port 2222.
Check Was NODE_USE_ENV_PROXY=1 set before node started, on Node 24 or 22.21+? Does the file import undici? Is proxy: false set in axios?
Fix Start with the variable, print process.version and process.versions.undici, and call https://ipinfo.io/json. Use the dispatcher or agent that matches your library.
Stop when If the exit IP is still yours after the dispatcher is set globally, stop changing the code and test the proxy with curl.
fetch failed with UND_ERR_INVALID_ARG
Check Is the dispatcher from an installed undici while fetch is the built-in one?
Fix Import fetch from undici as well, or register the dispatcher with setGlobalDispatcher().
407 or Proxy Authentication Required
Check Is the login in the URL percent-encoded, and is it the login of this asset?
Fix Copy host, port, username and password from My assets again and encode the password with encodeURIComponent.
ECONNRESET or socket hang up on a SOCKS5 address
Check Is the port 3333 and was the credential created as SOCKS5?
Fix Generate or buy a credential as SOCKS5, or switch the code to the HTTP port 2222 with an http:// proxy URL.
Which Proxy302 product fits a Node.js script
For servers, test runs and scripts that do not log in to accounts, a datacenter IP rented per IP costs US$0.25 for 1 day or US$3.99 for 30 days, with HTTP (port 2222) or SOCKS5 (port 3333) chosen at purchase and up to 100 IPs in one order. Datacenter addresses are recognisable as datacenter, so for account, shop or ad-account work use a static ISP IP, from US$0.50 a day.
There is no free trial; the smallest purchase is one IP for one day.
Open the datacenter page, choose the country, term and protocol (HTTP for fetch and axios proxy options, SOCKS5 for the agent route), then review the cost and pay from the wallet.
Step 2
Open My assets and copy host, port, username and password.
Step 3
Put them into the example for your route, or into HTTPS_PROXY for the built-in switch.
Step 4
Call https://ipinfo.io/json and compare the printed IP with your own.
Expected result The proxy's IP, not yours.
FAQ
Does Node.js fetch use HTTP_PROXY?
Not by default. The built-in support is off until NODE_USE_ENV_PROXY=1 or --use-env-proxy is set at start-up, on Node 24 or 22.21 and newer.
Read on 14 November 2026 (command-line options page): NODE_USE_ENV_PROXY=1, added in v24.0.0 and v22.21.0, stability 1.1 (active development); when on, Node parses HTTP_PROXY, HTTPS_PROXY and NO_PROXY at startup and routes requests through the proxy.
Read on 14 November 2026: with the variable set to 1 the global agent is built with proxyEnv: process.env; lower-case variables win over upper-case; proxy URLs may be http:// or https:// with user:pass@host:port; NO_PROXY formats; http.setGlobalProxyFromEnv() turns it on from code for fetch() and http.request().
Read on 14 November 2026: fetch is based on undici; process.versions.undici shows the bundled version; fetch accepts a dispatcher option; setGlobalDispatcher() from an installed undici package affects both undici and Node.js.
Read on 14 November 2026: reads http_proxy, https_proxy, no_proxy (and upper-case forms; lower-case wins when both are set); setGlobalDispatcher(new EnvHttpProxyAgent()) makes fetch use it; constructing the agent alone has no effect.
Read on 14 November 2026: HTTP, HTTPS and SOCKS5 proxies; socks5: URIs are handed to Socks5ProxyAgent; for HTTP proxies the credentials in the URI are URL-decoded before use; HTTPS targets go through a CONNECT tunnel.
Read on 14 November 2026: the proxy object (protocol, host, port, auth); false disables proxies and ignores environment variables; http_proxy, https_proxy and no_proxy are honoured; for https:// targets axios opens a CONNECT tunnel and sends Proxy-Authorization on it; a supplied agent does its own tunnelling. SOCKS is not mentioned.
Read on 14 November 2026: SocksProxyAgent is a named export and is passed as the agent option of https.get; the README does not describe axios or the socks5h scheme, so those parts rest on our own test.
Local fixture run, 14 November 2026
Local example · Confirmed on:
Run on 14 November 2026 on macOS with Node.js 24.14.0 (bundled undici 7.21.0), axios 1.21.1, undici 8.12.4 and 7.30.2, socks-proxy-agent: a local HTTP proxy that requires a login, a local SOCKS5 proxy with a login and a plain-HTTP test page; each request was logged on the proxy side.
A plain-HTTP test page; HTTPS tunnelling is taken from the documentation. Versions move fast, so re-run the test on yours.
Proxy302 product facts and price list
Product observation · Confirmed on:
Product facts file of the site (values checked on 10 November 2026): protocols and ports, prices in US$ (1 PTC = US$1), lease terms, quantity limits, no free trial.
Ready to try it?
Create an account, top up once, then pick rotating residential, static ISP or datacenter IPs and have one running in your browser within minutes.