Wenn du einen roten CORS-Fehler in deiner Browser-Konsole gesehen hast, bedeutet das, dass dein Frontend eine Anfrage an eine API sendet, der Browser dir die Antwort aber verweigert. Die klassische Meldung lautet: Access to fetch at '...' from origin '...' has been blocked by CORS policy. Auf den ersten Blick wirkt es, als wäre der Server abgestürzt, doch die Anfrage erreicht den Server meist und eine Antwort kommt auch zurück — der Browser gibt diese Antwort wegen einer Sicherheitsregel nur nicht an dein JavaScript weiter. In diesem Artikel erkläre ich, was der Fehler wirklich ist, die Konzepte Origin und Preflight, und wie du das Problem mit den richtigen Response-Headern dauerhaft behebst.
Was genau ist ein CORS-Fehler?
CORS steht für Cross-Origin Resource Sharing. Standardmäßig setzen Browser die Same-Origin-Policy durch: JavaScript auf einer Seite darf nur Antworten lesen, die zur selben Origin gehören. Eine Origin besteht aus drei Teilen: Protokoll, Domain und Port. Somit sind https://site.com, http://site.com, https://api.site.com und https://site.com:8080 allesamt unterschiedliche Origins.
Wenn dein Frontend auf http://localhost:3000 und deine API auf http://localhost:8000 läuft, sind das zwei verschiedene Origins, und der Browser blockiert die Antwort, sofern der Server nicht ausdrücklich die Erlaubnis erteilt. CORS ist der standardisierte Weg, diese Erlaubnis zu erteilen: Der Server fügt seiner Antwort spezielle Header hinzu, die sagen „Ich erlaube dieser Origin, Daten von mir zu lesen".
Der entscheidende Unterschied: Die Lösung liegt auf dem Server, nicht auf dem Client
Das ist das häufigste Missverständnis. CORS ist ein Browser-Mechanismus, aber die Erlaubnis kommt vom Server. Du kannst den Fehler nicht lösen, indem du fetch-Optionen auf der JavaScript-Seite anpasst; die Lösung besteht darin, dass die API die richtigen Response-Header sendet. Der zentrale Header ist:
Access-Control-Allow-Origin: https://site.com
Fehlt dieser Header in der Antwort oder passt er nicht zur anfragenden Origin, blockiert der Browser sie. Wenn du dieselbe Anfrage aus Postman oder curl sendest, hast du kein Problem — weil das keine Browser sind und sie die Same-Origin-Policy nicht durchsetzen. Genau deshalb tritt der Fehler nur im Browser auf.
Was ist eine Preflight-Anfrage (OPTIONS)?
Vor manchen Anfragen sendet der Browser eine Preflight-Anfrage vor der eigentlichen. Das ist eine „Erlaubnisprüfung" mit der OPTIONS-Methode. Der Browser fragt: „Darf ich eine Anfrage von dieser Origin, mit dieser Methode, mit diesen Headern senden?"
Ein Preflight wird ausgelöst, weil die Anfrage nicht „einfach" ist. Eine Anfrage benötigt einen Preflight, wenn sie eine andere Methode als GET, POST oder HEAD verwendet (z. B. PUT, DELETE, PATCH) oder benutzerdefinierte Header trägt (z. B. Authorization, Content-Type: application/json). Der Server muss die erlaubten Methoden und Header in seiner OPTIONS-Antwort zurückgeben:
Access-Control-Allow-Origin: https://site.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Access-Control-Max-Age teilt dem Browser mit, wie viele Sekunden die Preflight-Antwort zwischengespeichert werden soll, damit nicht bei jeder Anfrage erneut ein OPTIONS-Aufruf erfolgt. Gibt der Server auf die OPTIONS-Anfrage einen 404 oder 405 zurück, ist das das Erste, was du beheben musst.
Den CORS-Fehler serverseitig beheben
Die Lösung variiert je nach Framework, doch die Logik ist dieselbe: die richtigen Header hinzufügen. In einer Express-basierten Node.js-API ist das offizielle cors-Paket der sauberste Weg:
const cors = require('cors');
app.use(cors({
origin: 'https://site.com',
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization'],
credentials: true,
}));
In Laravel liegt die CORS-Konfiguration in config/cors.php, und die HandleCors-Middleware wendet sie automatisch an. Dort definierst du die erlaubten Origins:
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['https://site.com'],
'allowed_headers' => ['*'],
'supports_credentials' => true,
Auf einem Webserver wie Nginx oder Apache kannst du die Header auch direkt hinzufügen, doch sie auf der Anwendungsebene zu verwalten ist meist flexibler, weil du die Origin bedingt validieren kannst.
Arbeiten mit Anmeldedaten (Cookies und Tokens)
Wenn deine Anfragen Cookies oder Authentifizierungsdaten tragen, greifen zwei Regeln. Erstens: Du musst credentials: 'include' auf der Client-Seite aktivieren:
fetch('https://api.site.com/data', {
credentials: 'include',
});
Zweitens und am wichtigsten: Werden Anmeldedaten verwendet, darf der Access-Control-Allow-Origin-Header nicht * (Wildcard) sein. Der Browser lehnt das aus Sicherheitsgründen ab; du musst die exakte Origin angeben. Der Server muss außerdem Access-Control-Allow-Credentials: true senden. Diese beiden Regeln zu übergehen ist eine der häufigsten Ursachen für den verwirrenden Fehler „Wildcard kann nicht mit Anmeldedaten verwendet werden".
Häufige Fehler und eine schnelle Checkliste
- Wildcard- + Anmeldedaten-Konflikt: Wenn du Cookies sendest, verwende die exakte Origin statt
*. - OPTIONS bleibt unbeantwortet: Stelle sicher, dass dein Server eine 2xx-Antwort auf den Preflight zurückgibt.
- Unterschied beim abschließenden Slash:
https://site.comgegenüberhttps://site.com/kann die Origin-Übereinstimmung brechen; vergleiche Protokoll + Host + Port genau. - Proxy-Workaround: In der Entwicklung kannst du den Frontend-Dev-Server (z. B. Vite) zur API proxyen, sodass Anfragen scheinbar von derselben Origin kommen.
Häufige Fragen
Kann ich den CORS-Fehler beheben, indem ich nur den Frontend-Code ändere?
Nein. Die richtigen Response-Header müssen vom Server kommen. Das Einzige, was du im Frontend tun kannst, ist in der Entwicklung einen Proxy zu nutzen oder deine credentials-Einstellung zu korrigieren; die eigentliche Erlaubnis wird stets auf der API-Seite erteilt.
Warum funktioniert es in Postman, aber ich bekomme im Browser einen CORS-Fehler?
Weil CORS eine Sicherheitsrichtlinie ist, die nur vom Browser durchgesetzt wird. Postman und curl setzen die Same-Origin-Policy nicht durch, daher funktioniert dieselbe Anfrage dort problemlos. Das zeigt dir, dass der Server läuft, aber die CORS-Header fehlen.
Ist es sicher, Access-Control-Allow-Origin: * zu verwenden?
Für eine öffentliche API ohne Anmeldedaten ist es akzeptabel. Aber für APIs, die mit Cookies/Tokens arbeiten oder sensible Daten ausliefern, verwende keine Wildcard; liste die erlaubten Origins ausdrücklich auf.
Möchtest du die CORS-Konfiguration deiner API dauerhaft und sicher lösen? Lass uns gemeinsam die Origin-, Preflight- und Anmeldedaten-Einstellungen zwischen deinem Frontend und Backend durchgehen und eine Lösung bauen, die zu deinem Projekt passt — nimm Kontakt mit mir auf.