Zurück zum Blog
Anleitungen
Mihnea-Octavian ManolacheLast updated on May 12, 202615 min read

Axios setzt Header im Jahr 2026: Das Entwickler Playbook

Axios setzt Header im Jahr 2026: Das Entwickler Playbook
Kurz gesagt: Axios setzt Header auf fünf Ebenen: pro Anfrage, globale Standardeinstellungen, axios.create() Instanzen, Request- und Response-Interceptors sowie die Antwort selbst. Dieser Leitfaden führt durch jede Ebene mit lauffähigen v1-Snippets und behebt anschließend die vier Fehler, die jedem zu schaffen machen: Multipart-Grenzen, CORS-Cookies, selbstsignierte Zertifikate und die Groß-/Kleinschreibung von Headern.

Axios ist nach wie vor der Standard-HTTP-Client, auf den die meisten JavaScript- und TypeScript-Teams zurückgreifen, und die meisten Fehler, die Nutzer melden, sind gar keine Axios-Fehler. Es sind Header-Fehler. Ein falsch platziertes Konfigurationsargument lässt deinen Authorization Header. Ein manuell eingegebener Content-Type: multipart/form-data beschädigt jeden Upload. Ein globales axios.defaults Token wird an jeden Drittanbieter-Host weitergegeben, den du aufrufst. Für jeden dieser Fälle gibt es eine saubere Lösung, sobald du weißt, an welcher Stelle im Lebenszyklus der Anfrage der Header stehen sollte.

Dieser Axios-Leitfaden zum Setzen von Headern ist das Handbuch, das ich mir gewünscht hätte, als ich meinen ersten Interceptor-Stack aufbaute. Er zielt auf Axios v1 unter Node 20+ ab, aber die Muster gelten auch für den Browser, wo sie sich unterscheiden. Sie werden Headers pro Anfrage, globale Standardwerte, instanzgebundene Instanzen sowie Anfrage- und Antwort-Interceptors nebeneinander sehen, zusammen mit einer Entscheidungsregel für die Wahl zwischen ihnen. Außerdem erhalten Sie einen vollständigen Abschnitt zu Axios-Antwort-Headern, den die meisten Tutorials auslassen, sowie einen Abschnitt zur Fehlerbehebung für die Probleme, auf die Sie in der Produktion tatsächlich stoßen.

Axios v1 in Node.js und im Browser einrichten

Bevor sich eines der folgenden Muster so verhält, wie es in der Dokumentation beschrieben wird, sollten Sie Ihre Version festlegen. Dieser Artikel zielt auf Axios v1.x unter Node 20 oder höher ab. Die 0.x-Reihe normalisierte Header anders, sodass sich die v1-Muster nicht alle nahtlos übertragen lassen.

Installieren Sie es über einen beliebigen Paketmanager:

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

ESM-Projekt:

import axios from "axios";

CommonJS-Dienst:

const axios = require("axios");

Einfache Browserseite:

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

Ein Umgebungsdetail, auf das später noch eingegangen wird: In Node nutzt Axios den integrierten http/https Stack, sodass du TLS, Agenten und Proxys kontrollieren kannst. Im Browser verwendet es XMLHttpRequest, sodass der Browser CORS und SameSite unabhängig von Ihrer Konfiguration durch. Wenn Sie zudem eine Proxy-Ebene benötigen, behandelt ein spezieller Axios-Proxy-Leitfaden diese Verkabelung von Anfang bis Ende.

Header pro Anfrage mit dem Konfigurationsobjekt übergeben

Header pro Anfrage sind der direkteste Weg, um in Axios Header für einen einzelnen Aufruf festzulegen. Sie sind die richtige Standardeinstellung für einmalige Authentifizierung, Content-Negotiation und isoliertes Debugging. Nichts wird zwischen Aufrufen geteilt, nichts gelangt in andere Module, und ein auf diese Weise festgelegter Header hat Vorrang vor jeder darunterliegenden Standardschicht.

// 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}` },
});

Ein paar Regeln, die es sich zu verinnerlichen lohnt. Das headers-Objekt akzeptiert in v1 nur String-Werte; Arrays und null werden nicht unterstützt. Alles, was Sie pro Anfrage festlegen, ist endgültig, selbst wenn ein Request-Interceptor später versucht, es zu überschreiben (das Guard-Muster wird unten gezeigt). Und dieses Axios-Header-Beispiel ist der sauberste Weg, um einen bestimmten Aufruf alles Globale ignorieren zu lassen, da Schlüssel pro Anfrage jede andere Ebene übertrumpfen.

Die Argument-Slot-Falle: GET/DELETE vs. POST/PUT/PATCH

Der häufigste von Anfängern gemeldete Axios-Fehler ist gar kein Header-Fehler, sondern ein Argument-Slot-Fehler. axios.get und axios.delete akzeptieren Konfigurationen als zweites Argument, da sie keinen Body haben. axios.post, axios.put, und axios.patch akzeptieren die Konfiguration als drittes Argument, da sich der Body in Argument zwei befindet.

Wenn du das falsch machst, landen deine Header im Body. Der Server sieht keine Authorization, gibt 401 zurück, und du verbringst eine Stunde damit, deinem Token-Speicher die Schuld zu geben.

// 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
);

Der schnellste Weg, um zu bestätigen, dass ein 401 auf diese Fehlplatzierung zurückzuführen ist, besteht darin, error.config.data und zu prüfen, ob deine Header in den Body gelangt sind. Wenn ja, verschiebe sie um eine Position nach rechts. Dies ist der klassische Axios-Header-POST-Fehler, und er verschwindet, sobald du die Slot-Regeln verinnerlicht hast.

Lege globale Standardwerte für jede Anfrage fest

Globale Axios-Header werden auf axios.defaults.headers und gelten für jeden Aufruf, der über die Standardinstanz erfolgt. Sie sind das richtige Werkzeug für eine begrenzte Anzahl von Fällen: ein Skript, das mit genau einer API kommuniziert, ein internes Entwicklertool, eine CLI oder eine kleine App, die ihren eigenen API-Client mitliefert. Sobald du mehr als einen Host aufrufst, werden Standardwerte zum Problem.

// 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}`;

Der common Bucket ist das, was du normalerweise willst, da es unabhängig von der HTTP-Methode gilt. Alles, was du dort festlegst, erscheint bei jedem ausgehenden GET-, POST-, PUT-, PATCH-, DELETE- und OPTIONS-Aufruf vom Standard-Axios-Singleton.

Die Wartungskosten zeigen sich später. Sobald ein zweiter Dienst oder ein SDK eines Drittanbieters in derselben Codebasis vorhanden ist, wandert dein globaler Authorization Header zu Hosts, die er gar nicht betreffen sollte. Im Abschnitt „Instanzen“ weiter unten wird dieses Problem ordnungsgemäß behoben.

Methodenspezifische Standardwerte (post, get, put)

Axios stellt auch methodenspezifische Buckets wie axios.defaults.headers.post, .get, .put, .patchund .delete. Diese gelten nur für das jeweilige Verb, was gelegentlich nützlich ist, wenn du für jede Methode einen anderen Standardwert festlegen möchtest.

// 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";

Für alles andere greifen Sie zunächst auf common zuerst darauf zurück, und schränke dich nur dann auf einen Methoden-Bucket ein, wenn du einen triftigen Grund dafür hast. In der Praxis sind die Methoden-Buckets für die meisten Teams reines Referenzwissen. Instanzen sind fast immer die übersichtlichere Form, und im nächsten Abschnitt hören die Axios-Standard-Header auf, dein primäres Werkzeug zu sein.

Isolieren Sie Header-Sätze pro API mit axios.create()-Instanzen

axios.create() ist die Standardempfehlung für 2026. Du erstellst einen kleinen Client pro Upstream-Dienst, legst dessen eigene baseURL und Header fest und stellen diesen Client den Modulen zur Verfügung, die ihn benötigen. Jede Instanz ist unabhängig, sodass die Aktualisierung einer Instanz keine Auswirkungen auf eine andere hat.

// 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,
  },
});

Sie legen Header pro Instanz genauso fest wie globale Header, nur auf dem Instanzobjekt:

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

Dieses Muster bietet Ihnen zwei Vorteile. Ihr Authorization Header wird immer nur an den Host gesendet, der das Token ausgestellt hat. Und wenn Sie einen Upstream gegen einen anderen austauschen, ändern Sie nur eine Client-Datei und sonst nichts. Das axios.create-Header-Muster ist das, was ohne Tücken skaliert.

Warum ein gemeinsamer Standardwert für „Authorization“ ein Sicherheitsrisiko darstellt

Wenn du axios.defaults.headers.common.Authorization = "Bearer ...", sendet jeder Aufruf, der über das standardmäßige Axios-Singleton läuft, dieses Token – einschließlich SDKs von Drittanbietern und Ad-hoc-Skripten, die das reine axios Modul importieren. Dazu gehören auch Hosts, die keine Ahnung haben, was Ihr JWT ist, und es möglicherweise protokollieren.

Der Axios-Authorization-Header sollte immer auf den Host beschränkt sein, der ihn ausgestellt hat. Zwei zuverlässige Muster:

// 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;
});

Das Interceptor-Muster eignet sich gut für Monorepos, die ein einziges axios. Das Instanzmuster ist in allen anderen Fällen sauberer.

Token automatisch mit Request-Interceptors einfügen

Ein Request-Interceptor ist das Axios-Tool zum Setzen von Headern, auf das Sie zurückgreifen, wenn der Header zum Zeitpunkt des Aufrufs und nicht beim Laden des Moduls berechnet werden muss. Er wird bei jeder ausgehenden Anfrage ausgeführt, bevor diese Axios verlässt. Hier kommt das Axios-Request-Interceptor-Muster zum Tragen: Lesen Sie das aktuelle Token von seinem Speicherort, fügen Sie es config.headers, die geänderte Konfiguration zurückgeben.

Zwei Speicherarten decken die meisten Anwendungen ab. Im Browser liest man normalerweise aus localStorage, sessionStorageoder dem Arbeitsspeicher. In Node verwaltet man ein kleines Token-Speichermodul, mit dem der Rest der App kommuniziert.

// 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;
});

Diese if (!config.headers.Authorization) Wächter ist wichtig. Es ist auch das Muster, das es ermöglicht, dass eine Übersteuerung pro Anfrage bei Bedarf gegenüber dem Interceptor Vorrang hat, was im Abschnitt zur Merge-Reihenfolge ausführlich behandelt wird.

Interceptors verarbeiten auch bedingte Logik, die die Ebenen „pro Anfrage“ und „Standardwerte“ nicht sauber ausdrücken können. Rollenbasierte Header, Umgebungsschalter und URL-abhängiges Verhalten gehören alle hierher:

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;
});

Verwende nach Möglichkeit einen Interceptor pro Thema. Das Vermischen von Authentifizierung, Rollenflags und Observability in einer einzigen Funktion erschwert das Debuggen, und jeder registrierte Interceptor wird ohnehin nur in der Reihenfolge seiner Registrierung ausgeführt.

Aktualisieren Sie abgelaufene Token bei 401 mit einem Response-Interceptor

Bei der Token-Aktualisierung treten in den meisten Axios-Codebasen subtile Fehler auf: endlose Wiederholungsschleifen, Race-Conditions bei parallelen Anfragen und Aktualisierungsaufrufe, die von genau dem Interceptor umgeschrieben werden, der sie eigentlich aktualisieren soll. Das folgende Muster vermeidet alle drei Probleme.

Es handelt sich um einen Response-Interceptor, der einen 401-Fehler abfängt, einen Aktualisierungs-Endpunkt mit einem separaten Axios-Client aufruft, die ursprüngliche Konfiguration so markiert, dass sie nicht endlos wiederholt wird, einen einzigen Wiederholungsversuch unternimmt und bei Fehlschlag die Abmeldung auslöst.

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);
    }
  }
);

Ein paar Hinweise zur Produktion, bevor dies im Echtbetrieb zum Einsatz kommt: Teilen Sie den Token-Speicher zwischen den Tabs (ein BroadcastChannel Listener funktioniert in Browsern), damit eine Aktualisierung in einem Tab einen anderen nicht blockiert. Verpacken Sie die laufende Aktualisierung in ein Promise-Singleton, damit zehn parallele 401-Fehler eine Aktualisierung auslösen, nicht zehn. Und begrenzen Sie die Wiederholungsversuche _retry , wenn der Aktualisierungsendpunkt selbst einen 401-Fehler zurückgeben kann; andernfalls gerät man bei einer widerrufenen Sitzung in eine Endlosschleife.

Antwort-Header lesen: Ratenbegrenzungen, ETag und Paginierung

Die meisten Anleitungen zum Setzen von Headern mit Axios beschränken sich auf die Anfrageseite und berücksichtigen nie, was zurückkommt. Das ist ein Fehler. Das Axios-Objekt für Antwort-Header ist der Ort, an dem die API dir mitteilt, wie du dich als Nächstes verhalten sollst: wie viele Anfragen du noch hast, ob deine zwischengespeicherte Kopie noch gültig ist und wo sich die nächste Seite befindet. Überspringe das, und dein Scraper wirkt am ersten Tag höflich und wird am dritten Tag gedrosselt.

Axios stellt Antwort-Header unter response.headers. Die Schlüssel werden in Kleinbuchstaben geschrieben, unabhängig davon, wie der Server sie in der Übertragung geschrieben hat. Das ist die häufigste Überraschung, wenn man anfängt, sie zu lesen. Der MDN-Leitfaden zu bedingten HTTP-Anfragen behandelt die Spezifikation für ETag und 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()}`);

Für cachefreundliches Polling speicherst du die ETag und spiele sie über If-None-Match. Wenn sich die Ressource nicht geändert hat, gibt der Server 304 mit einem leeren Body zurück und dein Code überspringt die Analyse:

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 */
  }
}

Paginierte APIs verwenden häufig den Link Header (RFC 8288) mit rel="next" und rel="prev". Durchlaufen Sie ihn manuell oder verwenden Sie einen Parser:

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"]);
}

Header, die bei den meisten APIs überwacht werden sollten:

Header

Was er Ihnen sagt

x-ratelimit-remaining, x-ratelimit-reset

Wie nah Sie an einem 429-Fehler sind und wann sich der Bucket wieder auffüllt

retry-after

Sekunden oder HTTP-Datum, das nach einem 429- oder 503-Fehler abgewartet werden muss

etag, last-modified

Cache-Validatoren für bedingte GET-Anfragen

link

Paginierungscursor gemäß RFC 8288

content-type

Ob der Body JSON, XML, NDJSON oder HTML ist

Wenn dein Code nur response.data, verpasst du die Hälfte dessen, was die API dir mitteilen will.

Wie Axios Header zusammenführt: Prioritätsregeln im Jahr 2026

Jedes Mal, wenn du in Axios Header aus mehr als einer Ebene setzt, muss die Bibliothek diese zusammenführen. Header werden zum Zeitpunkt der Anfrage berechnet, indem fünf Ebenen durchlaufen werden und das Prinzip „Last-Write-Wins“ angewendet wird. Die Kenntnis der Reihenfolge ermöglicht es dir, vorherzusagen, welchen Header dein Server tatsächlich sieht.

Die Zusammenführungsreihenfolge, von der niedrigsten bis zur höchsten Priorität:

  1. Bibliotheksstandardwerte. Integrierte Axios-Werte wie Accept: application/json, text/plain, */* und der methodenabhängige Content-Type für Schreibanfragen.
  2. Globale Standardwerte. Alles, was du in axios.defaults.headers.common, .post, .getund Ähnliches.
  3. Instanz-Standardwerte. Header, die auf einem mit axios.create({ headers: ... }) oder instance.defaults.headers.* .
  4. Konfiguration pro Anfrage. Das headers Objekt, das Sie direkt an axios.get(url, { headers }), axios.post(url, body, { headers }), und so weiter.
  5. Anfrage-Interceptors. Alles, was ein Interceptor in config.headers , bevor die Anfrage Axios verlässt. Diese werden nach der anfragebezogenen Zusammenführung ausgeführt.

Da Interceptors als Letzte ausgeführt werden, kommen sie technisch gesehen vor den anfragebezogenen Headern. Das bringt fast jeden beim ersten Mal aus der Bahn. Die Lösung ist eine Guard-Anweisung innerhalb des Interceptors, die einen vorhandenen Wert berücksichtigt:

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;
});

Mit dieser Schutzklausel überlebt ein anforderungsspezifischer Authorization den Interceptor-Stack und Ihre Überschreibung verhält sich intuitiv. Dies ist dasselbe Muster, das es einem bestimmten Aufruf ermöglicht, ein Service-zu-Service-Token zu verwenden, während der Rest der App ein Benutzer-Token nutzt.

Behebe die häufigsten Axios-Header-Fehler

Die meisten Header-Probleme in der Produktion lassen sich auf vier Muster zurückführen: eine entfernte Multipart-Grenze bei Uploads, eine CORS- oder withCredentials Fehlanpassung im Browser, ein selbstsigniertes TLS-Zertifikat in Node und Backends, die bei Groß- und Kleinschreibung unterscheiden und das von Axios gesendete Wire-Format ablehnen. Die folgenden vier Unterabschnitte sind so verfasst, dass Sie direkt über die Suche zu jedem einzelnen gelangen und die Korrektur anwenden können, ohne zurückblättern zu müssen.

Fehlgeschlagene Multipart/Form-Data-Uploads (die Boundary-Falle)

Der mit Abstand häufigste Axios-FormData-Content-Type-Fehler ist die „Korrektur“, die Nutzer instinktiv vornehmen: die Einstellung Content-Type: multipart/form-data selbst festlegen. Dieser Wert allein ist unvollständig, da echte Multipart-Body-Daten einen boundary Parameter, den der Server zur Trennung der Felder verwendet. Wenn Sie den bloßen Wert fest codieren, überschreibt Axios ihn nicht, die tatsächliche Begrenzung erreicht nie die Leitung, und der Server lehnt den Upload ab.

Der richtige Weg ist, den Header von der Laufzeitumgebung für dich erstellen zu lassen.

// 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

Eine Ausnahme: Wenn Sie Axios ein einfaches Objekt übergeben und es intern in FormData serialisieren lassen, ist ein expliziter Content-Type: multipart/form-data ist in Ordnung, da Axios die Trennzeichen selbst einfügt.

CORS-Blockierungen, `withCredentials` und fehlende Cookies

CORS ist browserabhängig. Node hat kein CORS, keine blockierten Header und keinen Preflight, daher ist dieser gesamte Abschnitt etwas, das Sie nur in einem Browser-Tab debuggen können. Axios-CORS-Header können vom Client aus nicht deaktiviert werden; der Browser ist für die Regel zuständig und Axios ist ihr untergeordnet. Die maßgebliche Referenz für das, was der Browser durchsetzt, ist der MDN-CORS-Leitfaden.

Damit Cross-Origin-Cookies übertragen werden können, müssen vier Dinge zusammenkommen:

  1. Der Client setzt Axios-Cookies mit „withCredentials“ auf „on“. Entweder instance.defaults.withCredentials = trueoder { withCredentials: true } pro Anfrage.
  2. Der Server gibt Access-Control-Allow-Credentials: true.
  3. Access-Control-Allow-Origin einen bestimmten Ursprung zurück, niemals *. Der Platzhalter wird abgelehnt, sobald Anmeldedaten im Spiel sind.
  4. Cookies werden mit SameSite=None; Secure. Ein SameSite=Strict Cookie wird niemals siteübergreifend gesendet, selbst bei withCredentials set.
const api = axios.create({
  baseURL: "https://api.example.com",
  withCredentials: true, // tells the BROWSER to attach cookies
});

Wenn Sie nicht Eigentümer der übergeordneten API sind und die CORS-Antwort nicht korrigieren können, ist die einzige ehrliche Lösung ein kleiner serverseitiger Proxy auf Ihrer eigenen Domain, der den Aufruf weiterleitet. Wenn Sie diesen hinter Ihrer eigenen Subdomain platzieren, umgehen Sie zudem das Problem der Abkündigung von Third-Party-Cookies. Eine Einführung in das zugrunde liegende Cookie-Verhalten lohnt es sich, als Lesezeichen zu speichern.

Selbstsignierte HTTPS-Zertifikate in Node.js

In Node haben Sie die volle Kontrolle über TLS, sodass Sie mit einer Dev-API kommunizieren können, die ein selbstsigniertes Zertifikat verwendet, ohne dass es zu Laufzeitproblemen kommt. In einem Browser ist dies nicht möglich und Sie sollten es auch nicht versuchen; der Benutzer muss der Zertifizierungsstelle im Betriebssystem oder im Browserspeicher vertrauen.

Verwenden Sie einen benutzerdefinierten HTTPS-Agenten ausschließlich für die Entwicklung oder das Staging auf Node-Seite. Die Node.js-Dokumentation zu „https.Agent behandelt alle Optionen:

import https from "node:https";

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

Dieses Flag deaktiviert die Zertifikatsüberprüfung, was bedeutet, dass Man-in-the-Middle-Angriffe nicht mehr erkennbar sind. Setze dies niemals in der Produktion ein. Die Lösung für die Produktion besteht darin, deine Zertifizierungsstelle in den System-Trust-Store aufzunehmen oder ein echtes Zertifikat auszustellen (Let's Encrypt, ein interner ACME-Server oder der Zertifikatsmanager deines Cloud-Anbieters). rejectUnauthorized: false ist ein Werkzeug für den Entwicklungszyklus, keine Bereitstellungsstrategie.

Groß-/Kleinschreibung von Headern bei wählerischen Legacy-Backends

HTTP ist theoretisch groß-/kleinschreibungsunabhängig, aber eine nicht unerhebliche Anzahl von Legacy-Backends lehnt Anfragen ab, deren Header-Namen nicht in der kanonischen Groß-/Kleinschreibung vorliegen. Axios normalisiert einige Header-Namen intern, aber bei benutzerdefinierten Headern sollten Sie die Groß-/Kleinschreibung senden, die der Upstream erwartet.

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

Die Kehrseite: Wenn du dieselben Header aus response.headers, wandelt Axios jeden Schlüssel in Kleinbuchstaben um. Du sendest also X-API-Key , lesen aber res.headers["x-api-key"]. Diese Asymmetrie ist beabsichtigt und zieht sich durch die gesamte Version 1. Wähle die kanonische Groß-/Kleinschreibung für ausgehende Daten, akzeptiere Kleinbuchstaben für eingehende Daten, und du wirst nie wieder einen „fehlenden Header“ debuggen müssen.

Sende browserähnliche Header für Web-Scraping mit Axios

Webserver überprüfen Request-Header, um zu entscheiden, ob der Client ein echter Browser oder ein Bot ist, und ein Standard-Node-User-Agent wie axios/1.7.7 der schnellste Weg, um als Bot markiert zu werden. Wenn Sie Axios zum Scraping verwenden, senden Sie ein glaubwürdiges Header-Bundle und wechseln Sie es regelmäßig.

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;
});

So umgehst du einfache Bot-Filter. Anspruchsvolle Ziele kombinieren JA3-Fingerabdrücke, TLS-Profile, Cloudflare-Challenges und Verhaltensprüfungen, und kein Header-Bundle allein kann diese Hürden nehmen. Wenn axios Rotation nicht mehr ausreicht, sollten Sie auf einen Residential-Proxy-Pool oder eine verwaltete Scraping-API umsteigen, die Fingerabdruckerkennung, Wiederholungsversuche und CAPTCHA-Workflows für Sie übernimmt. Eine Aufschlüsselung der Gründe, warum Scraper über Header hinaus blockiert werden, ist eine nützliche Lektüre für den nächsten Schritt.

Wichtige Erkenntnisse zu Axios-Header-Sets im Jahr 2026

Das gesamte Axios-Header-Modell lässt sich in ein fünfschichtiges Schema zusammenfassen, ergänzt durch eine Reihenfolgeregel:

  • Konfiguration pro Anfrage für Einzelfälle und Überschreibungen; hat Vorrang vor allen darunter liegenden Standardeinstellungen.
  • Globale Standardeinstellungen nur für Skripte mit einer einzigen API und Entwicklertools; riskant, sobald Sie mehrere Hosts aufrufen.
  • axios.create() Instanzen als Standard für 2026 für jede App, die mit mehr als einem Upstream kommuniziert.
  • Anfrage-Interceptors für übergreifende Aspekte wie Authentifizierungs-Injektion, Rollen-Flags und Tracing.
  • Antwortprüfung, sodass response.headers tatsächlich Ihre Wiederholungs-, Cache- und Paginierungslogik beeinflusst.

Zusammenführungsreihenfolge, von niedrig nach hoch: Bibliotheksstandardwerte, globale Standardwerte, Instanzstandardwerte, Konfiguration pro Anfrage, Anfrage-Interceptoren. Verwenden Sie den if (!config.headers.x) Guard innerhalb von Interceptors, wenn Sie möchten, dass die anfragebezogene Konfiguration Vorrang behält.

FAQ

Was ist der Unterschied zwischen axios.defaults.headers.common und axios.defaults.headers.post?

common gilt für jede HTTP-Methode der Standard-Axios-Instanz, sodass dort festgelegte Header bei GET, POST, PUT, PATCH und DELETE mitgeschickt werden. post (und .get, .put, .patch, .delete) gilt nur, wenn dieses spezifische Verb verwendet wird. Greifen Sie zuerst auf common zuerst; verwende die Methoden-Buckets nur, wenn ein Verb tatsächlich einen anderen Standardwert benötigt.

Wie stelle ich in Axios sicher, dass ein anfragebezogener Header Vorrang vor einem Request-Interceptor hat?

Schützen Sie den Interceptor so, dass er nur dann einen Header schreibt, wenn der Aufrufer noch keinen gesetzt hat. Das Muster lautet if (!config.headers.Authorization) { config.headers.Authorization = ... }. Da Interceptors nach der Zusammenführung der anfragebezogenen Header ausgeführt werden, überschreibt eine bedingungslose Zuweisung Ihre Überschreibung. Die abgesicherte Version berücksichtigt, was auch immer der Aufrufer übergeben hat.

Warum wandelt Axios Header-Namen in Kleinbuchstaben um, wenn ich sie aus response.headers auslese?

Axios normalisiert Response-Header-Schlüssel konventionell in Kleinbuchstaben. HTTP selbst behandelt Headernamen als groß-/kleinschreibungsunabhängig, und die Umwandlung in Kleinbuchstaben beim Auslesen bedeutet, dass Sie nie die Groß-/Kleinschreibung für etag, content-typeoder x-ratelimit-remaining. Sende die kanonische Schreibweise beim Senden, lies Kleinbuchstaben beim Empfangen.

Kann Axios CORS umgehen, wenn eine Drittanbieter-API vom Browser aus aufgerufen wird?

Nein. CORS wird vom Browser durchgesetzt, bevor Axios überhaupt ausgeführt wird, daher gibt es kein clientseitiges Flag, das es deaktivieren könnte. Die einzige wirkliche Lösung besteht darin, den Upstream dazu zu bringen, die richtigen Access-Control-Allow-Origin und Access-Control-Allow-Credentials Header sendet oder den Aufruf über einen kleinen serverseitigen Proxy zu leiten, den Sie kontrollieren. Node hat überhaupt keine CORS-Regeln.

Wie sende ich ein Bearer-Token nur an eine bestimmte baseURL, ohne es an andere Hosts weiterzugeben?

Erstellen Sie eine dedizierte axios.create() Instanz für diese API und legen Sie deren Authorization nur auf der Instanz fest. Schreiben Sie das Token niemals in axios.defaults, da dieser es an jeden Host weiterleitet, den das Standard-Singleton aufruft. Wenn du eine gemeinsame Instanz verwenden musst, schütze einen Request-Interceptor mit einer Hostnamenprüfung, damit der Header nur angehängt wird, wenn die URL mit deiner vertrauenswürdigen baseURL übereinstimmt.

Zusammenfassung

Wenn Sie eine Sache aus dieser Anleitung zum Setzen von Headern in Axios verinnerlichen, dann sollte es die Schichtung sein: Jeder Header befindet sich an einem von fünf Orten, und die Reihenfolge ist: Bibliotheksstandardwerte, globale Standardwerte, Instanzstandardwerte, Konfiguration pro Anfrage und schließlich Anfrage-Interceptors. Wählen Sie die höchste Ebene, die der Lebensdauer des Headers entspricht. Einmalige Überschreibungen erfolgen pro Anfrage. App-weite Aspekte gehören in eine Instanz. Querschnittsmäßige Authentifizierung gehört in einen Interceptor. Und jede Axios-Antwort enthält Header, die deine nächste Entscheidung beeinflussen sollten und nicht verworfen werden dürfen.

Die gleichen Muster gelten auch, wenn du mehr tust, als nur gut funktionierende REST-APIs aufzurufen. Sobald du Axios auf ein Ziel richtest, das Clients identifiziert, aggressive Ratenbegrenzungen durchführt oder Daten hinter JavaScript-Herausforderungen versteckt, reicht die Header-Rotation allein nicht mehr aus. Hier wird eine verwaltete Ebene zum entscheidenden Schritt: Die WebScrapingAPI Scraper-API übernimmt Proxy-Rotation, TLS-Fingerabdrücke auf Browserebene und CAPTCHA-Lösung hinter einem einzigen Endpunkt, sodass der Axios-Code, den du gerade geschrieben hast, seine Form behält und du keine Feuerwehreinsätze mehr durchführen musst. Setze ein Lesezeichen für diese Seite als Referenz für Axios-Header-Einstellungen und greife auf den verwalteten Weg zurück, wenn die Anforderungsschicht nicht mehr das interessante Problem ist.

Über den Autor
Mihnea-Octavian Manolache, Full-Stack-Entwickler @ WebScrapingAPI
Mihnea-Octavian ManolacheFull-Stack-Entwickler

Mihnea-Octavian Manolache ist Full-Stack- und DevOps-Entwickler bei WebScrapingAPI. Er entwickelt Produktfunktionen und sorgt für die Wartung der Infrastruktur, die den reibungslosen Betrieb der Plattform gewährleistet.

Los geht’s

Sind Sie bereit, Ihre Datenerfassung zu erweitern?

Schließen Sie sich den über 2.000 Unternehmen an, die WebScrapingAPI nutzen, um Webdaten im Unternehmensmaßstab ohne zusätzlichen Infrastrukturaufwand zu extrahieren.