TypeError: fetch failed in Node.js Through a Proxy
The built-in fetch in Node.js shows a generic "fetch failed" message, and the real reason sits in the cause field. With a proxy there is one more trap: by default fetch does not read the proxy variables.
Updated · Prokso editorial team
- fetch failed is only a wrapper: the real reason is in err.cause
- The built-in fetch reads HTTP_PROXY only with NODE_USE_ENV_PROXY=1 or --use-env-proxy
- The simplest fix is to pass a dispatcher with ProxyAgent from undici straight into fetch
What the error means
According to the Node.js documentation, the global fetch is built on the undici library. When a request fails at the network level, undici rejects it with TypeError: fetch failed and puts the original error into error.cause. That is where to look: console.log(err.cause).
The cause can be, for example, ECONNREFUSED, ENOTFOUND, a connect timeout with the code UND_ERR_CONNECT_TIMEOUT, or a proxy response. If the proxy did not accept the username for an HTTPS target, undici reports Proxy response (407) !== 200 when HTTP Tunneling.
The second trap: the built-in fetch reads HTTP_PROXY and HTTPS_PROXY only when built-in proxy support is enabled. The NODE_USE_ENV_PROXY=1 variable was added in Node.js 24.0.0 and 22.21.0, the --use-env-proxy flag in 24.5.0 and 22.21.0; the documentation marks this feature as under active development. Without it, the request goes direct, past the proxy.
Causes
- The proxy is not connected. The environment variables are set, but fetch does not read them without NODE_USE_ENV_PROXY=1 or --use-env-proxy, and the request leaves from your IP.
- A wrong host or port. The cause shows ECONNREFUSED or ENOTFOUND: a typo in gw.prokso.com or a port other than 823, 824 and 10000-20000.
- The username or password was rejected. For HTTPS targets the cause reads "Proxy response (407) !== 200 when HTTP Tunneling". The Prokso gateway answers "HTTP/1.1 407 NO_USER" in this case.
- A SOCKS5 port for an HTTP agent. A ProxyAgent with an http:// address on port 824 speaks HTTP to a SOCKS5 port, and the connection is not established.
- The site did not answer in time. A connect or read timeout: the proxy or the site did not respond in time.
How to fix it
- Print the reason:
catch (err) { console.log(err.cause) }. The code in cause tells you which step to start with. - Connect the proxy explicitly: install the undici package and pass
dispatcher: new ProxyAgent('http://USERNAME:PASSWORD@gw.prokso.com:823')to fetch. The Node.js documentation confirms that the global fetch accepts an undici-compatible dispatcher. - To take the proxy from environment variables, use
EnvHttpProxyAgentfrom undici withsetGlobalDispatcher(), or start Node.js withNODE_USE_ENV_PROXY=1or--use-env-proxyif your version supports it. - For a 407, copy the username and password from the dashboard again. If the password has special characters, encode them with
encodeURIComponent. The username syntax and ports are on the username, ports and parameters page. - For an HTTP agent use port 823, or a port from 10000-20000 for a sticky IP. Other ways to connect are in the Node.js guide.
- If the cause is a timeout, reduce the number of parallel requests and see the proxy timeout page.
How to check that it works
Run fetch against https://prokso.com/ip with the same dispatcher. If the JSON shows the proxy IP and country, the connection works. You can test the proxy string separately in the proxy checker.
Two-minute diagnosis
First paste the line into the proxy checker. If the proxy works there, the cause is in your app or its settings. If not, test the line from a terminal:
curl -v -x "http://USERNAME:PASSWORD@gw.prokso.com:823" https://api.ipify.org
- A
< HTTP/1.1 407line right afterCONNECTmeans the proxy answered. The name after the code, for exampleNO_USER, points to the cause. - The proxy answered
CONNECTwith 200 and then another code arrived - the proxy works, and that answer came from the website. - No answer at all, only a timeout - the connection never reached the proxy: check the host, port and network.
Setup guides where this error comes up
FAQ
Why does fetch work but the IP in the response is mine?
Most likely the proxy is simply not connected: the built-in fetch does not read HTTP_PROXY without NODE_USE_ENV_PROXY=1 or --use-env-proxy. Pass a dispatcher explicitly.
Does NODE_USE_ENV_PROXY support SOCKS5?
The Node.js documentation lists only HTTP and HTTPS proxy URLs for built-in support. For SOCKS5, use a separate agent or library.
The cause is a certificate error. Is it the proxy?
Port 823 does not replace site certificates, so look for the reason in the system or on the site. See <a href="/en/errors/ssl-certificate-errors">SSL certificate errors</a>.
How do I find the undici version in Node.js?
According to the Node.js documentation, through the process.versions.undici property.
Other proxy errors
Residential $1.59, mobile $2.50, datacenter $0.65 per GB
Sign up in a minute, get access right after payment.