# Настройка прокси в Node.js: Axios, Fetch, Undici и ротация

Опция прокси в axios является ловушкой для HTTPS-целей, а встроенный fetch полностью игнорирует ваши переменные окружения прокси. Вот настройка, которая работает с axios, fetch и undici — агенты, аутентификация, SOCKS5, ротация и потоковая передача.

Маршрутизация запросов Node.js через прокси выглядит как однострочник, но превращается в полдня отладки. Причина в том, что три HTTP-клиента, которые используют большинство проектов — axios, встроенный `fetch`, который появился в Node 18, и библиотека undici — каждый по-разному обрабатывают прокси, и ни один из них не ведет себя так, как вы ожидаете. В axios есть встроенная конфигурация `proxy`, которая документирована, работает только в Node и тихо ломается для HTTPS-целей за HTTP-прокси: ошибка, которая открыта на GitHub axios с 2020 года и вызвала популярную тему на Stack Overflow. Встроенный fetch, тем временем, игнорирует переменные окружения `HTTP_PROXY` и вообще не имеет опции прокси. Это руководство дает вам настройку, которая действительно работает в каждом клиенте, плюс аутентификация, SOCKS5, ротация и потоковая передача.

## Конфигурация прокси в axios против прокси-агентов

Axios поставляется с объектом `proxy` — `{ host, port, auth }` — и он отлично работает для обычных HTTP-целей. Ловушка в HTTPS: когда цель — `https://`, а прокси говорит на HTTP, axios не может открыть туннель CONNECT, и ваш запрос либо зависает, либо возвращается с вашим реальным IP. Решение, на котором сообщество остановилось, — полностью обойти встроенную конфигурацию и передать axios прокси-агент, затем установить `proxy: false`, чтобы два механизма не конфликтовали:

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

// Note the destructured import — a default import is the classic gotcha.
const agent = new HttpsProxyAgent("http://USER:PASS@residentialpremium.quantumproxies.io:8080");

const client = axios.create({
  httpAgent: agent,   // for http:// targets
  httpsAgent: agent,  // for https:// targets
  proxy: false,       // disable axios' own broken proxy handling
  timeout: 15000,
});

const r = await client.get("https://httpbin.org/ip");
console.log(r.data); // { origin: "<proxy exit IP>" }
```

Две детали экономят часы. Во-первых, используйте **деструктурированный** импорт `{ HttpsProxyAgent }` — в последних версиях он экспортируется как именованный символ, а импорт по умолчанию дает объект, который вызывает ошибку при создании. Во-вторых, схема URL прокси остается `http://`, даже если прокси передает HTTPS-трафик: схема описывает, как вы достигаете прокси, а TLS к цели проходит внутри туннеля. Та же ошибка встречается в Python; если вы также работаете с requests, эти шаблоны перекликаются с нашим [руководством по исправлению ProxyError и SSLError](https://quantumproxies.io/blog/python-requests-proxyerror-fix).

## Аутентификация и переменные окружения

Аутентифицированные прокси используют учетные данные HTTP Basic. С агентом встраивайте их в URL как `http://user:pass@host:port`; если пароль содержит `@`, `:` или `/`, сначала закодируйте его с помощью `encodeURIComponent()`, иначе URL разделится в неправильном месте. Сообщение `407 Proxy Authentication Required` означает, что учетные данные были отклонены или ваш исходный IP не включен в белый список. Axios также читает `HTTP_PROXY`, `HTTPS_PROXY` и `NO_PROXY` из окружения — удобно для проксирования сторонней библиотеки без изменения ее кода — и вы отключаете это, установив `proxy: false`. Важное предупреждение: встроенный `fetch` **не** читает эти переменные, так что скрейпер, который полагается на проксирование через переменные окружения, тихо идет напрямую, как только вы переключаетесь с axios на fetch.

![Три фрагмента кода для одного и того же запроса: axios принимает HttpsProxyAgent в httpAgent и httpsAgent с proxy: false, встроенный fetch принимает dispatcher undici в каждом вызове, а setGlobalDispatcher из undici с ProxyAgent проксирует весь процесс. Путаница между ними становится главной причиной жалоб «прокси не работает».](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335145/blog/generated/qp-b9-007-diag1.png)
*Один и тот же запрос, три системы. Axios хочет агента, встроенный fetch хочет диспетчера undici, и их смешивание — причина номер один, почему 'прокси не работает'.*

## Проксирование встроенного fetch с undici

Глобальный `fetch` в Node построен на undici, и именно там живет прокси. Вы создаете `ProxyAgent` и передаете его как нестандартную опцию `dispatcher` — это современный, легкий по зависимостям способ проксирования fetch, и он корректно обрабатывает HTTPS CONNECT из коробки:

```js
import { ProxyAgent } from "undici";

const dispatcher = new ProxyAgent({
  uri: "http://residentialpremium.quantumproxies.io:8080",
  token: "Basic " + Buffer.from("USER:PASS").toString("base64"),
});

const res = await fetch("https://httpbin.org/ip", { dispatcher });
console.log(await res.json());
```

Если вы используете undici напрямую, а не глобальный fetch, тот же `ProxyAgent` подключается к `request()` или к `setGlobalDispatcher()`, чтобы проксировать каждый fetch в процессе сразу. Этот глобальный переключатель в одно действие — самый чистый способ маршрутизации всего кода через прокси без передачи диспетчера через каждую функцию.

## SOCKS5-прокси в Node.js

Ни axios, ни undici не поддерживают SOCKS нативно — передайте строку `socks5://` в конфигурацию `proxy` в axios, и вы получите утверждение о `несоответствии протокола`. Установите `socks-proxy-agent` и используйте его так же, как и агент HTTPS, подключив к `httpAgent` и `httpsAgent`. Предпочитайте `socks5h://` вместо `socks5://`: завершающая `h` разрешает DNS на стороне прокси, что предотвращает утечки DNS и разрешает геоограниченные имена хостов из точки выхода. Каждый план [SOCKS5-прокси](https://quantumproxies.io/socks5-proxies) предоставляет тот же шлюз через HTTP и SOCKS5, так что это смена схемы, а не новая покупка:

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

const agent = new SocksProxyAgent("socks5h://USER:PASS@residentialpremium.quantumproxies.io:1080");

const client = axios.create({ httpAgent: agent, httpsAgent: agent });
const r = await client.get("https://httpbin.org/ip");
console.log(r.data);
```

## Ротация без списка прокси

Старый рецепт — массив IP, `Math.random()` для каждого запроса, удаление неработающих — это код, который вы больше не поддерживаете. Вращающийся шлюз назначает новый выходной IP на стороне сервера для каждого запроса, так что одна конечная точка ведет себя как целый пул. Через [вращающиеся резидентные прокси](https://quantumproxies.io/rotating-proxies) этот пул охватывает более 90 миллионов IP в более чем 200 странах, и цикл ниже выводит разное происхождение на каждой итерации без логики ротации:

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

const agent = new HttpsProxyAgent("http://USER:PASS@residentialpremium.quantumproxies.io:8080");
const client = axios.create({ httpAgent: agent, httpsAgent: agent, proxy: false });

for (let i = 0; i < 3; i++) {
  const r = await client.get("https://httpbin.org/ip");
  console.log(r.data.origin); // a different exit IP each time
}
```

Когда поток охватывает несколько запросов — вход в систему, добавление в корзину, оформление — ротация для каждого запроса нарушает сессию. Параметр липкой сессии в имени пользователя прокси закрепляет один выходной IP на заданное время, затем вращается; та же конечная точка, одно изменение строки. Если вы масштабируете это до тысяч одновременных запросов, перенесите работу с циклов axios и прочитайте наше руководство по [архитектуре крупномасштабного скрейпинга](https://quantumproxies.io/blog/large-scale-web-scraping-architecture) для очередей и бюджетов параллелизма.

## Потоковые ответы через прокси

Загрузка файлов или больших JSON-пакетов работает так же, как и любой запрос, как только агент подключен — установите `responseType: "stream"` и направьте тело на диск. Прокси обрабатывает передачу прозрачно, так что экспорт размером 200 МБ никогда не буферизуется в памяти:

```js
import fs from "node:fs";

const r = await client.get("https://example.com/large.json", {
  responseType: "stream",
});
r.data.pipe(fs.createWriteStream("out.json"));
```

![Страница httpbin.org/ip показывает четыре ошибки прокси в Node.js: конфигурация proxy в axios возвращает ваш реальный IP или зависает, импорт агента по умолчанию выбрасывает ошибку, socks5:// в axios вызывает несоответствие протокола, а fetch игнорирует HTTP_PROXY. Карточка дает исправление для каждой, а примечание предостерегает от одновременной настройки агента и proxy.](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335146/blog/generated/qp-b9-007-diag2.png)
*Большинство сбоев прокси в Node.js сводится к пяти ошибкам: ошибка HTTPS в axios, импорт агента по умолчанию, дублированная конфигурация прокси, неправильная схема SOCKS или ожидание, что fetch прочитает переменные окружения.*

## Часто задаваемые вопросы

### Почему мой прокси в axios не работает?

Наиболее распространенная причина — HTTPS-цель за HTTP-прокси: встроенная конфигурация `proxy` в axios не может открыть туннель CONNECT и возвращает ваш реальный IP или зависает. Переключитесь на прокси-агент — подключите `HttpsProxyAgent` к `httpAgent` и `httpsAgent`, и установите `proxy: false`, чтобы axios перестал пытаться обрабатывать прокси самостоятельно.

### Поддерживает ли axios SOCKS5-прокси?

Не нативно — передача URL `socks5://` в конфигурацию `proxy` вызывает ошибку несоответствия протокола. Установите `socks-proxy-agent`, создайте `SocksProxyAgent` и подключите его к `httpAgent` и `httpsAgent`. Используйте схему `socks5h://`, чтобы DNS разрешался на стороне прокси, а не утекал с вашего компьютера.

### Как использовать прокси с встроенным fetch в Node.js?

Встроенный fetch не имеет опции прокси и игнорирует переменные окружения `HTTP_PROXY`. Создайте `ProxyAgent` в undici и передайте его как опцию `dispatcher` в вызове fetch, или вызовите `setGlobalDispatcher()` один раз, чтобы проксировать каждый fetch в процессе. Undici корректно обрабатывает HTTPS CONNECT без дополнительной конфигурации.

### Как установить прокси в axios с помощью переменных окружения?

Экспортируйте `HTTP_PROXY`, `HTTPS_PROXY` и, при необходимости, `NO_PROXY` с полными URL прокси; axios читает их автоматически. Установите `proxy: false` в запросе или экземпляре, чтобы axios игнорировал окружение. Помните, что это касается только axios — undici и встроенный fetch не будут использовать эти переменные.

Вся история умещается на карточке: axios нужен агент и `proxy: false`, встроенному fetch нужен диспетчер undici, SOCKS нужен свой агент, а ротация должна быть на шлюзе, а не в вашем цикле. Настройте правильно, и последняя переменная — качество IP — чистый резидентный выход проходит там, где отмеченный датацентр IP получает 403 на том же коде.

[Получите резидентные прокси, которые проходят с первого запроса](https://quantumproxies.io/residential-proxies)
