# Axios Proxy Not Working: 16 Causes and Fixes (Tested)

Source: https://ipvolt.com/guides/fix-axios-proxy-not-working
Markdown: https://ipvolt.com/guides/fix-axios-proxy-not-working.md

[Home](https://ipvolt.com/index.md) / [Guides](https://ipvolt.com/guides.md) / [Axios Proxy Not Working: 16 Causes and Fixes (Tested)](https://ipvolt.com/guides/fix-axios-proxy-not-working.md)

Category: Troubleshooting
Published: 2026-11-11
Reading time: 15 minutes
Author: ipvolt

Axios skips your proxy or fails through it in Node.js? 16 causes with tested fixes: proxy: false in 1.21, HTTP/2, CONNECT, 407, NO_PROXY, redirects, SOCKS5.

When an Axios request in Node.js skips the proxy, or fails on its way through one, the cause is one of the 16 below, and most of them depend on the Axios version. Axios 1.21.0 and 1.21.1 ignore a `proxyEnv` agent when `proxy: false` is set. `httpVersion: 2` and the fetch adapter go direct on every version that has them. Releases before 1.16.1 never open a CONNECT tunnel for an `https://` URL. Each cause comes with the output we recorded and a fix we ran.

Tested on Node.js 24.22.2 and 26.13.0 with Axios 1.12.2, 1.19.0, 1.20.0, 1.21.0 and 1.21.1, plus 1.13.6, 1.15.0, 1.16.0, 1.16.1 and 1.18.1 to find where behaviour changed, https-proxy-agent 9.1.0 and socks-proxy-agent 10.1.0, on macOS 26.5.1 arm64, 11 November 2026. The lab is a logging proxy and an HTTPS target on 127.0.0.1. "Bypassed" means the target answered and the proxy logged nothing. The scripts, the [results table](/downloads/fix-axios-proxy-not-working/RESULTS.md) and all 1,290 records are in the [lab folder](/downloads/fix-axios-proxy-not-working/README.md). To set a proxy up for the first time, start with [Axios proxy setup](/guides/axios-proxy-setup); this page is for a setup that doesn't behave.

## Quick check: is the request using the proxy?

```js
import axios from 'axios';

// Use the same client and options as the code you are debugging.
const res = await axios.get('https://api.ipify.org?format=json', {
  proxy: { protocol: 'http', host: 'proxy.example', port: 8080 },
});
console.log(res.data);
```

Run it with the options of the failing code, then once more with no proxy at all. If both runs print the same IP, the request went around the proxy. A `200` proves nothing: every bypass on this page returned `200`. If you can read the proxy's own log, look there first. In the lab each proxied `https://` request left one `CONNECT` line, and each bypassed one left none.

## Find your symptom

| What you see | Go to |
| --- | --- |
| Status `200`, but the IP is your own and the proxy logs nothing | [The request ignores the proxy](#the-request-ignores-the-proxy-with-no-error) |
| `400`, `socket hang up`, `wrong version number`, `ENOTFOUND undefined`, or a request that never returns | [HTTPS through an HTTP proxy fails](#https-through-an-http-proxy-fails) |
| `Request failed with status code 407` | [407 and authentication errors](#407-and-authentication-errors) |
| `HTTPS_PROXY` is set but ignored, or a host is skipped that shouldn't be | [Environment variables and NO_PROXY](#environment-variables-arent-picked-up-or-noproxy-matches-wrongly) |
| The first request is proxied and the redirect is not | [Redirects leave the proxy](#redirects-leave-the-proxy) |
| `protocol mismatch`, or a SOCKS proxy that can't resolve the host | [SOCKS5 proxies](#socks5-proxies) |

## The request ignores the proxy, with no error

### 1. proxy: false next to a proxyEnv agent (Axios 1.21.0 and later)

```js
import https from 'node:https';
import axios from 'axios';

const agent = new https.Agent({ proxyEnv: { https_proxy: 'http://proxy.example:8080' } });
const res = await axios.get('https://example.com/', { proxy: false, httpsAgent: agent });
console.log(res.status);
```

On Axios 1.20.0 the lab proxy carried this request. On 1.21.0 the same script printed:

```text
200
# proxy log: (nothing)
# target log: GET /ip HTTP/1.1 direct
```

Since 1.21.0, `proxy: false` means "connect directly" even when the agent has its own proxy settings: Axios replaces the agent with a copy that has no `proxyEnv` ([#11402](https://github.com/axios/axios/issues/11402), closed on 5 November 2026; the change is [PR #11242](https://github.com/axios/axios/pull/11242), commit [2498c23](https://github.com/axios/axios/commit/2498c233438eb72c9a9ee8540ded19c6ef4224fa)). The same happened in the lab with Node's own switch: `NODE_USE_ENV_PROXY=1` or `--use-env-proxy` plus `proxy: false` went through the proxy up to 1.20.0 and direct on 1.21.0 and 1.21.1.

**Fix:** remove `proxy: false` from requests that use such an agent. The reporter of #11402 confirmed it, and in the lab the script without it went through the proxy on all ten versions. Axios leaves environment proxying to an agent that has `proxyEnv` ([request config docs](https://axios.rest/pages/advanced/request-config)). Keep `proxy: false` next to a third-party agent such as `HttpsProxyAgent`: that pair worked on every version (cause 5).

### 2. httpVersion: 2

```js
import axios from 'axios';

// HTTPS_PROXY=http://proxy.example:8080 is set in the environment.
const res = await axios.get('https://example.com/', { httpVersion: 2 });
console.log(res.status);
```

On Axios 1.21.1:

```text
200
# proxy log: (nothing)
# target log: GET /ip HTTP/2.0 direct
```

| Axios | `proxy` object | `HTTPS_PROXY` | `proxy: false` + `HttpsProxyAgent` |
| --- | --- | --- | --- |
| 1.13.6, 1.15.0, 1.16.0 | `ERR_HTTP2_ERROR` | `ERR_HTTP2_ERROR` | bypassed silently |
| 1.16.1, 1.18.1, 1.19.0 | bypassed silently | bypassed silently | bypassed silently |
| 1.20.0, 1.21.0, 1.21.1 | `ERR_NOT_SUPPORT` | bypassed silently | bypassed silently |

Axios 1.12.2 has no HTTP/2 support and ignored the option. The security advisory [GHSA-3pq3-5fj3-cg6v](https://github.com/axios/axios/security/advisories/GHSA-3pq3-5fj3-cg6v) (CVE-2026-101898, [GitLab entry](https://advisories.gitlab.com/npm/axios/CVE-2026-101898/)) covers 1.13.0 up to, but not including, 1.20.0: the HTTP/2 path connects on its own and drops the proxy. The lab reproduced the silent bypass on 1.16.1 to 1.19.0. On 1.13.6, 1.15.0 and 1.16.0 the request failed with `Protocol error` after sending HTTP/2 bytes to the proxy, so there it was loud, not silent.

The fix in 1.20.0 rejects an explicit `proxy` object with `HTTP/2 requests with a proxy are not supported`. It does not cover the environment: [PR #11141](https://github.com/axios/axios/pull/11141) says HTTP/2 stays direct when the proxy comes only from environment variables or an agent, and the [docs](https://axios.rest/pages/advanced/request-config) say HTTP/2 requests cannot be proxied. `NODE_USE_ENV_PROXY=1` went direct too.

**Fix:** remove `httpVersion: 2` from every request that must use the proxy. The same request without it went through the proxy over HTTP/1.1 on 1.16.1 and later.

### 3. The fetch adapter

With `adapter: 'fetch'`, a `proxy` object, `HTTPS_PROXY` and an `httpsAgent` were each bypassed silently on all ten versions and both Node lines. The docs mark `proxy` as [Node.js only](https://axios.rest/pages/advanced/request-config), and in the lab only the default HTTP adapter read it, the proxy variables or the agents.

**Fix:** remove `adapter: 'fetch'`, or let Node proxy its own `fetch`: with [`NODE_USE_ENV_PROXY=1`](https://nodejs.org/api/cli.html#node_use_env_proxy1) and `HTTPS_PROXY` set, the fetch adapter went through the proxy on Node 24.22.2 and 26.13.0. `proxy: false` did not switch that off. If the error is `fetch failed` instead, see [fix Node.js fetch failed behind a proxy](/guides/fix-node-fetch-failed-proxy) and [invalid onError method on Node.js 26](/guides/node-26-invalid-onerror-method).

### 4. The agent is in the wrong option

An `HttpsProxyAgent` passed as `httpAgent` only, with an `https://` URL: bypassed silently on every version. Axios uses `httpAgent` for `http://` requests and `httpsAgent` for `https://` requests ([README](https://github.com/axios/axios/blob/v1.21.1/README.md#request-config)).

**Fix:** set both options, as the SOCKS example below does.

## HTTPS through an HTTP proxy fails

### 5. Axios before 1.16.1 sends no CONNECT

With a `proxy` object or `HTTPS_PROXY`, Axios 1.12.2, 1.13.6, 1.15.0 and 1.16.0 did not ask the proxy for a tunnel. The lab proxy received the whole URL in a plain request:

```text
AxiosError: Request failed with status code 400
# exit code: 1
# proxy log: A GET https://target.test:<T>/ip -> 400
# target log: (nothing)
```

Our proxy refuses such a request with `400`. A lab proxy that drops the connection produced `socket hang up` (`ECONNRESET`), the error reported in [#4531](https://github.com/axios/axios/issues/4531). That issue was opened in March 2022 and closed on 30 July 2025 in a cleanup that asked reporters to retest. [#3384](https://github.com/axios/axios/issues/3384), closed in June 2022, describes the same setup with a proxy-specific handshake error that we could not reproduce.

[Axios 1.16.1](https://github.com/axios/axios/releases/tag/v1.16.1) changed this: [PR #10858](https://github.com/axios/axios/pull/10858) makes Axios use a CONNECT tunnel for HTTPS targets "instead of forwarding request URLs, headers, and bodies to the proxy in plaintext". From 1.16.1 on, every one of these cases tunnelled.

**Fix:** upgrade to 1.16.1 or later. If you can't, use a proxy agent and switch Axios's own proxy handling off. This worked on all ten versions, 1.12.2 included:

```js
import axios from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';

const agent = new HttpsProxyAgent('http://proxy.example:8080');
const res = await axios.get('https://example.com/', {
  proxy: false, // Axios adds no proxy handling of its own
  httpsAgent: agent, // the agent opens the CONNECT tunnel
  signal: AbortSignal.timeout(15000),
});
console.log(res.status);
```

### 6. wrong version number: the proxy scheme is wrong or missing

```text
write EPROTO <id>:error:0A00010B:SSL routines:tls_validate_record_header:wrong version number:../deps/openssl/openssl/ssl/record/methods/tlsany_meth.c:78:
```

The client is speaking TLS to a proxy port that speaks plain HTTP. On every version the lab got this error from `protocol: 'https'` in the `proxy` object, from `HTTPS_PROXY=https://127.0.0.1:8080`, from `HTTPS_PROXY=127.0.0.1:8080` with no scheme at all, and from `new HttpsProxyAgent('https://…')`. Up to 1.16.0, a `proxy` object with no `protocol` failed the same way; from 1.16.1 it worked.

`protocol` and the URL scheme describe the connection to the proxy, not to the site: use `https` only when the proxy itself serves TLS ([README](https://github.com/axios/axios/blob/v1.21.1/README.md#request-config)). [#6198](https://github.com/axios/axios/issues/6198) reports this error with an `HttpsProxyAgent`; it was closed in August 2025 for lack of a reproduction, and its configuration with an `http://` proxy URL worked in our lab.

**Fix:** write `protocol: 'http'`, or `http://` in the URL, for an ordinary HTTP proxy. [SSL: wrong version number through a proxy](/guides/fix-ssl-wrong-version-number-proxy) covers the same error in other clients.

### 7. The proxy is a string, or the scheme is inside host

- `proxy: 'http://proxy.example:8080'` (a string): `getaddrinfo ENOTFOUND undefined` from 1.16.1, `connect ECONNREFUSED ::1:443` before it.
- `proxy: { host: 'http://proxy.example', port: 8080 }`: `Invalid URL` (`ERR_INVALID_URL`) from 1.16.1, `getaddrinfo ENOTFOUND http://127.0.0.1` before it.

Neither reached the proxy. [#2072](https://github.com/axios/axios/issues/2072), closed in 2020, has the second form in browser code, where the `proxy` option does not apply at all ([docs](https://axios.rest/pages/advanced/request-config)); we did not test browsers.

**Fix:** pass an object with a bare hostname in `host`, a numeric or string `port` and the scheme in `protocol`.

### 8. The request never returns

From Axios 1.16.1, with a `proxy` object or `HTTPS_PROXY`, a proxy that closed the connection after `CONNECT`, or never answered it, left the request pending: no response and no error after 15 seconds, although `timeout: 5000` was set. Before 1.16.1 the same cases rejected with `socket hang up` or `timeout of 5000ms exceeded`. With `proxy: false` and an `HttpsProxyAgent`, a closed connection rejected with `Proxy connection ended before receiving CONNECT response`, and a silent proxy left the request pending on all ten versions. `http://` URLs rejected normally, with `timeout of 5000ms exceeded` or `socket hang up`. We found no Axios issue for this on 11 November 2026.

**Fix:** give every proxied request a deadline of its own. `signal: AbortSignal.timeout(3000)` ended every pending case after 3 seconds with `canceled` (`ERR_CANCELED`). `maxRedirects: 0` also made `timeout` work for the built-in tunnel, a case the [1.16.0 notes](https://github.com/axios/axios/releases/tag/v1.16.0) mention.

## 407 and authentication errors

A wrong password, or none, returned the same thing on every version, whether the credentials came from `proxy.auth`, from `HTTPS_PROXY` or from an `HttpsProxyAgent` URL: `Request failed with status code 407`, with `error.code` set to `ERR_BAD_REQUEST` and `error.response.status` to `407`. The proxy logged one request, answered with 407, and the target saw nothing. A SOCKS5 proxy has no status code: a wrong password there gave `Socks5 Authentication failed`.

### 9. The credentials are in the wrong place

Putting the proxy's username and password in the top-level `auth` option returned 407, and the proxy log shows it received no credentials. Top-level `auth` is for the site; the proxy's credentials go in `proxy.auth` ([README](https://github.com/axios/axios/blob/v1.21.1/README.md#request-config)). With `proxy.auth`, from 1.16.1 the proxy authenticated the `CONNECT` and the target never saw a `Proxy-Authorization` header, on a redirect to a second host too.

### 10. Special characters encoded the wrong way

The lab proxy expected the password `p@ss/w0rd#1`:

| Where the password goes | Written | Result |
| --- | --- | --- |
| `proxy.auth.password` | as it is | through the proxy (1.16.1 and later) |
| `proxy.auth.password` | percent-encoded | 407: the proxy received `p%40ss%2Fw0rd%231` |
| `HTTPS_PROXY` URL | as it is | `getaddrinfo ENOTFOUND ss` |
| `HTTPS_PROXY` URL | percent-encoded | 407: the proxy received `p%40ss%2Fw0rd%231` |
| `HttpsProxyAgent` URL | percent-encoded | through the proxy (all versions) |

Pasted as it is, the `@` ends the credentials early and `ss` becomes the host. Percent-encoded, the URL parses, but Axios copies the username and password out of it without decoding them ([http.js in 1.21.1](https://github.com/axios/axios/blob/v1.21.1/lib/adapters/http.js)). So on the tested versions a password with reserved characters could not go through `HTTPS_PROXY` at all.

**Fix:** pass it in `proxy.auth` unencoded, or in an agent URL percent-encoded. Both requests below went through the proxy on 1.19.0 to 1.21.1:

```js
import axios from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';

const user = process.env.PROXY_USER;
const pass = process.env.PROXY_PASS;

// In the proxy object: the raw password, not percent-encoded.
const a = await axios.get('https://example.com/', {
  proxy: { protocol: 'http', host: 'proxy.example', port: 8080, auth: { username: user, password: pass } },
});

// In a proxy URL for an agent: percent-encode both parts.
const url = `http://${encodeURIComponent(user)}:${encodeURIComponent(pass)}@proxy.example:8080`;
const b = await axios.get('https://example.com/', { proxy: false, httpsAgent: new HttpsProxyAgent(url) });
console.log(a.status, b.status);
```

For a 407 that survives correct credentials, such as an IP allowlist or a username format, see [fix proxy error 407](/guides/fix-proxy-error-407).

## Environment variables aren't picked up, or NO_PROXY matches wrongly

What Axios read in the lab, on all ten versions: `HTTPS_PROXY` or `https_proxy` for `https://` URLs, `HTTP_PROXY` or `http_proxy` for `http://` URLs, and `ALL_PROXY` or `all_proxy` when the specific one is missing. With both spellings set, lowercase won. The variables are read at request time, so assigning `process.env.HTTPS_PROXY` in code before the request worked. A `proxy` object beat both the variables and `NO_PROXY`. Before 1.16.1 the variables were read the same way, but `https://` requests then failed as in cause 5.

### 11. The variable doesn't match the URL scheme

With only `HTTP_PROXY` set, an `https://` request went direct with no error, on every version. With only `HTTPS_PROXY`, an `http://` request did.

**Fix:** set both, usually to the same `http://` proxy URL. [Proxy environment variables](/guides/proxy-environment-variables) compares how other clients read them.

### 12. An environment proxy overrides your agent

With `HTTPS_PROXY` set, an `HttpsProxyAgent` or `SocksProxyAgent` passed as `httpsAgent` without `proxy: false` was ignored: from 1.16.1 the request went through the proxy from the environment, not the agent's. A `proxy` object next to the agent won in the same way. A CI runner or a container that sets `HTTPS_PROXY` is enough to send your traffic through a different proxy than the one in your code.

**Fix:** `proxy: false` on every request that uses a third-party proxy agent. With it, the agent's proxy carried the request on all ten versions, whatever the environment held.

### 13. NO_PROXY matches differently across versions

With a proxy variable set and the URL host `target.test`:

| `NO_PROXY` | Route | Versions |
| --- | --- | --- |
| `target.test`, `TARGET.TEST`, `.test`, `*.test`, `*`, `target.test:PORT` with the URL's port | direct | all |
| `other.test target.test` or `other.test, target.test` | direct | all |
| `.target.test`, `test`, `get.test`, `target.test:9999`, `https://target.test` | proxy | all |
| `target.test`, when the URL says `target.test.` with a trailing dot | proxy on 1.12.2 and 1.13.6, direct from 1.15.0 | fixed in 1.15.0 |
| `127.0.0.0/8`, URL host `127.0.0.1` | proxy up to 1.19.0, direct from 1.20.0 | fixed in 1.20.0 |
| `localhost`, URL host `127.0.0.1` | proxy up to 1.15.0, direct from 1.16.0 | changed in 1.16.0 |

The trailing-dot row is [GHSA-3p68-rc4w-qgx5](https://github.com/axios/axios/security/advisories/GHSA-3p68-rc4w-qgx5), fixed in 1.15.0. The CIDR row is [GHSA-44g4-m2mj-wpvx](https://github.com/axios/axios/security/advisories/GHSA-44g4-m2mj-wpvx) (CVE-2026-101899), fixed in 1.20.0; the advisory lists 1.15.0 and later as affected, and in the lab 1.12.2 and 1.13.6 ignored the CIDR entry as well. With `NO_PROXY` unset, requests to `localhost` and `127.0.0.1` went through the proxy on every version. [NO_PROXY matching, tested](/blog/no-proxy-matching-tested) has the same matrix for other clients.

## Redirects leave the proxy

### 14. A redirect changes scheme, or lands on a NO_PROXY host

The lab target answers `302` to a second host.

- **`http://` to `https://`, only `HTTP_PROXY` set:** the first hop went through the proxy and the second went direct, on every version. The same happened with `proxy: false` and only `httpAgent` set. With both agents, or from 1.16.1 with both variables, both hops were proxied.
- **`https://` to `https://` on another host:** both hops went through the proxy with a `proxy` object, with `HTTPS_PROXY` and with an agent, from 1.16.1. With proxy authentication, both `CONNECT` requests carried the credentials.
- **Redirect to a host listed in `NO_PROXY`:** on 1.21.0 and 1.21.1 the second hop went direct. On 1.16.1 to 1.20.0 it still went through the proxy. With an explicit `proxy` object both hops were proxied from 1.16.1 on.

**Fix:** set both variables or both agents. If a redirect must never leave the proxy, use a `proxy` object or an agent pair with `proxy: false`, and keep that host out of `NO_PROXY`.

## SOCKS5 proxies

### 15. socks5:// in the proxy option or HTTPS_PROXY

Axios has no SOCKS client. `proxy: { protocol: 'socks5', … }` and `HTTPS_PROXY=socks5://…` failed with `protocol mismatch` (`ERR_ASSERTION`) up to 1.16.0. From 1.16.1 Axios sent an HTTP `CONNECT` line to the SOCKS port, the lab's SOCKS server closed the connection, and the request never returned (cause 8).

**Fix:** a SOCKS agent in both agent options, with `proxy: false` (cause 12). This went through the lab's SOCKS5 proxy on all ten versions:

```js
import axios from 'axios';
import { SocksProxyAgent } from 'socks-proxy-agent';

// socks5h: the proxy resolves the hostname. socks5: this machine does.
const agent = new SocksProxyAgent('socks5h://proxy.example:1080');
const res = await axios.get('https://example.com/', {
  proxy: false,
  httpAgent: agent,
  httpsAgent: agent,
  signal: AbortSignal.timeout(15000),
});
console.log(res.status);
```

### 16. socks5 instead of socks5h

With `socks5://`, the lab's SOCKS server received an IP address: the client had resolved the name itself. With `socks5h://` it received the hostname ([socks-proxy-agent README](https://github.com/TooTallNate/proxy-agents/tree/main/packages/socks-proxy-agent)). For a name that only the proxy can resolve, `socks5://` failed with `getaddrinfo ENOTFOUND proxy-only.test` and `socks5h://` worked. [SOCKS5 vs SOCKS5h](/blog/socks5-vs-socks5h) explains what else the local lookup gives away.

## A known-good setup for each need

All three went through the lab proxy on Axios 1.19.0, 1.20.0, 1.21.0 and 1.21.1, on both Node lines. On 1.12.2 only the third did.

**A fixed proxy in code** (Axios 1.16.1 or later):

```js
import axios from 'axios';

const client = axios.create({
  proxy: {
    protocol: 'http', // how to reach the proxy, not the site
    host: 'proxy.example',
    port: 8080,
    auth: { username: process.env.PROXY_USER, password: process.env.PROXY_PASS },
  },
});

const res = await client.get('https://example.com/', { signal: AbortSignal.timeout(15000) });
console.log(res.status);
```

**A company proxy from the environment** (Axios 1.16.1 or later). Set the variables outside the code:

```sh
export HTTPS_PROXY=http://proxy.example:8080
export HTTP_PROXY=http://proxy.example:8080
export NO_PROXY=localhost,127.0.0.1
```

```js
import axios from 'axios';

// Started with HTTPS_PROXY, HTTP_PROXY and NO_PROXY in the environment.
// No proxy option, no agent, no httpVersion, default adapter.
const res = await axios.get('https://example.com/', { signal: AbortSignal.timeout(15000) });
console.log(res.status);
```

**A different proxy per request** (every tested version):

```js
import axios from 'axios';
import { HttpsProxyAgent } from 'https-proxy-agent';

const agents = new Map();
const agentFor = (proxyUrl) => {
  if (!agents.has(proxyUrl)) agents.set(proxyUrl, new HttpsProxyAgent(proxyUrl));
  return agents.get(proxyUrl);
};

const viaProxy = (url, proxyUrl) =>
  axios.get(url, { proxy: false, httpsAgent: agentFor(proxyUrl), signal: AbortSignal.timeout(15000) });

const first = await viaProxy('https://example.com/', 'http://proxy-a.example:8080');
const second = await viaProxy('https://example.com/', 'http://proxy-b.example:8080');
console.log(first.status, second.status);
```

In the lab the two requests left through two different proxies. For `http://` URLs add an `HttpProxyAgent` from `http-proxy-agent` as `httpAgent`.

## A guard for your tests

Most causes above return `200`, so a normal test suite stays green when an upgrade or a new option starts bypassing the proxy. This test starts a stand-in proxy that records what reaches it and refuses it, then sends one request through the client your application builds:

```js
import assert from 'node:assert/strict';
import { once } from 'node:events';
import http from 'node:http';
import { test } from 'node:test';
import { createClient } from './client.mjs';

test('the HTTP client sends requests through the proxy', async () => {
  const seen = [];
  // A stand-in proxy: it records what arrives and refuses it, so nothing leaves the machine.
  const proxy = http.createServer((req, res) => {
    seen.push(`${req.method} ${req.url}`);
    res.writeHead(503).end();
  });
  proxy.on('connect', (req, socket) => {
    seen.push(`CONNECT ${req.url}`);
    socket.end('HTTP/1.1 503 Service Unavailable\r\n\r\n');
  });
  proxy.listen(0, '127.0.0.1');
  await once(proxy, 'listening');

  const client = createClient(`http://127.0.0.1:${proxy.address().port}`);
  // .invalid never resolves, so a request that skips the proxy cannot reach a real site.
  await client.get('https://guard.invalid/', { signal: AbortSignal.timeout(5000) }).catch(() => {});
  proxy.close();

  assert.deepEqual(seen, ['CONNECT guard.invalid:443']);
});
```

`createClient(proxyUrl)` is your own factory. With the per-request client above, `node --test` passed on all five main versions. After `adapter: 'fetch'` was added to the same client, it failed:

```text
not ok 1 - the HTTP client sends requests through the proxy
    Expected values to be strictly deep-equal:
    + actual - expected
    + []
    - [
    -   'CONNECT guard.invalid:443'
    - ]
# tests 1
# pass 0
# fail 1
# exit code: 1
```

## Versions to use or avoid

- **Use 1.21.1**, the latest release on the test date, or at least 1.20.0. Check two things after the upgrade: `proxy: false` next to a `proxyEnv` agent (cause 1), and redirects to `NO_PROXY` hosts (cause 14).
- **Before 1.16.1:** no CONNECT tunnel for `https://` URLs through an HTTP proxy (cause 5). Use the agent pattern or upgrade.
- **1.13.0 up to 1.19.0 with `httpVersion: 2`:** inside the range of GHSA-3pq3-5fj3-cg6v. On 1.20.0 and later HTTP/2 still ignores `HTTPS_PROXY` (cause 2).
- **Before 1.15.0 and before 1.20.0:** `NO_PROXY` misses trailing-dot hosts and CIDR ranges respectively (cause 13).
- **Node.js:** 24.22.2 and 26.13.0 routed every case the same way. The one difference: through the fetch adapter, Node 26 negotiated HTTP/2 with the lab target and Node 24 used HTTP/1.1.

## FAQ

### Why does Axios ignore HTTPS_PROXY?

In the lab it did so for six reasons: `proxy: false` on the request, `httpVersion: 2`, `adapter: 'fetch'`, a `proxy` object that takes precedence, a `NO_PROXY` match, or an `http://` URL, which reads `HTTP_PROXY` instead.

### Do I still need https-proxy-agent with Axios?

Not for a single HTTP proxy on Axios 1.16.1 or later: the `proxy` object and `HTTPS_PROXY` tunnelled on their own. You need it on older versions, and it is the simplest way to use a different proxy per request.

### Does Axios support SOCKS5 proxies?

Not through `proxy` or `HTTPS_PROXY`. Pass a `SocksProxyAgent` as `httpAgent` and `httpsAgent` with `proxy: false`.

### Why does my Axios request hang through a proxy when timeout is set?

On the tested versions `timeout` did not cover a proxy that fails to answer `CONNECT` (cause 8). Add `signal: AbortSignal.timeout(ms)`.

### Does the Axios proxy option work in the browser?

No. The docs mark `proxy` as Node.js only; a browser uses the proxy of the operating system or the browser itself.

## Related guides

- [Axios proxy setup](/guides/axios-proxy-setup) is the setup page: one explicit proxy check and which layer owns routing.
- [Proxy environment variables](/guides/proxy-environment-variables) compares how curl, Requests and Node read them.
- [Fix proxy error 407](/guides/fix-proxy-error-407) covers a 407 that isn't about encoding.
- [fetch failed: invalid onError method on Node.js 26](/guides/node-26-invalid-onerror-method) is the Node 26 failure of undici proxy agents.
- [Fix Node.js TypeError: fetch failed behind a proxy](/guides/fix-node-fetch-failed-proxy) reads the error chain when you use `fetch`.
- [NO_PROXY matching, tested](/blog/no-proxy-matching-tested) has the matching rules of other clients.

**Test the fix through a real IP.** ipvolt sells [residential proxies](/residential-proxies) from $2.20 per GB and a dedicated [mobile proxy](/mobile-proxies) from $9 a day. Put the proxy in the setup above and run the quick check. [Check a proxy now](/tools/proxy-checker).

## Sources & further reading

- [axios/axios#11402: axios@1.21.0 breaks custom https.Agent with proxyEnv enabled](https://github.com/axios/axios/issues/11402)
- [axios/axios#11242: align request handling across runtimes (direct agents for proxy: false)](https://github.com/axios/axios/pull/11242)
- [axios/axios commit 2498c23](https://github.com/axios/axios/commit/2498c233438eb72c9a9ee8540ded19c6ef4224fa)
- [GHSA-3pq3-5fj3-cg6v (CVE-2026-101898): HTTP/2 adapter bypasses configured DNS lookup and proxy controls](https://github.com/axios/axios/security/advisories/GHSA-3pq3-5fj3-cg6v)
- [GitLab advisory database: CVE-2026-101898](https://advisories.gitlab.com/npm/axios/CVE-2026-101898/)
- [axios/axios#11141: HTTP/2 proxy handling and CIDR matching for NO_PROXY](https://github.com/axios/axios/pull/11141)
- [GHSA-3p68-rc4w-qgx5: NO_PROXY hostname normalization bypass](https://github.com/axios/axios/security/advisories/GHSA-3p68-rc4w-qgx5)
- [GHSA-44g4-m2mj-wpvx (CVE-2026-101899): CIDR-form NO_PROXY entries are ignored](https://github.com/axios/axios/security/advisories/GHSA-44g4-m2mj-wpvx)
- [axios/axios#4531: Proxy support does not work properly with CONNECT on https requests](https://github.com/axios/axios/issues/4531)
- [axios/axios#3384: HTTPS over HTTP Proxy Fails](https://github.com/axios/axios/issues/3384)
- [axios/axios#2072: Axios proxy is not working](https://github.com/axios/axios/issues/2072)
- [axios/axios#6198: https proxy agent not working as expected](https://github.com/axios/axios/issues/6198)
- [axios/axios#10858: CONNECT tunnelling for HTTPS targets](https://github.com/axios/axios/pull/10858)
- [Axios 1.16.0 release notes](https://github.com/axios/axios/releases/tag/v1.16.0)
- [Axios 1.16.1 release notes](https://github.com/axios/axios/releases/tag/v1.16.1)
- [Axios 1.20.0 release notes](https://github.com/axios/axios/releases/tag/v1.20.0)
- [Axios 1.21.0 release notes](https://github.com/axios/axios/releases/tag/v1.21.0)
- [Axios 1.21.1 release notes](https://github.com/axios/axios/releases/tag/v1.21.1)
- [Axios docs: request config (proxy, httpAgent, httpsAgent, environment variables)](https://axios.rest/pages/advanced/request-config)
- [Axios 1.21.1 README: request config](https://github.com/axios/axios/blob/v1.21.1/README.md#request-config)
- [Axios 1.21.1: HTTP adapter source](https://github.com/axios/axios/blob/v1.21.1/lib/adapters/http.js)
- [Node.js HTTP: built-in proxy support and the Agent proxyEnv option](https://nodejs.org/api/http.html#built-in-proxy-support)
- [Node.js CLI: NODE_USE_ENV_PROXY=1](https://nodejs.org/api/cli.html#node_use_env_proxy1)
- [Node.js CLI: --use-env-proxy](https://nodejs.org/api/cli.html#--use-env-proxy)
- [socks-proxy-agent README](https://github.com/TooTallNate/proxy-agents/tree/main/packages/socks-proxy-agent)

## Related guides

- [Axios proxy setup: routing, auth and NO_PROXY](https://ipvolt.com/guides/axios-proxy-setup.md)
- [Proxy environment variables: HTTP_PROXY and NO_PROXY](https://ipvolt.com/guides/proxy-environment-variables.md)
- [Fix proxy error 407 without guessing](https://ipvolt.com/guides/fix-proxy-error-407.md)
- [fetch failed: invalid onError method on Node 26 (undici fix)](https://ipvolt.com/guides/node-26-invalid-onerror-method.md)
- [Fix Node.js TypeError: fetch failed behind a proxy](https://ipvolt.com/guides/fix-node-fetch-failed-proxy.md)

## About ipvolt

Examples use generic proxy settings, with links to the original technical documentation. Product-specific behavior must be checked with your provider. ipvolt sells mobile proxies and residential proxies from $2.20/GB.

## Plug in your first proxy.

Mobile from $9 a day. Residential from $2.20 per GB.

[Buy mobile](https://ipvolt.com/dashboard/mobile)

[Buy residential](https://ipvolt.com/dashboard/residential)

