Voltar ao blogue
Guias
Mihnea-Octavian ManolacheLast updated on May 12, 202618 min read

Axios Set Headers in 2026: O manual do programador

Axios Set Headers in 2026: O manual do programador
Resumo: O Axios define cabeçalhos em cinco camadas: configuração por pedido, predefinições globais, axios.create() instâncias, interceptores de pedidos e respostas e a própria resposta. Este guia percorre cada camada com trechos de código v1 executáveis e, em seguida, corrige os quatro erros que afetam toda a gente: limites multipart, cookies CORS, certificados autoassinados e maiúsculas/minúsculas nos cabeçalhos.

O Axios continua a ser o cliente HTTP padrão que a maioria das equipas de JavaScript e TypeScript utiliza, e a maioria dos erros que as pessoas relatam não são, de todo, erros do Axios. São erros de cabeçalho. Um argumento de configuração mal colocado elimina silenciosamente o seu Authorization cabeçalho. Um Content-Type: multipart/form-data corrompe todos os uploads. Um axios.defaults vaza para todos os hosts de terceiros que por acaso chamar. Cada um destes tem uma correção simples, assim que souber em que ponto do ciclo de vida da solicitação o cabeçalho deve estar.

Este guia de configuração de cabeçalhos do Axios é o manual que eu gostaria de ter tido ao montar a minha primeira pilha de interceptores. Ele é voltado para o Axios v1 no Node 20+, mas os padrões aplicam-se ao navegador, onde apresentam diferenças. Vais ver cabeçalhos por pedido, predefinições globais, instâncias com âmbito e interceptores de pedido e resposta lado a lado, com uma regra de decisão para escolher entre eles. Também terás uma secção completa sobre cabeçalhos de resposta do Axios que a maioria dos tutoriais ignora, além de um bloco de resolução de problemas para os erros que realmente encontras em produção.

Configurar o Axios v1 no Node.js e no navegador

Antes de qualquer padrão abaixo se comportar da forma que a documentação afirma, fixe a sua versão. Este artigo destina-se ao Axios v1.x no Node 20 ou posterior. A linha 0.x normalizava os cabeçalhos de forma diferente, pelo que os padrões da v1 não se traduzirão todos de forma perfeita.

Instale através de qualquer gestor de pacotes:

npm install axios
# or: yarn add axios   |   pnpm add axios

Projeto ESM:

import axios from "axios";

Serviço CommonJS:

const axios = require("axios");

Página simples do navegador:

<script src="https://cdn.jsdelivr.net/npm/axios@1/dist/axios.min.js"></script>

Um detalhe de ambiente que voltará a ser abordado mais tarde: no Node, o Axios usa a pilha http/https , pelo que controla o TLS, os agentes e os proxies. No navegador, utiliza XMLHttpRequest, pelo que o navegador impõe as regras CORS e SameSite regras, independentemente da sua configuração. Se também precisar de uma camada de proxy, um guia dedicado ao proxy do Axios aborda essa integração de ponta a ponta.

Passe cabeçalhos por pedido com o objeto de configuração

Os cabeçalhos por solicitação são a forma mais direta de definir cabeçalhos no Axios para uma única chamada. São a configuração padrão ideal para autenticação pontual, negociação de conteúdo e depuração isolada. Nada é partilhado entre chamadas, nada vaza para outros módulos, e um cabeçalho definido desta forma prevalece sobre todas as camadas padrão abaixo dele.

// GET with auth and a custom Accept
const orders = await axios.get("https://api.example.com/orders", {
  headers: {
    Authorization: `Bearer ${token}`,
    Accept: "application/vnd.example.v2+json",
  },
});

// POST: body in arg 2, config in arg 3
const created = await axios.post(
  "https://api.example.com/orders",
  { sku: "ABC-123", quantity: 2 },
  { headers: { "Idempotency-Key": crypto.randomUUID() } }
);

// PUT and PATCH follow the same three-argument shape as POST
await axios.put(url, body, { headers: { "If-Match": etag } });
await axios.patch(url, body, {
  headers: { "Content-Type": "application/merge-patch+json" },
});

// DELETE takes config in arg 2, like GET
await axios.delete(url, {
  headers: { Authorization: `Bearer ${token}` },
});

Algumas regras que vale a pena interiorizar. O objeto headers aceita apenas valores de string na v1; matrizes e null não são formatos suportados. Tudo o que definir por pedido é definitivo, mesmo que um interceptor de pedidos tente substituí-lo mais tarde (o padrão guard é mostrado abaixo). E este exemplo de cabeçalhos do Axios é a forma mais simples de fazer com que uma chamada específica ignore tudo o que é global, uma vez que as chaves por pedido prevalecem sobre todas as outras camadas.

A armadilha do slot de argumento: GET/DELETE vs POST/PUT/PATCH

O bug mais comum do Axios relatado por iniciantes não é um bug de cabeçalho, mas sim um bug de slot de argumento. axios.get e axios.delete aceitam a configuração como segundo argumento porque não têm corpo. axios.post, axios.put, e axios.patch aceita a configuração como terceiro argumento porque o corpo está no segundo argumento.

Se errares nisto, os teus cabeçalhos acabam dentro do corpo. O servidor não vê Authorization, retorna um 401 e você passa uma hora a culpar o seu armazenamento de tokens.

// WRONG: headers object treated as the POST body
await axios.post("https://api.example.com/orders", {
  headers: { Authorization: `Bearer ${token}` }, // becomes the request body
});

// RIGHT: empty body, headers in the third slot
await axios.post(
  "https://api.example.com/orders",
  {},                                                // body
  { headers: { Authorization: `Bearer ${token}` } }  // config
);

A maneira mais rápida de confirmar que um 401 se deve a este erro de posicionamento é registar error.config.data e verificar se os teus cabeçalhos vazaram para o corpo. Se isso aconteceu, move-os uma posição para a direita. Este é o erro canónico de cabeçalhos POST do Axios, e desaparece assim que internalizares as regras de posicionamento.

Defina padrões globais para cada pedido

Os cabeçalhos globais do Axios são definidos em axios.defaults.headers e aplicam-se a todas as chamadas feitas através da instância padrão. São a ferramenta certa para um conjunto restrito de casos: um script que comunica com exatamente uma API, uma ferramenta de desenvolvimento interna, uma CLI ou uma pequena aplicação que inclui o seu próprio cliente API. No momento em que chamas mais do que um host, os padrões tornam-se um risco.

// Apply to every method
axios.defaults.headers.common["Accept"] = "application/json";
axios.defaults.headers.common["X-App-Version"] = "2026.04.1";

// Pull secrets from env, never inline
axios.defaults.baseURL = process.env.API_URL;
axios.defaults.headers.common["Authorization"] =
  `Bearer ${process.env.API_TOKEN}`;

O common bucket é o que normalmente se pretende, porque se aplica independentemente do método HTTP. Tudo o que se definir aí aparece em todas as chamadas GET, POST, PUT, PATCH, DELETE e OPTIONS de saída a partir do singleton padrão do Axios.

O custo de manutenção surge mais tarde. Assim que um segundo serviço ou SDK de terceiros passa a fazer parte da mesma base de código, o seu cabeçalho Authorization cabeçalho global viaja para hosts que não tem nada que tocar. A secção de instâncias abaixo é onde esse problema é resolvido corretamente.

Padrões específicos do método (post, get, put)

O Axios também expõe grupos de valores com âmbito de método, como axios.defaults.headers.post, .get, .put, .patch, e .delete. Estes aplicam-se apenas a esse verbo específico, o que por vezes é útil quando se pretende um padrão diferente por método.

// Force a JSON content type only on writes
axios.defaults.headers.post["Content-Type"] = "application/json";
axios.defaults.headers.put["Content-Type"] = "application/json";
axios.defaults.headers.patch["Content-Type"] = "application/json";

Para tudo o resto, opte primeiro por common primeiro e, só depois, restringe-te a um conjunto de métodos quando tiveres um motivo válido. Na prática, os conjuntos de métodos são conhecimento apenas de referência para a maioria das equipas. As instâncias são quase sempre a forma mais clara, e a próxima secção é onde os cabeçalhos padrão do Axios deixam de ser a tua ferramenta principal.

Isolar conjuntos de cabeçalhos por API com instâncias de axios.create()

axios.create() é a recomendação padrão para 2026. Cria-se um pequeno cliente por serviço upstream, define-se os seus próprios baseURL e cabeçalhos, e distribui esse cliente aos módulos que dele necessitam. Cada instância é independente, pelo que a atualização de uma não afeta as outras.

// Internal API: short tokens, custom version header
export const internalApi = axios.create({
  baseURL: "https://internal.example.com/api",
  headers: {
    "Accept": "application/json",
    "X-Internal-Client": "checkout-svc",
  },
});

// Third-party API: completely separate auth and content negotiation
export const partnerApi = axios.create({
  baseURL: "https://partner.example.com",
  headers: {
    "Accept": "application/vnd.partner.v3+json",
    "X-Partner-Key": process.env.PARTNER_KEY,
  },
});

Define-se os cabeçalhos por instância da mesma forma que se definem globais, apenas no objeto da instância:

// After login, write the new token to one instance only
internalApi.defaults.headers.common["Authorization"] = `Bearer ${jwt}`;

Este padrão oferece-lhe duas vantagens. O seu Authorization cabeçalho só é enviado para o host que emitiu o token. E quando troca um upstream por outro, altera apenas um ficheiro de cliente e nada mais. A expressão de cabeçalhos axios.create é o que permite escalar sem riscos.

Por que razão um valor predefinido de Autorização partilhado é um risco de segurança

Quando define axios.defaults.headers.common.Authorization = "Bearer ...", todas as chamadas que passam pelo singleton padrão do Axios enviam esse token, incluindo SDKs de terceiros e scripts ad hoc que importam o módulo axios . Isso inclui hosts que não fazem ideia do que é o seu JWT e podem registá-lo.

O cabeçalho de autorização do Axios deve estar sempre restrito ao host que o emitiu. Dois padrões confiáveis:

// 1. Use a dedicated instance and never touch axios.defaults
internalApi.defaults.headers.common.Authorization = `Bearer ${jwt}`;

// 2. Or guard a request interceptor by baseURL / hostname
axios.interceptors.request.use((cfg) => {
  const host = new URL(cfg.baseURL || cfg.url, "http://x").hostname;
  if (host === "internal.example.com") {
    cfg.headers.Authorization = `Bearer ${jwt}`;
  }
  return cfg;
});

O padrão de interceptor é adequado para monorepos que partilham um axios. O padrão de instância é mais limpo em todos os outros casos.

Injete tokens automaticamente com interceptores de solicitação

Um interceptor de solicitação é a ferramenta de definição de cabeçalhos do Axios que você usa quando o cabeçalho precisa ser calculado no momento da chamada, e não ao carregar o módulo. Ele é executado em todas as solicitações de saída antes que elas saiam do Axios. É aí que o padrão de interceptor de solicitação do Axios ganha seu lugar: leia o token atual de onde quer que ele esteja, anexe-o a config.headers, e devolve a configuração modificada.

Dois tipos de armazenamento cobrem a maioria das aplicações. No navegador, costuma-se ler a partir de localStorage, sessionStorageou da memória. No Node, mantém-se um pequeno módulo de armazenamento de tokens com o qual o resto da aplicação comunica.

// Browser: read the latest token on every request
internalApi.interceptors.request.use((config) => {
  const token = localStorage.getItem("access_token");
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});
// Node: module-level store, swap-able for Redis or a vault
import { getToken } from "./auth/token-store.js";

internalApi.interceptors.request.use(async (config) => {
  const token = await getToken();
  if (token && !config.headers.Authorization) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config;
});

Essa if (!config.headers.Authorization) proteção é importante. É também o padrão que permite que uma substituição por pedido prevaleça sobre o interceptor quando necessário, o que a secção sobre a ordem de fusão aborda em detalhe.

Os interceptores também lidam com lógica condicional que as camadas por pedido e padrão não conseguem expressar de forma clara. Cabeçalhos baseados em funções, alternâncias de ambiente e comportamento sensível a URLs pertencem todos aqui:

internalApi.interceptors.request.use((config) => {
  const user = getCurrentUser();
  if (user?.role === "admin") {
    config.headers["X-Admin"] = "true";
  }
  if (config.url?.startsWith("/billing/")) {
    config.headers["X-Sensitive-Path"] = "1";
  }
  if (process.env.NODE_ENV === "development") {
    config.headers["X-Debug-Trace"] = crypto.randomUUID();
  }
  return config;
});

Mantenha um interceptor por preocupação sempre que possível. Misturar autenticação, sinalizadores de função e observabilidade numa única função torna a depuração difícil, e cada interceptor registado só é executado na ordem de registo de qualquer forma.

Atualize tokens expirados em 401 com um interceptor de resposta

A atualização de tokens é onde a maioria das bases de código do Axios apresenta pequenos erros: loops de tentativas infinitas, condições de corrida entre pedidos paralelos e chamadas de atualização que são reescritas pelo próprio interceptor que deveria atualizá-las. O padrão abaixo evita todos os três.

A estrutura é um interceptor de resposta que capta um 401, chama um endpoint de atualização com um cliente Axios separado, marca a configuração original para que não possa tentar indefinidamente, tenta uma vez e desiste para fazer logout em caso de falha.

import axios from "axios";

// 1. Plain client for refresh, with NO interceptors of its own.
//    This is what keeps the refresh call out of the retry loop.
const authClient = axios.create({ baseURL: "https://auth.example.com" });

// 2. Your normal API client with auth wiring.
const api = axios.create({ baseURL: "https://api.example.com" });

api.interceptors.request.use((cfg) => {
  const t = tokenStore.access;
  if (t) cfg.headers.Authorization = `Bearer ${t}`;
  return cfg;
});

api.interceptors.response.use(
  (res) => res,
  async (error) => {
    const original = error.config;
    if (
      error.response?.status !== 401 ||
      original._retry ||
      !tokenStore.refresh
    ) {
      // Either not an auth failure, already retried once,
      // or we have nothing to refresh with.
      return Promise.reject(error);
    }
    original._retry = true; // 3. one shot only, no loops
    try {
      const { data } = await authClient.post("/refresh", {
        refresh_token: tokenStore.refresh,
      });
      tokenStore.access = data.access;
      tokenStore.refresh = data.refresh;
      // 4. write the new token onto the original request and replay it
      original.headers.Authorization = `Bearer ${data.access}`;
      return api(original);
    } catch (refreshErr) {
      tokenStore.clear();
      window.location.href = "/login"; // or your auth flow
      return Promise.reject(refreshErr);
    }
  }
);

Algumas notas de produção antes de isto chegar ao tráfego real. Partilhe o armazenamento de tokens entre separadores (um BroadcastChannel listener funciona nos navegadores) para que uma atualização numa aba não bloqueie outra. Envolva a atualização em andamento num singleton Promise para que dez erros 401 paralelos acionem uma atualização, e não dez. E limite as tentativas além _retry se o ponto final de atualização puder ele próprio devolver 401; caso contrário, entrará num ciclo com uma sessão revogada.

Leia os cabeçalhos de resposta: limites de taxa, ETag e paginação

A maioria dos guias de configuração de cabeçalhos do Axios fica pelo lado da solicitação e nunca analisa o que é devolvido. Isso é um erro. O objeto de cabeçalhos de resposta do Axios é onde a API indica como agir a seguir: quantas solicitações restam, se a sua cópia em cache ainda está válida e onde se encontra a próxima página. Ignore isso e o seu scraper parecerá educado no primeiro dia, mas será limitado no terceiro.

O Axios expõe os cabeçalhos de resposta em response.headers. As chaves são em minúsculas, independentemente de como o servidor as escreveu na rede. Essa é a surpresa mais comum quando se começa a lê-las. O guia de Pedidos Condicionais HTTP da MDN aborda a especificação para ETag e If-None-Match.

const res = await api.get("/orders");

// All read as lowercase keys, regardless of server casing
const limit = Number(res.headers["x-ratelimit-limit"]);
const remaining = Number(res.headers["x-ratelimit-remaining"]);
const resetAt = new Date(Number(res.headers["x-ratelimit-reset"]) * 1000);

console.log(`API budget: ${remaining}/${limit}, resets at ${resetAt.toISOString()}`);

Para um polling compatível com o cache, armazene o ETag e reproduza-a via If-None-Match. Se o recurso não tiver mudado, o servidor retorna 304 com um corpo vazio e o seu código salta a análise:

let cachedEtag = null;
let cachedBody = null;

async function pollOrders() {
  try {
    const res = await api.get("/orders", {
      headers: cachedEtag ? { "If-None-Match": cachedEtag } : {},
      validateStatus: (s) => s === 200 || s === 304, // 304 is not an error
    });
    if (res.status === 200) {
      cachedEtag = res.headers["etag"];
      cachedBody = res.data;
    }
    return cachedBody;
  } catch (err) {
    /* network/HTTP errors only land here now */
  }
}

As APIs paginadas utilizam frequentemente o Link (RFC 8288) com rel="next" e rel="prev". Percorra-o manualmente ou utilize um analisador:

function nextLink(linkHeader) {
  if (!linkHeader) return null;
  const match = linkHeader.split(",").find((p) => /rel="next"/.test(p));
  return match ? match.match(/<([^>]+)>/)[1] : null;
}

let url = "/orders?per_page=100";
while (url) {
  const res = await api.get(url);
  process(res.data);
  url = nextLink(res.headers["link"]);
}

Cabeçalhos que vale a pena monitorizar na maioria das APIs:

Cabeçalho

O que indica

x-ratelimit-remaining, x-ratelimit-reset

Quão perto está de um 429 e quando o bucket se reabastece

retry-after

Segundos ou data HTTP a aguardar após um 429 ou 503

etag, last-modified

Validadores de cache para GETs condicionais

link

Cursores de paginação de acordo com a RFC 8288

content-type

Se o corpo é JSON, XML, NDJSON ou HTML

Se o teu código apenas inspeciona response.data, está a desperdiçar metade do que a API está a tentar dizer-lhe.

Como o Axios mescla cabeçalhos: regras de precedência em 2026

Sempre que define cabeçalhos do Axios a partir de mais do que uma camada, a biblioteca tem de os fundir. Os cabeçalhos são calculados no momento do pedido, percorrendo cinco camadas e aplicando o princípio «o último a escrever prevalece». Saber a ordem é o que lhe permite prever qual o cabeçalho que o seu servidor realmente vê.

A ordem de fusão, da prioridade mais baixa à mais alta:

  1. Padrões da biblioteca. Valores integrados do Axios como Accept: application/json, text/plain, */* e o Content-Type para pedidos de gravação.
  2. Padrões globais. Qualquer coisa que coloques em axios.defaults.headers.common, .post, .gete similares.
  3. Padrões de instância. Cabeçalhos definidos num cliente criado com axios.create({ headers: ... }) ou atribuídos instance.defaults.headers.* posteriormente.
  4. Configuração por pedido. O headers objeto que passa diretamente para axios.get(url, { headers }), axios.post(url, body, { headers }), e assim por diante.
  5. Interceptores de solicitação. Qualquer coisa que um interceptor escreva em config.headers antes de a solicitação sair do Axios. Estes são executados após a fusão por solicitação.

Como os interceptores são executados por último, tecnicamente eles têm prioridade sobre os cabeçalhos por solicitação. Isso confunde quase toda a gente na primeira vez. A solução é uma condição de verificação dentro do interceptor que respeite um valor existente:

api.interceptors.request.use((config) => {
  // Only inject if the caller has not already set Authorization
  if (!config.headers.Authorization) {
    const t = tokenStore.access;
    if (t) config.headers.Authorization = `Bearer ${t}`;
  }
  return config;
});

Com essa condição de segurança implementada, um Authorization sobrevive à pilha de interceptores e a sua substituição comporta-se de forma intuitiva. Este é o mesmo padrão que permite que uma chamada específica utilize um token de serviço para serviço, enquanto o resto da aplicação utiliza um token de utilizador.

Corrija os erros de cabeçalho mais comuns do Axios

A maioria dos problemas de cabeçalhos em produção resume-se a quatro padrões: um limite multipart removido em uploads, uma incompatibilidade de CORS ou withCredentials incompatibilidade no navegador, um certificado TLS autoassinado no Node e backends sensíveis a maiúsculas e minúsculas que rejeitam o formato de transmissão que o Axios envia. As quatro subsecções abaixo foram escritas para que possa aceder a qualquer uma delas diretamente a partir da pesquisa e aplicar a correção sem ter de voltar atrás.

Uploads multipart/form-data com falha (a armadilha do limite)

O bug mais comum do Axios FormData Content-Type é a «correção» que as pessoas aplicam por instinto: definir Content-Type: multipart/form-data por conta própria. Esse valor por si só é incompleto, porque corpos multipart reais requerem um boundary parâmetro que o servidor usa para separar campos. Quando codifica o valor simples, o Axios não o sobrescreve, o delimitador real nunca chega à rede e o servidor rejeita o upload.

O passo certo é deixar que o tempo de execução construa o cabeçalho por si.

// Node: form-data library exposes getHeaders() with the boundary baked in
import FormData from "form-data";
import fs from "node:fs";

const form = new FormData();
form.append("file", fs.createReadStream("./invoice.pdf"));
form.append("note", "Q4 invoice");

await api.post("/uploads", form, {
  headers: form.getHeaders(), // multipart/form-data; boundary=...
});
// Browser: send a real FormData and let Axios omit Content-Type
const fd = new FormData();
fd.append("file", fileInput.files[0]);
fd.append("note", "Q4 invoice");

await api.post("/uploads", fd); // do not set Content-Type

Uma exceção: se passar um objeto simples ao Axios e permitir que ele o serialize para FormData internamente, um Content-Type: multipart/form-data é aceitável, porque o Axios preencherá o delimitador por si próprio.

Bloqueios CORS, withCredentials e cookies em falta

O CORS é exclusivo do navegador. O Node não tem CORS, nem cabeçalhos bloqueados, nem pré-verificação, pelo que toda esta secção é algo que só se depura numa guia do navegador. Os cabeçalhos CORS do Axios não podem ser desativados a partir do cliente; o navegador detém o controlo e o Axios está a jusante dele. A referência canónica para o que o navegador impõe é o guia CORS da MDN.

Para que os cookies de origem cruzada sejam transmitidos, quatro coisas têm de estar alinhadas:

  1. O cliente define os cookies withCredentials do Axios como ativados. Ou instance.defaults.withCredentials = true, ou { withCredentials: true } por pedido.
  2. O servidor retorna Access-Control-Allow-Credentials: true.
  3. Access-Control-Allow-Origin uma origem específica, nunca *. O curinga é rejeitado assim que as credenciais entram em jogo.
  4. Os cookies são emitidos com SameSite=None; Secure. Um SameSite=Strict cookie nunca será enviado entre sites, mesmo com withCredentials set.
const api = axios.create({
  baseURL: "https://api.example.com",
  withCredentials: true, // tells the BROWSER to attach cookies
});

Se não for o proprietário da API upstream e não puder corrigir a resposta CORS, a única solução honesta é um pequeno proxy do lado do servidor no seu próprio domínio que encaminhe a chamada. Colocá-lo atrás do seu próprio subdomínio também contorna a questão da descontinuação dos cookies de terceiros. Vale a pena manter nos favoritos um guia introdutório sobre o comportamento subjacente dos cookies.

Certificados HTTPS autoassinados no Node.js

No Node, tem controlo total sobre o TLS, pelo que pode comunicar com uma API de desenvolvimento que utilize um certificado autoassinado sem causar problemas no tempo de execução. Num navegador, não pode fazê-lo e não deve tentar; o utilizador deve confiar na CA no sistema operativo ou na loja do navegador.

Apenas para desenvolvimento ou staging no lado do Node, anexe um agente HTTPS personalizado. A documentação do Node.js sobre o `https.Agent` abrange todas as opções:

import https from "node:https";

const devApi = axios.create({
  baseURL: "https://dev.internal.local",
  httpsAgent: new https.Agent({ rejectUnauthorized: false }),
});

Esse sinalizador desativa a verificação de certificados, o que significa que os ataques man-in-the-middle deixam de ser detetáveis. Nunca envie isto para produção. A correção para produção consiste em colocar a sua CA no armazenamento de confiança do sistema ou emitir um certificado real (Let's Encrypt, um servidor ACME interno ou o gestor de certificados do seu fornecedor de nuvem). rejectUnauthorized: false é uma ferramenta para o ciclo de desenvolvimento, não uma estratégia de implementação.

Maiúsculas e minúsculas nos cabeçalhos em backends legados exigentes

O HTTP não distingue maiúsculas de minúsculas em teoria, mas um número não negligenciável de backends legados recusará um pedido cujos nomes de cabeçalho não estejam na forma canónica de maiúsculas e minúsculas. O Axios normaliza internamente alguns nomes de cabeçalho, mas para cabeçalhos personalizados deve enviar a forma de escrita que o upstream espera.

// Safer than x-api-key on older middleware
await api.get("/secret", {
  headers: { "X-API-Key": process.env.API_KEY },
});

O reverso da moeda: quando lês esses mesmos cabeçalhos de volta do response.headers, o Axios converte todas as chaves para minúsculas. Assim, você envia X-API-Key mas lê res.headers["x-api-key"]. Esta assimetria é intencional e consistente em toda a v1. Escolha o formato canónico para saídas, aceite minúsculas para entradas e nunca mais terá de depurar um «cabeçalho em falta».

Envie cabeçalhos semelhantes aos de um navegador para web scraping com o Axios

Os servidores web inspecionam os cabeçalhos de solicitação para decidir se o cliente é um navegador real ou um bot, e um agente de usuário Node padrão como axios/1.7.7 é a forma mais rápida de ser sinalizado. Se estiver a usar o Axios para scraping, envie um conjunto de cabeçalhos credível e alterne-o.

const UA_POOL = [
  "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
  "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15",
  "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
];

const scraper = axios.create({
  headers: {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Upgrade-Insecure-Requests": "1",
  },
  timeout: 15_000,
});

// Axios User-Agent rotation per request
scraper.interceptors.request.use((cfg) => {
  cfg.headers["User-Agent"] = UA_POOL[Math.floor(Math.random() * UA_POOL.length)];
  return cfg;
});

Isto permite-lhe ultrapassar filtros de bots ingênuos. Alvos sofisticados sobrepõem impressões digitais JA3, perfis TLS, desafios do Cloudflare e verificações comportamentais, e nenhum pacote de cabeçalhos por si só consegue contornar isso. Quando axios a rotação deixar de ser suficiente, recorra a um conjunto de proxies residenciais ou a uma API de scraping gerida que trate de impressões digitais, novas tentativas e fluxos de trabalho CAPTCHA por si. Uma análise detalhada das razões pelas quais os scrapers são bloqueados para além dos cabeçalhos é uma próxima leitura útil.

Principais conclusões para os cabeçalhos definidos pelo Axios em 2026

Todo o modelo de definição de cabeçalhos da Axios resume-se a uma imagem mental de cinco camadas, mais uma regra de ordenação:

  • Configuração por pedido para casos pontuais e substituições; prevalece sobre todos os padrões abaixo.
  • Padrões globais apenas para scripts de API única e ferramentas de desenvolvimento; arriscado quando se chamam vários hosts.
  • axios.create() Instâncias como padrão de 2026 para qualquer aplicação que comunique com mais de um upstream.
  • Interceptores de pedidos para questões transversais, como injeção de autenticação, sinalizadores de função e rastreamento.
  • Inspeção de respostas para que response.headers influa efetivamente a sua lógica de repetição, cache e paginação.

Ordem de fusão, de baixo para alto: predefinições da biblioteca, predefinições globais, predefinições de instância, configuração por pedido, interceptores de pedido. Use o if (!config.headers.x) guard dentro dos interceptores quando quiser que a configuração por pedido mantenha a sua prioridade.

Perguntas frequentes

Qual é a diferença entre axios.defaults.headers.common e axios.defaults.headers.post?

common aplica-se a todos os métodos HTTP na instância padrão do Axios, pelo que os cabeçalhos definidos aí são incluídos em GET, POST, PUT, PATCH e DELETE. post (e .get, .put, .patch, .delete) aplica-se apenas quando esse verbo específico é utilizado. Recorra a common primeiro; use os grupos de métodos apenas quando um verbo precisar realmente de um padrão diferente.

Como faço para que um cabeçalho por solicitação tenha prioridade sobre um interceptor de solicitação no Axios?

Proteja o interceptor para que ele só escreva um cabeçalho quando o chamador ainda não tiver definido um. O padrão é if (!config.headers.Authorization) { config.headers.Authorization = ... }. Como os interceptores são executados após a fusão por solicitação, uma atribuição incondicional anulará a sua substituição. A versão protegida respeita o que quer que o chamador tenha passado.

Por que é que o Axios coloca os nomes dos cabeçalhos em minúsculas quando os leio em response.headers?

O Axios normaliza as chaves dos cabeçalhos de resposta para minúsculas por convenção. O próprio HTTP trata os nomes dos cabeçalhos como insensíveis a maiúsculas e minúsculas, e colocar em minúsculas no caminho de leitura significa que nunca terá de adivinhar as maiúsculas e minúsculas para etag, content-type, ou x-ratelimit-remaining. Envie a grafia canónica na saída, leia em minúsculas na entrada.

O Axios pode contornar o CORS ao chamar uma API de terceiros a partir do navegador?

Não. O CORS é aplicado pelo navegador antes mesmo do Axios ser executado, por isso não existe nenhuma opção do lado do cliente que o desative. As únicas soluções reais são fazer com que o servidor de origem envie o Access-Control-Allow-Origin e Access-Control-Allow-Credentials , ou encaminhar a chamada através de um pequeno proxy do lado do servidor que você controla. O Node não tem regras CORS de todo.

Como posso enviar um token Bearer apenas para um baseURL específico sem o divulgar a outros hosts?

Crie uma instância dedicada axios.create() para essa API e defina o seu Authorization apenas na instância. Nunca escreva o token em axios.defaults, o que o transmite para todos os hosts que o singleton padrão chama. Se tiver de usar uma instância partilhada, proteja um interceptor de pedidos com uma verificação do nome do host para que o cabeçalho só seja anexado quando a URL corresponder à sua baseURL de confiança.

Conclusão

Se tiver de reter apenas uma coisa deste guia sobre a definição de cabeçalhos no Axios, que seja a estrutura em camadas: cada cabeçalho fica num de cinco locais, e a ordem é: predefinições da biblioteca, predefinições globais, predefinições da instância, configuração por pedido e, por fim, interceptores de pedido. Escolha a camada mais alta que corresponda ao tempo de vida do cabeçalho. As substituições pontuais vão por pedido. As questões que afetam toda a aplicação vão para uma instância. A autenticação transversal vai para um interceptor. E todas as respostas do Axios transportam cabeçalhos que devem influenciar a sua próxima decisão, não ser descartados.

Os mesmos padrões aplicam-se quando se faz mais do que chamar APIs REST bem comportadas. No momento em que se direciona o Axios para um alvo que identifica clientes, impõe limites de taxa de forma agressiva ou oculta dados por trás de desafios JavaScript, a rotação de cabeçalhos por si só deixa de ser suficiente. É aí que uma camada gerida se torna a jogada de maior impacto: a API WebScrapingAPI Scraper lida com a rotação de proxies, impressões digitais TLS ao nível do navegador e resolução de CAPTCHA por trás de um único ponto de extremidade, para que o código Axios que acabou de escrever mantenha a sua forma e deixe de ter de lidar com blocos de emergência. Marque isto como a sua referência de definição de cabeçalhos do Axios e opte pelo caminho gerido quando a camada de pedidos já não for o problema interessante.

Sobre o autor
Mihnea-Octavian Manolache, Desenvolvedor Full Stack @ WebScrapingAPI
Mihnea-Octavian ManolacheDesenvolvedor Full Stack

Mihnea-Octavian Manolache é engenheiro Full Stack e DevOps na WebScrapingAPI, onde desenvolve funcionalidades do produto e mantém a infraestrutura que garante o bom funcionamento da plataforma.

Comece a construir

Pronto para expandir a sua recolha de dados?

Junte-se a mais de 2.000 empresas que utilizam a WebScrapingAPI para extrair dados da Web à escala empresarial, sem quaisquer custos de infraestrutura.