Extração de dados

Como Configurar Proxies Residenciais no Node.js com Axios, Fetch e Got

A configuração do agente é dez linhas. Configurar um projeto Node para que os proxies permaneçam configuráveis, verificáveis e baratos é a parte que leva mais tempo. Um guia de configuração.

James Meadow

James Meadow

4 de setembro de 2026 · 9 min de leitura

Conseguir fazer uma única requisição passar por um proxy no Node é um problema de dez linhas. Todo tutorial termina aí, e então o projeto cresce: um segundo cliente HTTP aparece, credenciais ficam hardcoded em três arquivos, alguém precisa da Alemanha em vez dos Estados Unidos, e ninguém consegue responder se as requisições estão realmente saindo de onde deveriam.

Este é um guia de configuração, não um guia de sintaxe. Se o que você precisa é a configuração exata de agente que cada cliente espera, incluindo o motivo pelo qual o Axios precisa de proxy: false junto com seu agente, isso é abordado em detalhes em usando proxies residenciais no Node.js com Axios e Got. O que vem a seguir é como organizar um projeto para que essa fiação permaneça correta conforme o projeto cresce.

Decida quais clientes você realmente suporta

O Node tem três clientes HTTP em uso comum e eles recebem proxies por mecanismos diferentes. Suportar os três é normal em uma base de código de qualquer idade, mas isso deveria ser uma decisão, não um acidente.

O Axios precisa de um agente explícito, porque sua própria opção proxy não lida com o tunelamento HTTPS da forma que as pessoas esperam. Instale https-proxy-agent.

O Got recebe o agente em um slot agent.https em vez de uma opção de nível superior.

O fetch nativo passa pelo undici, então precisa de ProxyAgent como dispatcher. O undici vem com o Node, mas você vai querer tê-lo como dependência explícita se estiver construindo dispatchers você mesmo.

A consequência prática é que sua lista de dependências é determinada pelos clientes que você mantém, então manter dois clientes significa manter dois caminhos de proxy. A maioria das bases de código estaria melhor padronizando em um só e convertendo os remanescentes, e as que genuinamente precisam de dois deveriam pelo menos saber por quê.

Credenciais pertencem ao ambiente, não ao código-fonte

O gateway recebe o direcionamento no nome de usuário, o que significa que a string de credencial e a configuração de roteamento são a mesma string. Isso é conveniente, e também é como credenciais de proxy acabam sendo commitadas.

Mantenha as partes separadas na configuração:

PROXY_HOST=p.shifter.io
PROXY_PORT=443
PROXY_USER=customer-USERNAME
PROXY_PASS=your-password
PROXY_COUNTRY=us

Depois monte o nome de usuário em tempo de execução. A regra que economiza problemas mais tarde é que nenhum arquivo fora do seu módulo de proxy deveria conter uma URL de proxy literal. Uma vez que uma string de credencial com direcionamento embutido aparece inline em um scraper, ela é copiada, e as cópias divergem.

Não coloque a senha em uma URL que você loga. URLs de proxy são a forma mais comum de credenciais chegarem a um agregador de logs, porque a linha de debug natural é a URL inteira.

Um módulo constrói os agentes

A decisão estrutural mais importante é ter exatamente um lugar que transforma configuração em agente. É um módulo pequeno e evita uma classe inteira de problemas.

proxy.js
import { HttpsProxyAgent } from "https-proxy-agent";
const { PROXY_HOST, PROXY_PORT, PROXY_USER, PROXY_PASS } = process.env;
export function proxyUrl({ country, session, ttl } = {}) {
const parts = [PROXY_USER];
if (country) parts.push("country", country);
if (session) parts.push("sid", session);
if (session && ttl) parts.push("ttl", String(ttl));
const user = parts.join("-");
return `https://${user}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}`;
}
export function agentFor(opts) {
return new HttpsProxyAgent(proxyUrl(opts));
}

Dois detalhes nesse trecho valem a pena ser mencionados explicitamente. As flags de direcionamento são construídas a partir de opções nomeadas em vez de concatenar strings em cada ponto de chamada, o que é o que impede que um erro de digitação no nome de uma flag vire um 407 que parece um problema de credenciais. E ttl só é adicionado quando há uma sessão presente, porque um time to live não tem nada para manter vivo sem um identificador de sessão.

Os chamadores então nunca veem uma URL:

const agent = agentFor({ country: "de", session: "job-141", ttl: 600 });
// axios
await axios.get(url, { httpsAgent: agent, proxy: false });
// got
await got(url, { agent: { https: agent } });

O fetch nativo é o único que não recebe um agente, já que o undici quer um dispatcher em vez disso:

import { ProxyAgent, fetch } from "undici";
import { proxyUrl } from "./proxy.js";
const dispatcher = new ProxyAgent(proxyUrl({ country: "de" }));
await fetch(url, { dispatcher });

Manter proxyUrl exportado separadamente é o que permite que o caminho do fetch compartilhe configuração com os outros dois sem duplicar a construção da string.

Reutilize agentes e decida sessões antecipadamente

Um agente mantém um pool de conexões. Construir um por requisição descarta esse pool a cada vez, o que aparece como latência que você vai diagnosticar erroneamente como problema de rede.

Construa agentes uma vez por configuração que você usa e faça cache deles. Se você está alternando entre cinco países, isso são cinco agentes mantidos pela vida do processo, não um por requisição.

Sessões são a decisão relacionada. Sem um identificador de sessão o gateway rotaciona, o que é o que você quer para requisições independentes. Com sid você obtém um IP fixo (sticky), mantido pelo ttl que você especificar, o que é o que você quer para qualquer coisa com continuidade: um conjunto de resultados paginado, um fluxo de múltiplas etapas, qualquer coisa em que a segunda requisição precise vir do mesmo lugar que a primeira. O tempo fixo padrão é 120 segundos se você não definir um.

Escolher isso no momento da configuração em vez de por ponto de chamada é a diferença entre uma política de rotação coerente e uma base de código onde metade das requisições por acaso são fixas. As compensações estão detalhadas em sticky vs proxies residenciais rotativos.

Verifique antes de construir sobre isso

Escreva o script de verificação antes do scraper. Leva cinco minutos e transforma uma categoria inteira de confusão futura em uma resposta imediata.

import { agentFor } from "./proxy.js";
import axios from "axios";
const agent = agentFor({ country: "de" });
const { data } = await axios.get("https://api.ipify.org?format=json", {
httpsAgent: agent,
proxy: false,
});
console.log(data);

Se isso imprimir seu próprio endereço, o agente não está conectado e todas as requisições no projeto estão saindo direto. Este é um estado genuinamente comum de se estar por dias, porque nada falha: o código funciona, só não está usando o proxy. Verificar se o país realmente corresponde ao que você solicitou é a segunda metade da checagem, e o método para fazer isso corretamente está em testando velocidade de proxy, taxa de sucesso e precisão de localização.

Transforme isso em um script no package.json para que qualquer pessoa possa executá-lo quando algo parecer errado.

Mapeie os erros de uma vez

Erros de proxy são específicos o suficiente para serem diagnosticados automaticamente, e fazer isso em um único lugar é melhor do que interpretá-los repetidamente às três da manhã:

  • 407 significa que as credenciais estão erradas ou uma flag de direcionamento está malformada. Uma flag digitada errado cai aqui, motivo pelo qual vale a pena checar os nomes das suas flags antes da sua senha.
  • 502 significa que nenhuma saída corresponde ao seu filtro. O filtro está estreito demais, não a rede está fora do ar.
  • 509 significa que o limite de banda foi esgotado.
  • Connection refused geralmente significa um host ou porta legado deixado de uma configuração antiga.

Apenas falhas transitórias merecem uma nova tentativa. Tentar novamente um 407 em loop consome seu rate limit contra um problema que nunca vai se resolver sozinho, e tentar novamente um 509 não faz nada. Envolva as tentativas em um backoff real em vez de um atraso fixo, conforme abordado em rate limiting e throttling de requisições.

Limite a concorrência deliberadamente

O Node vai iniciar dez mil requisições de bom grado, e nenhum dos três clientes vai te impedir. Sob um proxy isso é pior que o normal, porque cada uma dessas requisições é um túnel que precisa ser estabelecido.

Use um limitador de concorrência desde o início em vez de adicionar um depois do primeiro incidente. Um limite modesto com throughput constante supera um burst sem limite que dispara defesas e depois gasta seu tempo tentando novamente.

Dev, CI e produção diferem

Três observações práticas que surgem em todo projeto Node depois que os proxies entram nele.

Tráfego residencial é cobrado por banda, então uma suíte de testes que atinge alvos reais através do proxy é uma conta recorrente sem benefício nenhum. Faça mock da camada HTTP nos testes unitários e mantenha um pequeno número de requisições reais em uma checagem separada, disparada manualmente.

O desenvolvimento local deveria usar o mesmo módulo e as mesmas variáveis de ambiente que a produção, com valores diferentes. Configuração que só existe em produção é configuração que ninguém testou.

E imagens de container não deveriam embutir credenciais. Passe-as em tempo de execução, assim como qualquer outro segredo.

Perguntas frequentes

Preciso do https-proxy-agent se eu só uso fetch?

Não. O ProxyAgent do undici cobre esse caminho. Você precisa do pacote de agente separado para Axios e Got.

Por que o Axios precisa de proxy: false quando eu já dei a ele um agente?

Porque o Axios vai, do contrário, tentar aplicar seu próprio tratamento de proxy sobre o agente, e os dois não se combinam. Definir como false entrega o trabalho inteiramente ao agente.

Posso definir o direcionamento por requisição em vez de por agente?

Você pode, mas cada configuração distinta é um agente distinto, então construir um por requisição é o que custa seu pool de conexões. Faça cache deles por chave de configuração.

O país deveria ser um valor de configuração ou um argumento por chamada?

Ambos, na prática. Um padrão na configuração, sobrescrevível por chamada para os jobs que precisam de uma região específica. O que você quer evitar é o país aparecer como um literal dentro de scrapers individuais.

Conclusão

A fiação de proxy no Node é pequena e bem compreendida. O que determina se um projeto permanece sustentável é o arranjo ao redor dela: um módulo que constrói agentes a partir de configuração, credenciais que vivem no ambiente, agentes reutilizados em vez de reconstruídos, uma política de sessão escolhida deliberadamente, um script de verificação que existe antes do scraper, e tratamento de erros que sabe a diferença entre um filtro estreito demais e uma senha errada.

Configure isso uma vez e adicionar uma biblioteca de cliente ou uma nova região vira uma mudança de configuração. Pule isso e cada novo requisito é uma busca pela base de código atrás de strings hardcoded. Detalhes do gateway estão na página de proxies residenciais, com taxas de banda na página de preços.

Pronto para começar?

Experimente os proxies residenciais da Shifter, mais de 205M IPs, mais de 195 países, a partir de $ 0,75/GB.

Começar