Geonode logo
Geonode Team

Geonode Team

Atualizado: 7 de outubro de 2026

Publicado: 2 de setembro de 2026

Axios vs Fetch

Há uma diferença que se destaca mais do que todas as outras juntas: o `fetch` não rejeita em caso de erros HTTP. Um erro 404 ou 500 é resolvido com sucesso e o seu código continua a funcionar. Tudo o resto — tamanho do pacote, sintaxe, interceptores — é uma questão de preferência. Essa característica específica é uma fonte de erros e trata-se de um comportamento documentado, e não de uma peculiaridade. Este guia aborda o que cada ferramenta faz efetivamente, de acordo com a sua própria documentação, o código padrão que se deve escrever para que o `fetch` funcione corretamente e a lacuna do proxy no Node que costuma apanhar as pessoas de surpresa.

Existem duas formas de efetuar um pedido HTTP em JavaScript, que são alvo de discussões intermináveis, e o debate centra-se geralmente nos aspetos menos importantes.

O tamanho do pacote, a elegância da sintaxe, se uma dependência se justifica — tudo isto são preferências, e pessoas sensatas podem ter opiniões diferentes. Uma diferença não é uma preferência e gera erros reais no código de produção: fetch não rejeita a sua promessa quando o servidor devolve um estado de erro. Um 404 é resolvido. Um 500 é resolvido. O seu .catch() nunca é executado e o código prossegue como se tudo tivesse funcionado.

Trata-se de um comportamento documentado e não de uma peculiaridade, e é isso que deve ser compreendido antes de mais nada.

Somos a Geonode e comercializamos proxies, pelo que a nota relevante para o tema vai aqui: existe uma diferença genuína e pouco documentada entre estes dois no que diz respeito ao suporte a proxies no Node, e isso confunde as pessoas regularmente. O fetch nativo no Node não reconhece as variáveis de ambiente padrão do proxy, o que surpreende quase toda a gente que assume que se comporta como o curl. Isso tem a sua própria secção e, se não estiveres a encaminhar pedidos através de um proxy, podes ignorá-la completamente — a maioria das pessoas deve fazê-lo.

Uma pequena nota de organização, uma vez que afeta quem estiver a seguir links mais antigos: A documentação do Axios mudou de endereço. axios-http.com redireciona agora para axios.rest. Os marcadores e as respostas do Stack Overflow que apontam para o domínio antigo continuam a funcionar através do redirecionamento, mas o endereço canónico mudou.

Tudo o que se segue sobre o comportamento provém da MDN e da própria documentação do Axios, e não da memória de ninguém.

A diferença que causa erros reais

Comece por aqui, porque é a única diferença que não é uma questão de gosto.

O que diz a MDN

Diretamente da documentação:

«Uma promessa do tipo «fetch()

» só é rejeitada quando o pedido falha, por exemplo, devido a um URL de pedido mal formado ou a um erro de rede. Uma promessa fetch()

não rejeita se o servidor responder com códigos de estado HTTP que indiquem erros (404

, 504

, etc.). Em vez disso, um manipulador then()

deve verificar as propriedades Response.ok

e/ou Response.status

.»

A ênfase em não é da própria MDN.

O que isso significa na prática

// Looks correct. Is not.
try {
  const res = await fetch('/api/user/999');
  const user = await res.json();
  showUser(user);          // runs on a 404
} catch (err) {
  showError(err);          // never runs on a 404
}

O servidor devolveu um 404 com um corpo de erro. fetch

foi resolvido sem problemas. res.json()

analisou o objeto de erro. showUser

recebeu algo que não é um utilizador, e a falha surge mais tarde, noutro local, como um erro confuso sobre uma propriedade indefinida.

A versão correta:

try {
  const res = await fetch('/api/user/999');
  if (!res.ok) {
    throw new Error(`HTTP ${res.status}`);
  }
  const user = await res.json();
  showUser(user);
} catch (err) {
  showError(err);
}

Três linhas adicionais, e são obrigatórias em todas as solicitações que escrever.

Como o Axios se comporta

Por predefinição, o Axios rejeita códigos de estado fora do intervalo 2xx. O código equivalente não necessita de verificação de estado:

try {
  const { data } = await axios.get('/api/user/999');
  showUser(data);
} catch (err) {
  showError(err);          // runs on a 404
}

Qual é o comportamento correto

Ambos são defensáveis, e a discordância é de natureza filosófica.

fetch

defende que a transferência foi bem-sucedida — o servidor foi alcançado, respondeu e a resposta chegou intacta. Um 404 é uma resposta válida a uma pergunta, não uma falha ao fazê-la. Rejeitar confundiria uma falha de transporte com a semântica da aplicação. Esta é, aliás, exatamente a posição do curl também, onde um 404 também produz um código de saída zero.

O Axios defende que a maioria dos utilizadores trata um código 4xx ou 5xx como uma falha, pelo que deve comportar-se como tal.

A realidade prática é que o modelo do «fetch

» é mais correto e mais propenso a erros, porque exige disciplina em cada chamada e nada o avisa quando essa disciplina falha.

O que é o Fetch e quanto custa

A norma, com as suas vantagens e as suas lacunas.

As vantagens

Está integrado. Sem dependências, sem instalação, sem custos de pacotes, sem cadeia de abastecimento para auditar. Nos navegadores e no Node moderno, está simplesmente lá.

É um padrão. Especificado, em vez de mantido por um projeto que possa mudar de direção, ser abandonado ou introduzir uma alteração compatibilidade com o seu próprio calendário.

É a base. Muitas bibliotecas de nível superior são wrappers à sua volta, pelo que compreender o fetch significa compreender o que elas fazem.

Lida bem com streaming. Response.body é um fluxo legível, o que torna natural o processamento progressivo de respostas de grande dimensão.

O que não faz

Estas são as lacunas que o utilizador preenche por si próprio, e o seu número constitui o verdadeiro argumento a favor do Axios.

Não há JSON automático. Chama-se .json(), o que representa mais um await e mais um ponto de falha se a resposta não for JSON — uma página de erro HTML, por exemplo, que é exatamente o que se obtém de um servidor mal configurado.

Não há rejeição de estado. Já abordado acima.

Sem tempo limite por predefinição. Uma chamada fetch pode ficar bloqueada indefinidamente. AbortSignal.timeout() fornece um tempo limite em ambientes modernos, mas é opcional e fácil de esquecer — o que é mais importante precisamente nas situações em que um bloqueio é mais grave.

Sem interceptores. Não há onde anexar um token de autenticação, um ID de correlação ou registar centralmente. Ou cada chamada repete o processo ou escreve-se um wrapper, e é ao escrever um wrapper que as pessoas acabam por criar acidentalmente o seu próprio Axios, mas pior.

Sem progresso de upload. O progresso de download é possível através do fluxo de resposta; o progresso de upload não é tão simples.

Sem serialização automática do corpo da solicitação. Chama-se JSON.stringify e define-se o tipo de conteúdo manualmente, sempre.

Sem configuração de proxy no Node. Tem a sua própria secção abaixo.

O resumo honesto

O fetch é uma primitiva de baixo nível bem concebida. As suas omissões são deliberadas — uma norma deve ser mínima e imparcial.

A questão não é se é boa. É se quer implementar a camada em falta por si próprio e se a versão que implementar será melhor do que aquela mantida por um projeto com uma grande base de utilizadores a identificar os seus casos extremos.

O que o Axios lhe oferece

Segundo a sua própria documentação, a lista de funcionalidades é o argumento principal.

Cliente HTTP baseado em Promises com uma interface consistente em todos os ambientes, disponibilizando pacotes separados para navegador e Node.

Interceptores para pedidos e respostas, que constituem a funcionalidade mais valiosa e a mais difícil de replicar de forma limpa. Basta anexar um cabeçalho de autenticação uma vez, tratar a atualização 401 uma vez, adicionar o registo uma vez — e todos os pedidos na aplicação herdam essas configurações.

Tratamento automático de JSON em ambas as direções. Os corpos das solicitações são serializados e o tipo de conteúdo é definido; as respostas são analisadas para um response.data.

Tratamento de erros com rejeição em códigos de estado que não sejam 2xx.

Configuração de tempo limite, descrita na documentação como uma forma de evitar que as solicitações fiquem pendentes indefinidamente. Um único valor de configuração, em vez de um controlador de abortamento por chamada.

Cancelamento de pedidos em curso.

Acompanhamento do progresso tanto para uploads como para downloads, algo que o fetch não oferece de forma direta.

Proteção XSRF integrada.

Envio de ficheiros e dados de formulários multipart tratados automaticamente.

Limitação de taxa e regulação de pedidos.

Instâncias com predefinições, para que um cliente configurado com um URL base, cabeçalhos e tempo de espera possa ser criado uma vez e importado para qualquer lugar.

Os custos

Uma dependência. Algo para instalar, manter atualizado e auditar. Num ambiente preocupado com a segurança, isso representa um custo real e não apenas teórico.

Tamanho do pacote. Significativo para um front-end pequeno, insignificante para uma aplicação de grande dimensão ou qualquer coisa do lado do servidor.

Mais uma abstração para aprender, e que, ocasionalmente, se comporta de forma diferente da plataforma subjacente, de maneiras que o podem surpreender.

A perspetiva justa

O Axios é, grosso modo, o que a maioria das pessoas acaba por construir com base no fetch quando precisa destes comportamentos — só que já está escrito, já foi depurado e já lida com os casos em que ainda não pensaste.

Se não precisares de nenhum deles, é uma dependência desnecessária.

Comparação lado a lado

fetchAxios
InstalaçãoIntegradanpm install
Rejeita erros 404/500NãoSim
Análise de JSONManual .json()Automática
Serialização do corpo da solicitaçãoManualAutomática
Tempo limiteAbortSignal.timeout()Opção de configuração
InterceptoresNãoSim
Progresso do uploadNão é simplesSim
Progresso do downloadAtravés do fluxo de respostaSim
CancelamentoAbortControllerIntegrado
Proteção XSRFManualIntegrada
Instâncias com valores predefinidosNãoSim
Configuração de proxy no NodeNãoSim
TransmissãoExcelenteMais limitada
Custo do pacoteZeroPequeno, mas diferente de zero

A mesma solicitação, de ambas as formas

// fetch, written correctly
const res = await fetch('https://api.example.com/users', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': `Bearer ${token}`
  },
  body: JSON.stringify({ name: 'Alice' }),
  signal: AbortSignal.timeout(5000)
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();

// Axios
const { data } = await axios.post(
  'https://api.example.com/users',
  { name: 'Alice' },
  { headers: { Authorization: `Bearer ${token}` }, timeout: 5000 }
);

Ambas estão corretas. A versão do fetch tem onze linhas, contra as cinco do Axios, e a diferença consiste inteiramente em aspetos que é necessário lembrar em cada chamada, em vez de configurar uma única vez.

As duas linhas que fazem a diferença

Rejeições em 404/500 e configuração do proxy no Node são as únicas linhas em que uma ferramenta não consegue fazer diretamente o que a outra faz. O resto é código padrão, e o código padrão representa um custo, mas não uma impossibilidade.

O «Boilerplate Tax»

A verdadeira comparação não é entre uma chamada ao fetch

e uma chamada ao axios

. É entre uma base de código que utiliza cada uma delas.

O que toda a gente acaba por escrever

Depois de ter repetido a verificação de estado, o tempo de espera e a análise de JSON pela terceira ou quarta vez, escreve isto:

async function request(url, options = {}) {
  const res = await fetch(url, {
    ...options,
    headers: {
      'Content-Type': 'application/json',
      ...(token && { Authorization: `Bearer ${token}` }),
      ...options.headers
    },
    signal: options.signal ?? AbortSignal.timeout(options.timeout ?? 10000)
  });
  if (!res.ok) {
    const body = await res.text();
    throw new HttpError(res.status, body);
  }
  return res.status === 204 ? null : res.json();
}

Trata-se de um wrapper razoável e bastante bom. É também, sem dúvida, um pequeno Axios.

O que o wrapper não irá resolver até que alguém repare

Nova tentativa com backoff. Atualização do token no erro 401 sem uma enxurrada de pedidos quando várias chamadas falham ao mesmo tempo. Pedidos que devolvem HTML em vez de JSON. Respostas 204 sem corpo. Cancelamento propagado através de chamadas aninhadas. Progresso do upload. Tipos de conteúdo que não sejam JSON. IDs de correlação para rastreamento.

Cada um é uma pequena adição. Em conjunto, formam uma biblioteca, e a versão que escrever será menos testada do que aquela que milhares de pessoas já estão a utilizar.

Quando é aconselhável escrevê-lo por conta própria

Quando precisar de muito pouco dele. Um punhado de pedidos GET para uma API. O wrapper acima tem trinta linhas e é inteiramente da sua autoria.

Quando o tamanho do pacote é realmente importante. Uma página em que o desempenho é crítico e cada kilobyte conta.

Quando as dependências são dispendiosas. Ambientes em que cada pacote requer revisão.

Quando queres compreender a plataforma. Uma razão legítima, e essa compreensão é transferível.

Quando não é a opção certa

Quando se encontra na terceira iteração do wrapper, quando diferentes partes da base de código têm wrappers diferentes, ou quando está a adicionar lógica de repetição de tentativas. Nessa altura, está a manter uma biblioteca como um projeto paralelo, e a dependência que evitou é mais económica do que aquela que criou.

Tamanho do pacote e a questão dos nós

Os dois fatores contextuais que influenciam a resposta.

No navegador

O Axios aumenta o peso do teu pacote. Se isso é relevante ou não depende inteiramente do que estás a desenvolver.

Uma página de destino ou um widget em que o tempo de carregamento é o produto — usa fetch. Cada kilobyte conta, e os padrões de pedidos são normalmente suficientemente simples para que o código padrão seja trivial.

Uma aplicação de grande dimensão que já inclui um framework e uma biblioteca de componentes — o custo marginal é insignificante, e o suporte a interceptores vale consideravelmente mais do que os bytes.

A verdade é que o tamanho do pacote é o argumento a que as pessoas recorrem quando querem uma razão técnica para uma preferência estética. É real, mas é decisivo com muito menos frequência do que é citado.

No Node

É um cálculo completamente diferente. O tamanho do pacote é irrelevante num servidor, pelo que o principal argumento contra o Axios perde todo o sentido.

O fetch nativo está disponível no Node moderno e funciona bem. Mas o código do lado do servidor tende a precisar precisamente das coisas que o fetch omite: tempos de espera em tudo, novas tentativas com backoff, gestão centralizada da autenticação, registo estruturado de chamadas de saída e — como a próxima secção aborda — configuração de proxy.

Assim, a balança pende mais para o Axios no servidor do que no navegador, o que é o oposto de como o argumento é normalmente apresentado.

O compromisso de que ninguém fala

Pode usar ambos. O fetch para chamadas simples e o Axios quando precisar da maquinaria. Nada o impede e o argumento da consistência é mais fraco do que parece.

O que realmente causa problemas são três wrappers próprios diferentes numa única base de código, cada um a lidar com erros de forma ligeiramente diferente. Isso é pior do que utilizar qualquer uma das bibliotecas de forma consistente, e é aí que acaba por cair um número surpreendente de projetos.

Proxies em ambos

O nosso território e a origem de uma tarde verdadeiramente confusa para muitos programadores.

A versão resumida

O fetch nativo do Node não lê as variáveis de ambiente padrão do proxy. Definir HTTP_PROXY e HTTPS_PROXY não tem qualquer efeito, ao contrário do curl, ao contrário da maioria das bibliotecas HTTP e ao contrário do que quase toda a gente espera.

O fetch global do Node é baseado no undici, e o encaminhamento através de um proxy requer a especificação explícita de um despachador:

import { ProxyAgent, setGlobalDispatcher } from 'undici';

setGlobalDispatcher(new ProxyAgent('http://user:pass@proxy.example.com:8080'));

// now fetch goes through the proxy
const res = await fetch('https://example.com');

Ou por pedido, passando a opção dispatcher.

Axios no Node

O Axios tem uma opção de configuração proxy:

const res = await axios.get('https://example.com', {
  proxy: {
    protocol: 'http',
    host: 'proxy.example.com',
    port: 8080,
    auth: { username: 'user', password: 'pass' }
  }
});

Para proxies SOCKS, ou para um controlo mais preciso, a abordagem habitual é uma biblioteca de agente passada como httpAgent e httpsAgent.

No navegador, nenhum dos dois consegue

Vale a pena referir isto porque poupa tempo. O JavaScript num navegador não consegue definir um proxy. O navegador utiliza o que quer que o sistema ou uma extensão tenha configurado, e nenhuma biblioteca altera isso. A opção proxy do Axios é uma funcionalidade do Node.

Se precisar de pedidos via proxy a partir de código baseado no navegador, o pedido tem de passar por um servidor que controle.

O indício de depuração

Se um proxy «não estiver a funcionar» no Node, verifique qual o cliente que está a efetuar a solicitação antes de verificar qualquer outra coisa. Código que funciona com o Axios e falha com o fetch — ou vice-versa — é quase sempre este, e é invisível porque nenhum deles apresenta erros. A solicitação simplesmente segue diretamente.

Verifique solicitando um endpoint de relatório de endereço através do seu cliente configurado e confirmando se o endereço devolvido é o do proxy.

E a parte que vai contra o nosso próprio interesse

A maioria das chamadas HTTP do lado do servidor não precisa de proxy nenhum. Chamar uma API para a qual tem credenciais, a partir de um servidor autorizado a aceder à mesma, não requer nada de extra — um proxy acrescenta latência, um ponto de falha e uma fatura. Os proxies justificam a sua existência para a verificação geográfica e para a recolha em grande volume, onde se aplicam limites de taxa por endereço. Fora isso, o cliente simples é o melhor cliente.

Qual escolher

Uma lista de critérios de decisão, em vez de um veredicto.

Utilize o fetch quando

O tamanho do pacote for realmente crítico. Páginas de destino, widgets, scripts incorporados.

Os seus pedidos forem simples. Alguns pedidos GET, tratamento de erros mínimo, sem autenticação partilhada.

Não é possível adicionar dependências, ou todos os pacotes requerem revisão.

Está a trabalhar com fluxos. O modelo de streaming do fetch é melhor e isto é uma vantagem técnica real, em vez de uma mera preferência.

Quer aprender a plataforma. O conhecimento é transferível; o conhecimento específico do Axios não é.

Utilize o Axios quando

Precisa de interceptores. Autenticação centralizada, atualização de tokens, registo, IDs de correlação. Esta é a razão mais forte e não tem um equivalente claro no fetch.

Está no servidor. O tamanho do pacote não é relevante e as funcionalidades em falta são exatamente aquilo de que o código do servidor necessita.

Precisa de acompanhar o progresso do upload, o que o fetch não facilita.

Está a efetuar muitas solicitações variadas numa base de código extensa e pretende um comportamento consistente sem ter de manter um wrapper.

Precisa de configuração de proxy e prefere utilizar uma opção documentada em vez de montar um dispatcher.

Seja qual for a sua escolha

Defina sempre um tempo limite. AbortSignal.timeout() ou a opção timeout do Axios. Uma solicitação sem um tempo limite pode ficar pendente indefinidamente, e esta é a falha de fiabilidade mais comum no código HTTP em JavaScript.

Verifique sempre o estado com fetch. Em todas as chamadas, sem exceção. «res.ok» são duas palavras e a ausência delas é o bug com que este artigo começou.

Centralize tudo. Um wrapper ou uma instância do Axios configurada. Três abordagens inconsistentes numa única base de código são piores do que qualquer uma das bibliotecas, e é o resultado que ninguém escolhe deliberadamente.

Perguntas frequentes

Qual é a principal diferença entre o Axios e o fetch?

O tratamento de erros. De acordo com o MDN, uma promessa «fetch» «não rejeita se o servidor responder com códigos de estado HTTP que indiquem erros» — deve verificar o «response.ok» por si próprio. O Axios rejeita códigos de estado que não sejam 2xx. Todo o resto é uma questão de conveniência: o Axios adiciona interceptores, conversão automática para JSON, tempos limite, progresso e configuração de proxy.

O Axios ainda é necessário agora que o fetch está integrado?

Depende do que precisas. Para pedidos simples, não. Para interceptores, progresso de upload, predefinições por instância ou configuração de proxy no Node, o Axios ainda oferece funcionalidades que o fetch não oferece, e escrevê-las tu mesmo implica manter uma pequena biblioteca.

Por que é que o fetch não lança uma exceção em caso de 404?

Porque a transferência foi bem-sucedida — o servidor foi alcançado e respondeu. O fetch trata um 404 como uma resposta válida, em vez de uma solicitação falhada, e rejeita apenas em caso de erros de rede ou de um URL mal formado. Verifique response.ok em cada chamada.

O que é mais rápido, o Axios ou o fetch?

Para uma única solicitação, a diferença é insignificante; ambos estão limitados pela rede. O Axios acrescenta uma pequena quantidade de processamento e, no navegador, uma pequena quantidade de download para a própria biblioteca.

Como defino um tempo limite com o fetch?

AbortSignal.timeout(5000) passado como a opção «signal» em ambientes modernos, ou um «AbortController» com o seu próprio temporizador. Não existe um tempo limite predefinido, pelo que uma solicitação sem um pode ficar pendente indefinidamente.

O «fetch» funciona com proxies no Node?

Não através das variáveis de ambiente habituais. O «fetch» global do Node é baseado no «undici» e não lê «HTTP_PROXY» nem «HTTPS_PROXY». Tem de fornecer um despachador ProxyAgent, quer globalmente com setGlobalDispatcher, quer por pedido. O Axios tem, em vez disso, uma opção de configuração proxy.

Posso utilizar um proxy com o fetch no navegador?

Não. O JavaScript do navegador não consegue configurar um proxy — o navegador utiliza as definições do sistema ou das extensões. A opção de proxy de qualquer biblioteca é uma funcionalidade exclusiva do Node. As solicitações encaminhadas por proxy a partir do navegador têm de passar por um servidor que esteja sob o seu controlo.

Devo utilizar tanto o Axios como o fetch num único projeto?

Isso, por si só, não constitui um problema. O que causa verdadeiros problemas são vários wrappers personalizados e inconsistentes, com comportamentos de erro diferentes. A consistência na forma como as falhas são tratadas é mais importante do que a biblioteca que gerou a solicitação.

Conclusão

Uma diferença é de fundo e o resto é uma questão de preferência.

** O fetch não rejeita em caso de erros HTTP.** O MDN afirma-o explicitamente: um erro 404 ou 504 é resolvido, e o utilizador deve verificar por si próprio response.ok ou response.status. Se isso lhe escapar numa chamada, a falha manifesta-se noutro local completamente diferente, como um erro confuso sobre dados que nunca foram válidos. O Axios rejeita códigos de estado que não sejam 2xx por predefinição. Ambas as posições são defensáveis; apenas uma exige disciplina em cada chamada, e a disciplina não é uma característica que as bases de código mantêm quando estão sob pressão de prazos.

Tudo o resto resume-se ao que está a construir. No navegador, o fetch está integrado e é gratuito, e para padrões de pedidos simples o código padrão é trivial. No servidor, o tamanho do pacote deixa de ser relevante e as funcionalidades que o fetch omite — tempos de espera, interceptores, repetição de tentativas, configuração de proxy — são precisamente o que o código do servidor precisa, pelo que a balança pende para o outro lado.

O teste que vale a pena aplicar: se escreveste um wrapper em torno de fetch e este tem agora mais de cerca de trinta linhas, estás a manter uma pequena biblioteca HTTP. Essa é uma escolha legítima feita deliberadamente e uma má escolha feita por acidente.

Quanto aos proxies, e esta é a parte em que as pessoas perdem uma tarde inteira: o fetch nativo no Node ignora as variáveis de ambiente padrão do proxy. Definir HTTPS_PROXY não tem qualquer efeito, o pedido é enviado diretamente e não ocorre qualquer erro. Forneça um despachante undici ProxyAgentou utilize a opçãoproxy`` do Axios — e verifique junto de um ponto final que reporte o endereço, em vez de partir de suposições.

Nós vendemos proxies e a maioria das solicitações do lado do servidor não necessita de nenhum. Nos casos em que for necessário, saber qual o cliente que está a utilizar é o primeiro passo na depuração, não o último.