Configuração de Proxy Node.js: Axios, Fetch, Undici e Rotação
A opção de proxy do axios é uma armadilha para alvos HTTPS, e o fetch nativo ignora completamente suas variáveis de ambiente de proxy. Aqui está a configuração que funciona em axios, fetch e undici — agentes, autenticação, SOCKS5, rotação e streaming.
Roteamento de solicitações Node.js através de um proxy parece ser uma linha única e se transforma em uma tarde de depuração. A razão é que os três clientes HTTP que a maioria dos projetos usa — axios, o fetch nativo que foi incluído como global no Node 18, e a biblioteca subjacente undici — cada um aceita um proxy de maneira diferente, e nenhum deles se comporta como você espera. O Axios tem uma configuração de proxy embutida que é documentada, exclusiva para Node, e silenciosamente quebrada para alvos HTTPS por trás de um proxy HTTP: um bug que está aberto no rastreador do GitHub do axios desde 2020 e gerou uma discussão muito votada no Stack Overflow. Enquanto isso, o fetch nativo ignora as variáveis de ambiente HTTP_PROXY e não tem opção de proxy. Este guia oferece a configuração que realmente funciona em cada cliente, além de autenticação, SOCKS5, rotação e streaming.
Configuração de proxy do Axios vs agentes de proxy
O Axios vem com um objeto proxy — { host, port, auth } — e funciona bem para alvos HTTP simples. A armadilha é o HTTPS: quando o alvo é https:// e o proxy fala HTTP, o axios falha em abrir o túnel CONNECT e sua solicitação ou fica pendente ou retorna com seu IP real. A solução que a comunidade encontrou é ignorar completamente a configuração embutida e fornecer ao axios um agente de proxy, em seguida, definir proxy: false para que os dois mecanismos não entrem em conflito:
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@gate.quantumproxies.io:PORT");
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>" }
Dois detalhes economizam horas. Primeiro, use a importação desestruturada { HttpsProxyAgent } — versões recentes exportam como um símbolo nomeado, e uma importação padrão fornece um objeto que gera erro quando construído. Segundo, o esquema de URL do proxy permanece http:// mesmo quando o proxy transporta tráfego HTTPS: o esquema descreve como você alcança o proxy, e o TLS para o alvo ocorre dentro do túnel. A mesma classe de falha aparece em Python; se você também trabalha com requests, os padrões rimam com nosso guia de correção de ProxyError e SSLError.
Autenticação e variáveis de ambiente
Proxies autenticados usam credenciais HTTP Basic. Com um agente, incorpore-as no URL como http://user:pass@host:port; se a senha contiver @, : ou /, codifique o URL com encodeURIComponent() primeiro ou o URL se dividirá no lugar errado. Um 407 Proxy Authentication Required significa que as credenciais foram rejeitadas ou seu IP de origem não está na lista de permissões. O Axios também lê HTTP_PROXY, HTTPS_PROXY e NO_PROXY do ambiente — útil para proxyar uma biblioteca de terceiros sem tocar no código dela — e você desativa isso definindo proxy: false. O aviso importante: o fetch nativo não lê essas variáveis, então um scraper que depende de proxying por variáveis de ambiente vai diretamente no momento em que você troca de axios para fetch.

Proxying fetch nativo com undici
O fetch global do Node é construído sobre undici, e é no undici que o proxy vive. Você cria um ProxyAgent e o passa como a opção não padrão dispatcher — esta é a maneira moderna e leve de proxyar fetch, e lida com HTTPS CONNECT corretamente desde o início:
import { ProxyAgent } from "undici";
const dispatcher = new ProxyAgent({
uri: "http://gate.quantumproxies.io:PORT",
token: "Basic " + Buffer.from("USER:PASS").toString("base64"),
});
const res = await fetch("https://httpbin.org/ip", { dispatcher });
console.log(await res.json());
Se você estiver usando undici diretamente em vez de fetch global, o mesmo ProxyAgent se conecta a request() ou a setGlobalDispatcher() para proxyar todos os fetches no processo de uma só vez. Essa troca global de chamada única é a maneira mais limpa de rotear toda uma base de código através de um proxy sem passar um dispatcher por cada função.
Proxies SOCKS5 no Node.js
Nem axios nem undici falam SOCKS nativamente — passe uma string socks5:// para a configuração de proxy do axios e você receberá uma asserção de protocol mismatch. Instale socks-proxy-agent e use-o da mesma forma que o agente HTTPS, conectado tanto em httpAgent quanto em httpsAgent. Prefira socks5h:// sobre socks5://: o h final resolve DNS no lado do proxy, o que impede vazamentos de DNS e resolve nomes de host geograficamente restritos a partir da localização de saída. Cada plano de proxy SOCKS5 expõe o mesmo gateway sobre HTTP e SOCKS5, então isso é uma troca de esquema, não uma nova compra:
import axios from "axios";
import { SocksProxyAgent } from "socks-proxy-agent";
const agent = new SocksProxyAgent("socks5h://USER:PASS@gate.quantumproxies.io:PORT");
const client = axios.create({ httpAgent: agent, httpsAgent: agent });
const r = await client.get("https://httpbin.org/ip");
console.log(r.data);
Rotação sem uma lista de proxies
A receita antiga — um array de IPs, Math.random() por solicitação, poda dos inativos — é um código que você não mantém mais. Um gateway rotativo atribui um IP de saída novo no lado do servidor a cada solicitação, então um endpoint se comporta como um pool inteiro. Através de proxies residenciais rotativos esse pool abrange mais de 90 milhões de IPs em mais de 200 países, e o loop abaixo imprime uma origem diferente a cada iteração sem lógica de rotação:
import axios from "axios";
import { HttpsProxyAgent } from "https-proxy-agent";
const agent = new HttpsProxyAgent("http://USER:PASS@gate.quantumproxies.io:PORT");
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
}
Quando um fluxo abrange várias solicitações — login, adicionar ao carrinho, checkout — a rotação por solicitação quebra a sessão. Um parâmetro de sessão persistente no nome de usuário do proxy fixa um IP de saída por um período definido, depois rotaciona; mesmo endpoint, uma mudança de string. Se você estiver escalando isso para milhares de solicitações simultâneas, mova o trabalho fora dos loops do axios e leia nosso guia de arquitetura de scraping em larga escala para filas e orçamentos de concorrência.
Streaming de respostas através de um proxy
Baixar arquivos ou grandes cargas de JSON funciona da mesma forma que qualquer solicitação uma vez que o agente está anexado — defina responseType: "stream" e direcione o corpo para o disco. O proxy lida com a transferência de forma transparente, então uma exportação de 200MB nunca é armazenada em buffer na memória:
import fs from "node:fs";
const r = await client.get("https://example.com/large.json", {
responseType: "stream",
});
r.data.pipe(fs.createWriteStream("out.json"));

Perguntas frequentes
Por que meu proxy do axios não está funcionando?
A causa mais comum é um alvo HTTPS por trás de um proxy HTTP: a configuração de proxy embutida do axios falha em abrir o túnel CONNECT e retorna seu IP real ou fica pendente. Mude para um agente de proxy — anexe HttpsProxyAgent a httpAgent e httpsAgent, e defina proxy: false para que o axios pare de tentar lidar com o proxy por conta própria.
O axios suporta proxies SOCKS5?
Não nativamente — passar uma URL socks5:// para a configuração de proxy gera um erro de incompatibilidade de protocolo. Instale socks-proxy-agent, construa um SocksProxyAgent, e conecte-o tanto em httpAgent quanto em httpsAgent. Use o esquema socks5h:// para que o DNS seja resolvido no lado do proxy em vez de vazar da sua máquina.
Como uso um proxy com fetch nativo no Node.js?
O fetch nativo não tem opção de proxy e ignora variáveis de ambiente HTTP_PROXY. Crie um ProxyAgent do undici e passe-o como a opção dispatcher na chamada de fetch, ou chame setGlobalDispatcher() uma vez para proxyar todos os fetches no processo. O undici lida com HTTPS CONNECT corretamente sem configuração extra.
Como configuro um proxy do axios com variáveis de ambiente?
Exporte HTTP_PROXY, HTTPS_PROXY e opcionalmente NO_PROXY com URLs de proxy completos; o axios os lê automaticamente. Defina proxy: false em uma solicitação ou instância para fazer o axios ignorar o ambiente. Lembre-se de que isso afeta apenas o axios — undici e fetch nativo não captam essas variáveis.
Toda a história cabe em um cartão: o axios precisa de um agente e proxy: false, o fetch nativo precisa de um dispatcher do undici, SOCKS precisa de seu próprio agente, e a rotação pertence ao gateway em vez de no seu loop. Configure corretamente o encanamento e a última variável é a qualidade do IP — uma saída residencial limpa passa onde um IP de datacenter sinalizado recebe um 403 no mesmo código.
Obtenha proxies residenciais que passam na primeira solicitação