CORS-Fehler beheben: Debugging von Access-Control-Allow-Origin

Einen CORS-Fehler bekommen? Erfahren Sie, was ihn auslöst, wie der Preflight funktioniert, die 6 häufigsten Access-Control-Allow-Origin-Fehler und die genaue Lösung für jeden davon.

Ashley Innocent

Ashley Innocent

31 August 2026

CORS-Fehler beheben: Debugging von Access-Control-Allow-Origin

Apidog für Unternehmen

On-Premises Bereitstellung

SSO & RBAC

SOC 2 konform

Apidog Enterprise entdecken

Sie veröffentlichen ein neues Frontend, öffnen die Konsole, und da ist er: ein roter CORS-Fehler, der Ihnen sagt, dass die Anfrage „durch die CORS-Richtlinie blockiert wurde“. Ihre API funktioniert einwandfrei in Apidog oder curl, doch der Browser weigert sich, Ihrem JavaScript die Antwort zu übergeben. Frustrierend? Ja. Mysteriös? Nicht, wenn Sie wissen, wo der Fehler liegt.

Hier ist die Kerninformation, die die meisten Tutorials verschweigen: Ein CORS-Fehler wird vom Browser erzwungen, aber vom Server verursacht. Der Browser blockiert die Antwort, weil Ihr Server nicht die richtigen Access-Control-Allow-Origin-Header gesendet hat. Die Lösung liegt also fast immer in der Serverkonfiguration, nicht in Ihrem Frontend-Code.

Dieser Leitfaden erklärt, was CORS bewirkt, wie die Preflight-Anfrage funktioniert, die sechs häufigsten CORS-Fehlermeldungen mit der genauen Lösung für jede einzelne sowie funktionierende Konfigurationen für Express, Spring Boot und Nginx. Sie erfahren auch, wie Sie außerhalb des Browsers debuggen können, was der schnellste Weg ist, um „Server falsch konfiguriert“ von „Browser blockiert“ zu unterscheiden.

Was ein CORS-Fehler ist (und was nicht)

CORS steht für Cross-Origin Resource Sharing (Ressourcenfreigabe über verschiedene Ursprünge). Standardmäßig setzen Browser die Same-Origin-Policy (Gleiche-Ursprungs-Richtlinie) durch: JavaScript, das auf https://app.example.com läuft, kann keine Antworten von https://api.example.com lesen, da Schema, Host oder Port abweichen. CORS ist der Mechanismus, den Server verwenden, um diese Regel absichtlich zu lockern. Die vollständigen Details finden Sie in der MDN CORS-Dokumentation, und der zugrunde liegende Algorithmus ist in der Fetch-Spezifikation definiert.

Drei Punkte klären die meisten Missverständnisse auf:

Wenn Sie also einen CORS-Fehler sehen, greifen Sie nicht zu einem Frontend-Workaround. Lesen Sie die Fehlermeldung und beheben Sie dann den fehlenden oder falschen Header auf dem Server.

Anatomie der Preflight-Anfrage

Vor bestimmten Cross-Origin-Anfragen sendet der Browser einen „Scout“: eine OPTIONS-Anfrage, die als Preflight bezeichnet wird. Sie wird ausgelöst, wenn Ihre Anfrage Methoden über GET, HEAD oder POST hinaus verwendet, benutzerdefinierte Header wie Authorization sendet oder einen Content-Type wie application/json verwendet.

Die Preflight-Anfrage sieht so aus:

OPTIONS /v1/orders HTTP/1.1
Host: api.example.com
Origin: https://app.example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization, content-type

Der Browser fragt: „Eine Seite auf app.example.com möchte hier mit diesen Headern einen POST-Request senden. Erlaubt?“ Eine korrekte Serverantwort:

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type
Access-Control-Max-Age: 86400
Vary: Origin

Fehlt ein Element, bricht der Browser die eigentliche Anfrage ab, bevor sie überhaupt ausgeführt wird. Ihr API-Endpunkt wird nie aufgerufen, Ihre Logs zeigen nichts außer einem OPTIONS-Treffer, und die Konsole zeigt einen CORS-Fehler an. Access-Control-Max-Age weist den Browser an, dieses Urteil zu cachen (hier 86400 Sekunden), sodass wiederholte Anfragen den Preflight überspringen.

Behalten Sie diesen zweistufigen Tanz im Hinterkopf. Die Hälfte aller CORS-Debugging-Fälle lässt sich auf eine Frage reduzieren: Ist der Preflight fehlgeschlagen, oder ist die eigentliche Anfrage fehlgeschlagen?

Die 6 häufigsten CORS-Fehler und wie man sie behebt

Browser schreiben überraschend präzise CORS-Fehlermeldungen. Vergleichen Sie Ihre mit der folgenden Liste.

1. Der Header „Access-Control-Allow-Origin“ ist nicht vorhanden

Der Klassiker. Ihr Server hat eine Antwort ohne jegliche CORS-Header gesendet. Der Browser hatte nichts zu bewerten und blockierte daher den Zugriff.

Lösung: Konfigurieren Sie den Server so, dass er Access-Control-Allow-Origin entweder mit dem spezifischen anfragenden Ursprung oder mit * für öffentliche, anmeldefreie APIs sendet:

Access-Control-Allow-Origin: https://app.example.com

Eine Falle: Fehlerantworten überspringen oft CORS-Header, auch wenn Erfolgsantworten diese enthalten. Wenn Ihre API einen 500er-Fehler zurückgibt und die Middleware nur 200er-Antworten dekoriert, zeigt die Konsole einen CORS-Fehler anstelle des tatsächlichen Serverfehlers. Stellen Sie sicher, dass CORS-Header an jede Antwort angehängt werden, einschließlich 403 Forbidden und 500er-Seiten.

2. Wildcard „*“ kann nicht mit Anmeldeinformationen verwendet werden

Die Meldung lautet: „Der Wert des Headers ‚Access-Control-Allow-Origin‘ darf nicht der Wildcard-Wert ‚*‘ sein, wenn der Anmeldeinformationsmodus der Anfrage ‚include‘ ist.“

Ihr Frontend sendet Cookies oder Authentifizierungs-Header mit credentials: 'include', aber der Server antwortet mit Access-Control-Allow-Origin: *. Die Fetch-Spezifikation verbietet diese Kombination; eine Wildcard plus Anmeldeinformationen würde es jeder Website im Internet ermöglichen, authentifizierte Antworten zu lesen.

Lösung: Geben Sie den genauen Ursprung anstelle der Wildcard zurück und fügen Sie den Credentials-Header hinzu:

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true

Validieren Sie den eingehenden Origin anhand einer Zulassungsliste, bevor Sie ihn zurückgeben. Das Zurückgeben beliebiger Ursprünge mit aktivierten Anmeldeinformationen untergräbt den gesamten Schutz.

3. Die Antwort auf die Preflight-Anfrage besteht die Zugriffskontrollprüfung nicht

Ihr Server hat die OPTIONS-Anfrage nie bearbeitet. Vielleicht definiert die Route nur POST, sodass OPTIONS einen 404 oder 405 zurückgibt. Vielleicht hat eine Auth-Middleware die Anfrage mit einem 401 abgelehnt, weil der Preflight kein Token enthält (Browser fügen Preflights niemals Anmeldeinformationen hinzu).

Lösung: Behandeln Sie OPTIONS explizit und geben Sie einen 2xx-Status mit dem vollständigen Satz von CORS-Headern zurück, bevor die Authentifizierung ausgeführt wird. In den meisten Frameworks löst die frühzeitige Einbindung der CORS-Middleware das Problem. Wenn Sie es manuell schreiben:

app.options('/v1/orders', (req, res) => {
  res.set({
    'Access-Control-Allow-Origin': 'https://app.example.com',
    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
    'Access-Control-Allow-Headers': 'Authorization, Content-Type'
  });
  res.sendStatus(204);
});

4. Der Header-Wert stimmt nicht mit dem angegebenen Ursprung überein

Der Server sendet einen Access-Control-Allow-Origin-Header, aber er nennt den falschen Ursprung. Häufige Ursachen: ein fest codierter Produktionsursprung, während Sie von http://localhost:5173 testen, ein Fehler beim Vergleich der Zulassungsliste zwischen http und https oder ein versehentlicher abschließender Schrägstrich (https://app.example.com/ ist kein gültiger Ursprungswert).

Lösung: Vergleichen Sie den Origin-Header der Anfrage genau mit Ihrer Zulassungsliste, geben Sie die Übereinstimmung zurück und senden Sie Vary: Origin, damit Caches und CDNs den Header eines Ursprungs nicht einem anderen Ursprung servieren:

const allowed = ['https://app.example.com', 'http://localhost:5173'];
if (allowed.includes(req.headers.origin)) {
  res.set('Access-Control-Allow-Origin', req.headers.origin);
  res.set('Vary', 'Origin');
}

5. Anfrage-Header-Feld oder Methode ist nicht erlaubt

Zwei verwandte Meldungen: „Anfrage-Header-Feld Authorization ist nicht durch Access-Control-Allow-Headers in der Preflight-Antwort erlaubt“ und „Methode PUT ist nicht durch Access-Control-Allow-Methods erlaubt.“

Der Preflight war erfolgreich, aber seine Antwort deckte nicht ab, was Ihre Anfrage benötigt. Sie haben einen Authorization-Header oder einen X-Request-Id hinzugefügt, und die Zulassungsliste des Servers hat ihn nie erwähnt.

Lösung: Erweitern Sie die Preflight-Antwort, um jeden Header und jede Methode einzuschließen, die Ihr Frontend sendet:

Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS
Access-Control-Allow-Headers: Authorization, Content-Type, X-Request-Id

Header-Namen sind hier Groß- und Kleinschreibung ignorierend. Methoden sind Groß- und Kleinschreibung beachtend und in Großbuchstaben.

6. Weiterleitung ist für eine Preflight-Anfrage nicht erlaubt

Der Preflight traf auf eine URL, die einen 301- oder 302-Status zurückgab, und Browser weigern sich, Weiterleitungen während des Preflights zu folgen. Typische Übeltäter: eine http-URL, die zu https weiterleitet, ein fehlender abschließender Schrägstrich, den Ihr Framework „hilfreich“ umleitet, oder ein Gateway, das /v1/orders auf /v1/orders/ umleitet.

Lösung: Richten Sie Ihr Frontend direkt auf die endgültige URL aus. Verwenden Sie von Anfang an https, passen Sie die Konvention für den abschließenden Schrägstrich Ihres Routers an und bestätigen Sie mit einem manuellen OPTIONS-Aufruf, ob der Endpunkt mit einem 2xx- anstelle eines 3xx-Status antwortet.

Beispiele für Serverkonfigurationen

Hier ist die korrekte CORS-Einrichtung in drei gängigen Stacks.

Express

Verwenden Sie die offizielle cors-Middleware, anstatt die Header manuell zu erstellen:

const express = require('express');
const cors = require('cors');
const app = express();

app.use(cors({
  origin: ['https://app.example.com', 'http://localhost:5173'],
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Authorization', 'Content-Type'],
  credentials: true,
  maxAge: 86400
}));

Binden Sie sie vor Ihrer Auth-Middleware ein, damit Preflights niemals wegen fehlender Tokens abgelehnt werden. Python-Entwickler erhalten das gleiche Muster von der Flask-CORS-Erweiterung, die eine identische Header-Logik für Flask-Anwendungen kapselt.

Spring Boot

Globale Konfiguration über WebMvcConfigurer:

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/v1/**")
            .allowedOrigins("https://app.example.com")
            .allowedMethods("GET", "POST", "PUT", "DELETE")
            .allowedHeaders("Authorization", "Content-Type")
            .allowCredentials(true)
            .maxAge(86400);
    }
}

Verwenden Sie Spring Security? Rufen Sie .cors(Customizer.withDefaults()) auch in Ihrer Security-Filterkette auf, da sonst die Sicherheitsebene Preflights blockiert, bevor die MVC-Konfiguration sie überhaupt sieht. Die vollständige Optionspalette finden Sie in der Spring CORS-Dokumentation.

Nginx

Wenn Nginx Anfragen vor Ihrer Anwendung terminiert, beantworten Sie Preflights am Edge:

location /v1/ {
    if ($request_method = OPTIONS) {
        add_header Access-Control-Allow-Origin "https://app.example.com" always;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;
        add_header Access-Control-Max-Age 86400 always;
        return 204;
    }
    add_header Access-Control-Allow-Origin "https://app.example.com" always;
    add_header Vary "Origin" always;
    proxy_pass http://backend;
}

Der always-Flag ist wichtig. Ohne ihn verwirft Nginx add_header-Direktiven bei 4xx- und 5xx-Antworten, was bei jeder fehlgeschlagenen Anfrage Fehler Nummer eins wieder herstellt. Und wählen Sie eine Ebene, die für CORS zuständig ist: Wenn sowohl Nginx als auch Ihre Anwendung Header hinzufügen, sehen Browser Duplikate wie Access-Control-Allow-Origin: *, * und lehnen die Antwort ab.

CORS außerhalb des Browsers mit Apidog debuggen

Der Konsolenfehler zeigt Ihnen an, dass der Browser etwas blockiert hat. Er sagt Ihnen nicht, was der Server gesendet hat. Der schnellste Weg, die Wahrheit herauszufinden, ist, den Browser aus der Schleife zu nehmen.

Apidog ist ein Desktop-API-Client, daher unterliegen seine Anfragen überhaupt keinen Browser-CORS-Checks. Das ermöglicht ein sauberes Experiment: Senden Sie dieselbe Anfrage von Apidog, die Ihr Frontend gestellt hat. Wenn sie dort erfolgreich ist, ist Ihre API-Logik in Ordnung und das Problem sind lediglich fehlende CORS-Header. Wenn sie dort auch fehlschlägt, haben Sie einen gewöhnlichen API-Fehler im CORS-Gewand, und allgemeine API-Testtechniken sind anwendbar.

Eine CORS-Debugging-Sitzung in Apidog sieht so aus:

  1. Die tatsächliche Anfrage wiederholen. Kopieren Sie die fehlgeschlagene Anfrage aus dem Netzwerk-Tab Ihres Browsers und erstellen Sie sie in Apidog mit derselben Methode, denselben Headern und demselben Body neu. Überprüfen Sie Status und Body. Ein 500er hier bedeutet, dass CORS nie Ihr Problem war.
  2. Den Preflight manuell testen. Erstellen Sie eine neue Anfrage, setzen Sie die Methode auf OPTIONS und fügen Sie die Header hinzu, die ein Browser senden würde: Origin: https://app.example.com, Access-Control-Request-Method: POST und Access-Control-Request-Headers: authorization, content-type. Senden Sie sie.
  3. Die Antwort-Header inspizieren. Suchen Sie im Antwortbereich nach Access-Control-Allow-Origin, Access-Control-Allow-Methods und Access-Control-Allow-Headers. Vergleichen Sie jeden Wert mit dem, was Ihr Frontend benötigt. Ein fehlender Header, ein falscher Ursprung oder ein 3xx-Status sticht sofort ins Auge, ohne Konsolen-Rätselraten.
  4. Die Korrektur überprüfen. Nach dem Ändern der Serverkonfiguration senden Sie dieselbe gespeicherte OPTIONS-Anfrage erneut und beobachten Sie, wie sich die Header aktualisieren. Kein erneutes Bereitstellen von Frontends, keine Cache-Löschrituale.

Dieser Workflow löst auch das ewige Argument „funktioniert in meinem API-Client, schlägt im Browser fehl“ in Sekunden, dasselbe Rätsel hinter der Postman CORS-Test-Frage. Der Client funktioniert, weil er CORS umgeht. Der Browser schlägt fehl, weil Ihr Server die magischen Worte nicht gesagt hat. Laden Sie Apidog kostenlos herunter und speichern Sie die OPTIONS-Anfrage neben Ihren regulären Endpunkt-Tests; zukünftige CORS-Brände werden mit einem Klick gelöscht.

Eine 30-Sekunden-CORS-Checkliste

Bevor Sie den Fehler melden, gehen Sie diese Liste durch:

In neun von zehn Fällen ist eine dieser sechs Zeilen Ihre Antwort. Überprüfen Sie dies mit einer manuellen OPTIONS-Anfrage in Apidog, patchen Sie die Serverkonfiguration und widmen Sie sich wieder dem Aufbau.

FAQ

Warum erhalte ich nur im Browser einen CORS-Fehler?

Weil nur Browser CORS durchsetzen. Die Same-Origin-Policy schützt Benutzer vor bösartigen Seiten, die ihre authentifizierten Daten lesen, daher überprüfen Browser Access-Control-Allow-Origin bei jeder Cross-Origin-Antwort. curl, Backend-Dienste und Desktop-Clients haben keine solche Regel. Wenn eine Anfrage überall außer im Browser erfolgreich ist, fehlen Ihrem Server CORS-Header oder sind falsch konfiguriert; die API selbst ist in Ordnung.

Gilt CORS für Postman oder Apidog?

Nein. Postman und Apidog sind Desktop-Anwendungen, keine Webseiten, die in einer Browser-Sandbox laufen, daher umgehen ihre Anfragen CORS vollständig. Genau das macht sie für das CORS-Debugging nützlich: Sie zeigen Ihnen die rohen Antwort-Header des Servers ohne die Filterung des Browsers. Die Verwirrung um den Postman CORS-Test beginnt meist hier; eine erfolgreiche Anfrage in einem Desktop-Client beweist nichts über das Browserverhalten, aber sie isoliert die fehlerhafte Schicht.

Ist ein CORS-Fehler eine Sicherheitsfunktion oder ein Bug?

Eine Funktion. CORS-Fehler bedeuten, dass der Browser seine Aufgabe erfüllt: Er weigert sich, ursprungsübergreifende Antwortdaten Skripten preiszugeben, es sei denn, der Server stimmt dem zu. Das Deaktivieren von CORS im Browser mit Flags oder Erweiterungen verbirgt das Symptom auf Ihrem Computer, während jeder Benutzer weiterhin auf die Barriere stößt. Beheben Sie stattdessen die Server-Header.

Kann ich Access-Control-Allow-Origin: * überall verwenden?

Nur für öffentliche, schreibgeschützte APIs ohne Cookies oder Authentifizierung. Die Wildcard wird abgelehnt, sobald Anmeldeinformationen enthalten sind, und sie kündigt an, dass Ihre Daten für jeden Ursprung im Web offen sind. Für alles Authentifizierte pflegen Sie eine Ursprungs-Zulassungsliste, geben Sie den passenden Ursprung zurück und senden Sie Vary: Origin, damit gemeinsame Caches die Antworten getrennt halten.

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen