TypeError: fetch failed в Node.js через прокси

Встроенный fetch в Node.js показывает общий текст «fetch failed», а настоящая причина лежит в поле cause. Через прокси к этому добавляется ещё одна ловушка: fetch по умолчанию не читает переменные прокси.

Обновлено · Редакция Prokso

Коротко
  • fetch failed — лишь обёртка: настоящая причина лежит в err.cause
  • Встроенный fetch читает HTTP_PROXY только с NODE_USE_ENV_PROXY=1 или --use-env-proxy
  • Проще всего передать dispatcher с ProxyAgent из undici прямо в fetch

Что означает ошибка

По документации Node.js, глобальный fetch построен на библиотеке undici. Когда запрос не удаётся на уровне сети, undici отклоняет его ошибкой TypeError: fetch failed, а исходную ошибку кладёт в error.cause. Поэтому смотреть нужно именно туда: console.log(err.cause).

В cause будет, например, ECONNREFUSED, ENOTFOUND, тайм-аут подключения с кодом UND_ERR_CONNECT_TIMEOUT или ответ прокси. Если прокси не принял логин для HTTPS-адреса, undici пишет Proxy response (407) !== 200 when HTTP Tunneling.

Вторая ловушка: переменные HTTP_PROXY и HTTPS_PROXY встроенный fetch читает только тогда, когда включена встроенная поддержка прокси. Переменная NODE_USE_ENV_PROXY=1 появилась в Node.js 24.0.0 и 22.21.0, флаг --use-env-proxy — в 24.5.0 и 22.21.0; документация помечает эту возможность как активно развивающуюся. Без этого запрос идёт напрямую, мимо прокси.

Причины

  • Прокси не подключён. Переменные окружения заданы, но fetch их не читает без NODE_USE_ENV_PROXY=1 или --use-env-proxy, и запрос идёт с вашего IP.
  • Неверный хост или порт. В cause видно ECONNREFUSED или ENOTFOUND: ошибка в gw.prokso.com или порт вне 823, 824 и 10000–20000.
  • Логин или пароль не принят. Для HTTPS-адресов в cause приходит «Proxy response (407) !== 200 when HTTP Tunneling». Ответ шлюза Prokso в этом случае — «HTTP/1.1 407 NO_USER».
  • SOCKS5-порт для HTTP-агента. ProxyAgent с адресом http:// на порт 824 говорит HTTP с SOCKS5-портом, и соединение не устанавливается.
  • Сайт не ответил вовремя. Тайм-аут подключения или чтения: прокси или сайт не успели ответить.

Как исправить

  1. Выведите причину: catch (err) { console.log(err.cause) }. Код в cause подскажет, с какого шага начать.
  2. Подключите прокси явно: установите пакет undici и передайте в fetch dispatcher: new ProxyAgent('http://ЛОГИН:ПАРОЛЬ@gw.prokso.com:823'). Документация Node.js подтверждает, что глобальный fetch принимает dispatcher, совместимый с undici.
  3. Чтобы брать прокси из переменных окружения, используйте EnvHttpProxyAgent из undici через setGlobalDispatcher() или запустите Node.js с NODE_USE_ENV_PROXY=1 либо --use-env-proxy, если ваша версия это поддерживает.
  4. При 407 скопируйте логин и пароль из личного кабинета заново. Если в пароле есть спецсимволы, закодируйте их через encodeURIComponent. Синтаксис логина и порты собраны на странице логин, порты и параметры.
  5. Для HTTP-агента берите порт 823 или порт 10000–20000 для фиксированного IP. Другие варианты подключения — в инструкции Node.js.
  6. Если в cause тайм-аут, уменьшите число параллельных запросов и см. страницу тайм-аут прокси.

Как проверить, что всё заработало

Сделайте fetch на https://prokso.com/ip с тем же dispatcher. Если в JSON IP и страна прокси, подключение работает. Саму строку можно отдельно проверить в проверке прокси.

Диагностика за 2 минуты

Сначала вставьте строку в проверку прокси. Если там прокси работает, причина в программе или её настройках. Если нет — проверьте строку из терминала:

curl -v -x "http://ЛОГИН:ПАРОЛЬ@gw.prokso.com:823" https://api.ipify.org
  • Строка < HTTP/1.1 407 сразу после CONNECT — отвечает прокси. Название после кода, например NO_USER, подсказывает причину.
  • Прокси ответил на CONNECT кодом 200, а дальше пришёл другой код — прокси работает, этот ответ дал сайт.
  • Никакого ответа, только тайм-аут — соединение не дошло до прокси: проверьте хост, порт и сеть.

Инструкции, где встречается эта ошибка

Вопросы и ответы

Почему fetch работает, но IP в ответе мой?

Скорее всего, прокси просто не подключён: встроенный fetch не читает HTTP_PROXY без NODE_USE_ENV_PROXY=1 или --use-env-proxy. Передайте dispatcher явно.

Поддерживает ли NODE_USE_ENV_PROXY SOCKS5?

Документация Node.js описывает для встроенной поддержки только адреса прокси HTTP и HTTPS. Для SOCKS5 используйте отдельный агент или библиотеку.

В cause ошибка сертификата. Это прокси?

Порт 823 не подменяет сертификаты сайтов, так что причину ищите в системе или на сайте. См. <a href="/ru/errors/ssl-certificate-errors">ошибки SSL-сертификата</a>.

Как узнать версию undici в Node.js?

По документации Node.js — через свойство process.versions.undici.

Резидентские $1.59, мобильные $2.50, серверные $0.65 за 1 ГБ

Регистрация за минуту, доступы сразу после оплаты.

Создать аккаунт