CORS error explained: “No ‘Access-Control-Allow-Origin’ header is present”

Your fetch works in curl and Postman, then the browser says it was “blocked by CORS policy”. Here is what the browser is protecting, and the fix for each message.

What the browser is protecting

An origin is scheme + host + port: https://app.example.com and http://localhost:3000 are different origins, and so are example.com and api.example.com. By default a page may send requests to other origins but may not read the responses. Otherwise any website you visit could quietly read your webmail or bank pages using your logged-in cookies.

CORS (Cross-Origin Resource Sharing) is how a server opts in: it adds Access-Control-Allow-* headers, and the browser checks them before handing the response to your JavaScript. curl, Postman and server-side code don't run this check at all, which is why the same request “works everywhere except the browser”.

The message, and what it means

Browser saysWhat is actually wrongFix on the server
No 'Access-Control-Allow-Origin' header is present on the requested resourceThe response has no CORS header at all. Often it's an error page (404, 500, a proxy or login page) that skipped your CORS middleware.Send Access-Control-Allow-Origin on every response, including errors. Check the status in the Network tab first.
Response to preflight request doesn't pass access control check: It does not have HTTP ok statusThe OPTIONS preflight got a 401, 404, 405 or redirect.Answer OPTIONS with 204 (or 200) before any auth check.
Request header field authorization is not allowed by Access-Control-Allow-HeadersYou sent a header the preflight didn't approve.Access-Control-Allow-Headers: Authorization, Content-Type
Method PUT is not allowed by Access-Control-Allow-MethodsSame, for the method.Access-Control-Allow-Methods: GET, POST, PUT, DELETE
The value of the 'Access-Control-Allow-Origin' header must not be the wildcard '*' when the request's credentials mode is 'include'You send cookies (credentials: 'include') but the server allows *.Echo the exact allowed origin, add Access-Control-Allow-Credentials: true and Vary: Origin.
Redirect is not allowed for a preflight requestThe API redirects (http→https, missing trailing slash) before answering.Call the final URL directly. See redirect codes explained.

What is a preflight?

For anything beyond a “simple” request, the browser first sends an OPTIONS request asking permission. A request is simple only if it uses GET, HEAD or POST, sends no custom headers, and any Content-Type is text/plain, multipart/form-data or application/x-www-form-urlencoded. So a POST with Content-Type: application/json, or any request with an Authorization header, always triggers a preflight. A good preflight answer looks like this:

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

Access-Control-Max-Age lets the browser reuse the answer (Chrome caps it at two hours) so it doesn't preflight every call.

Preflight failing with 405, 401 or a redirect? See CORS preflight failed.

Fixes by situation

A CORS error can also hide a server error: if the API crashes with a 500 or a proxy returns a 502 Bad Gateway, the error page usually lacks CORS headers, so the browser reports CORS instead. Check the Network tab for the real status code.

Things that don't work

Tip: copy the failing response from the Network tab into the JSON formatter. If it isn't JSON at all (an HTML error page, a login form), that's usually the real problem and the CORS message is just the symptom.

Sending cookies or logins across origins? * stops working; see CORS with credentials and why a cookie is not being set.

Only seeing TypeError: Failed to fetch? A checklist for finding the real cause.

Related

TypeError: fetch failed (Node) · React hydration failed · WebSocket connection failed

Questions

Why does my request work in Postman but not in the browser?

CORS is enforced only by browsers. Postman, curl and server code never check Access-Control-Allow-Origin, so they see the response the browser is hiding from your page.

Can I fix a CORS error from the front end?

No. Only the server (or a proxy on your own origin) can grant access. mode: 'no-cors' just gives you an unreadable opaque response.

Is Access-Control-Allow-Origin: * safe?

For public data that needs no login, yes. Never combine it with cookies or other credentials; browsers refuse that, and reflecting arbitrary origins with credentials is a security hole.

Why do I get a CORS error on a 500 error?

Many frameworks add CORS headers only on successful responses. When the server crashes, the error page has no CORS header, so the browser reports CORS instead of the 500. Fix the error and make sure error responses also carry the header.

Published .

Try it

Related guides

Newest guides