Tailored quoteLeave a short request: we reply the same day and send a written quote within 1 business daySame-day reply · quote in 1 business dayGet a quote
Software

How to Fix CORS Error: "No Access-Control-Allow-Origin" Header

Talha Aslan 17 min read 4 views

How do you fix a CORS error?

A CORS error means the browser refused to hand a cross-origin response to your JavaScript, because the server did not send the permission headers. You fix it on the server. Add the right Access-Control-Allow-Origin header to the API response and answer the preflight (OPTIONS) request with a success status.

A red message in the console feels urgent, but the cause is usually small. Most of the time you have one missing header or one mistyped address. This guide walks through the checks from the most likely cause to the least likely one.

We keep the scope narrow on purpose. If your local server does not respond at all, read our localhost refused to connect guide first. That problem is a network issue, not CORS.

What is the quick fix for a CORS error, step by step?

First, confirm the problem is really CORS, because several other errors look similar. Then follow this order.

  1. Open the Network tab in your browser developer tools and find the failed request.
  2. Check whether the failing request is the preflight (OPTIONS) or the real request.
  3. Look for the Access-Control-Allow-Origin header in the response.
  4. Compare its value with the origin in your address bar, character by character.
  5. For a preflight, check Access-Control-Allow-Methods and Access-Control-Allow-Headers.
  6. If you send cookies or an authorization header, replace the wildcard (*) with an explicit origin and add Access-Control-Allow-Credentials.
  7. Apply the fix on the server, clear caches, and retry the request.

These seven steps solve most cases. The order is deliberate. The Network tab shows the facts, while the console only summarizes them, so do not skip the first two steps.

Why does a CORS error happen, and what is the same-origin policy?

Browsers enforce the same-origin policy by default. It stops code on one page from reading responses that belong to another origin. As a result, a malicious site cannot use your logged-in session to read data from a different site.

CORS (Cross-Origin Resource Sharing) is a controlled exception to that rule. The server declares which origins may read its responses, using headers. The browser checks those headers and withholds the response if they do not match.

One detail surprises many developers. The request often reaches the server, and the server answers. However, the browser is the one that blocks your code from reading the answer. That is why your server log can show the request while the console shows an error.

The MDN CORS guide and the WHATWG Fetch standard are the primary references if you want the full rules.

What is an origin, and which URLs count as different origins?

An origin combines three parts: scheme, host, and port. If any one of them differs, the browser treats the two URLs as different origins. The path and the query string do not count.

  • https://app.example.com and http://app.example.com differ, because the scheme changes.
  • https://app.example.com and https://api.example.com differ, because the host changes.
  • https://example.com and https://example.com:8443 differ, because the port changes.
  • https://example.com/a and https://example.com/b share one origin.

For example, during development your front end runs on one port and your API on another. Even on the same machine, those are different origins. Therefore, CORS applies.

Also remember that localhost and 127.0.0.1 count as different hosts. If you allow one in the header but call from the other, you get the error.

Can you turn off a CORS error in the browser or client?

No, the correct and lasting fix does not live in the client. The server makes the CORS decision through headers, and no fetch option can override it. If the response header is missing, the browser still withholds the response.

Many posts suggest browser extensions or launch flags that switch off web security. We do not recommend them. They only work on your own machine, they do not fix the problem for your users, and they leave your browser open to real attacks.

The fetch no-cors mode is not a fix either. Instead, the request goes out, but the response becomes opaque, so your code cannot read it. So the error goes quiet, yet the data stays out of reach.

In short, you fix the problem in one of three places: the API server, the reverse proxy in front of it, or a proxy you control during development. We cover all three below.

What are simple requests and preflight requests?

The browser sends some requests directly. We call them simple requests. For the others, it first sends an OPTIONS request, called a preflight, to ask the server for permission. If the answer is no, the browser never sends the real request.

A simple request uses GET, HEAD, or POST and only safe headers. For POST, the content type must be form data or plain text. The MDN CORS guide lists the exact rules.

In practice, these cases trigger a preflight:

  • A POST request with the application/json content type.
  • Methods such as PUT, PATCH, or DELETE.
  • Custom headers such as Authorization.

So that explains the common complaint that GET works but POST fails. Usually the preflight failed, not the POST itself.

The preflight carries no body, and your own code never sees it. The browser creates it automatically. So if your app has no OPTIONS handler, the request meets an unexpected answer.

Which CORS response headers do you need?

The server sends these headers with its response. Each one has a different job, so keep them separate in your mind.

  • Access-Control-Allow-Origin names the origin that may read the response. It holds one origin or a wildcard.
  • Access-Control-Allow-Methods lists the allowed methods in a preflight answer.
  • Access-Control-Allow-Headers lists the request headers that the real request may use.
  • Access-Control-Allow-Credentials allows requests with cookies or credentials. Its only valid value is true.
  • Vary: Origin tells caches that the answer changes per origin.

For many APIs, this short set on the preflight answer is enough:

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Vary: Origin

If your front end must read custom response headers, also use Access-Control-Expose-Headers. Header names are case insensitive, but values are not. Also keep the origin in lowercase. See the Access-Control-Allow-Origin reference for details.

Why can you not use a wildcard (*) with credentials?

When a request carries cookies, HTTP authentication, or client certificates, the browser rejects Access-Control-Allow-Origin: *. It demands one explicit origin instead.

If you use credentials: "include" in fetch, you need all three of these together:

  1. The response names one explicit origin in Access-Control-Allow-Origin.
  2. The response contains Access-Control-Allow-Credentials: true.
  3. A preflight answer also lists explicit methods and headers, not wildcards.

Many teams want to support several origins here. Because of that, they copy the incoming Origin value into the response. That works, however it is risky. Compare the value with a known allow list before you echo it back.

For the session and token side of this topic, our guide on what a JWT is helps.

Why does the preflight (OPTIONS) request fail?

A failing preflight is the most common cause behind the complaint that GET works but POST fails. Your server may not recognize OPTIONS, or it may push that request through an authentication layer.

For this reason, check these causes in order, from the most likely to the least likely:

  1. The server answers OPTIONS with 404 or 405. Add the method to your route list.
  2. An authentication middleware rejects the preflight because it carries no Authorization header. The browser never sends credentials in a preflight, so answer OPTIONS before you authenticate.
  3. The preflight status is not a success status (2xx).
  4. Access-Control-Allow-Headers misses a header that your request uses.
  5. The preflight lands on a redirect. Browsers do not follow redirects on a preflight.

In the Network tab, the OPTIONS request shows up as its own row. Read that row first, including its status code and response headers. This check takes seconds, so it often saves hours.

For example, an auth middleware that wraps every route returns 401 for OPTIONS. The browser then shows a CORS error, but the real cause is the middleware order.

What are the most common CORS mistakes?

In the field, we see small typing differences more often than anything else. The browser compares values exactly, so it has no tolerance.

  • Wrong origin: the header says https://example.com, but the page calls from https://www.example.com.
  • Trailing slash: you write https://app.example.com/ in the header, while an origin has no trailing slash.
  • http versus https: development uses http, production uses https, and your allow list covers only one.
  • Missing port: in local development, the port belongs to the origin.
  • Duplicate header: both the app and the reverse proxy add the header, and the browser rejects the double value.
  • Several origins in one value: you write two addresses separated by a comma, but the header accepts only one origin.

You catch all of these by placing the response headers next to the address bar in the Network tab.

Notice that none of these mistakes leaves a trace on the server. The server stays silent, and only the browser complains. Therefore, verify the header value by hand for every new environment.

Can a redirect cause a CORS error?

Yes. If your API address returns a redirect, for example from http to https or from a path without a trailing slash to one with it, the CORS check can break. A preflight request never follows a redirect.

Here is a typical example scenario. The front end calls a path without a trailing slash. Then the server answers with a 301 redirect to the slash version. Because that redirect response carries no CORS header, the browser reports an error.

The fix is simple: call the final address directly. That way no redirect sits in the middle, and all headers arrive in a single response.

To see redirect chains, use our free redirect checker. Paste the address and see where it goes, step by step.

Why does the CORS header disappear on 4xx and 5xx responses?

Many frameworks add CORS headers only to successful responses. When the server returns 401, 404, or 500, the middleware may not run, so the header is missing. The browser then shows a CORS error instead of the real one.

That sends you in the wrong direction. You see a CORS warning in the console, yet the real problem is a server error. For instance, authentication failed and the server returned 401.

To diagnose it properly, test the request outside the browser with a short command:

curl -i -X OPTIONS https://api.example.com/orders \
  -H "Origin: https://app.example.com" \
  -H "Access-Control-Request-Method: POST"

Then read the status code and the headers. If the status is 5xx, fix the server error first, because the CORS symptom is secondary. For the general logic of server errors, see our HTTP 500 guide.

How do you read a CORS diagnosis table by error type?

Browsers word their messages differently and change them over time. So the table below shows the meaning of similar warnings, not exact text. For exact wording, check the MDN CORS errors reference.

Symptom (similar warning)Likely causeFix
Permission header missing from the responseThe server sends no Access-Control-Allow-OriginAdd the header in the API or reverse proxy layer
Header value does not match the originWrong host, port, scheme, or trailing slashMatch the value to the address bar origin exactly
Wildcard not allowed with credentialsA credentialed request meets *Use an explicit origin and add Allow-Credentials: true
Preflight did not return a success statusOPTIONS returns 401, 404, 405, or 5xxAnswer OPTIONS with 2xx before authentication
Request header not allowedThe header is missing from Allow-HeadersAdd the header your request uses
Redirect during preflightThe request address returns 301 or 302Call the final address directly
Multiple values in the headerTwo layers add the headerAdd the header in one place only

When you use the table, read the console text first and the Network response headers second. Together they reveal the cause almost every time.

How do you work around a CORS error in development with a proxy?

If your dev server has a proxy feature, this is the cleanest route. The front end calls its own origin, and the dev server forwards the request to the API. From the browser's view, the call is same-origin, so CORS never applies.

The big advantage is that you never weaken browser security. It also resembles the production setup, so fewer surprises appear later. Most modern dev tools let you define a path-based proxy with a few lines of settings. The setting name differs per tool, so check your tool's official documentation.

However, this solution is for development only. For production, pick one of two paths:

  • Serve the API behind the same origin as the front end, with a reverse proxy that routes by path.
  • Keep the API on a separate host and write the CORS headers correctly.

The first option also removes most CORS needs. We explain the idea in our Nginx reverse proxy guide.

A proxy also reduces cookie trouble. Because the request goes to the same origin, cookies travel normally. So many teams pick this route during development.

Where do you add CORS headers behind a reverse proxy or CDN?

Manage the headers in one place only. Decide once whether the app, the reverse proxy, or the CDN adds them, and switch the others off. Otherwise you hit the duplicate header problem.

Adding them in application code lets you version the rules with the code. Adding them in the reverse proxy gives you one setting for all services. If a CDN caches responses, keep Vary: Origin in place. Without it, a response for one origin can reach another.

Here is an example scenario. A team adds the header in the app and also in the reverse proxy. The response shows Access-Control-Allow-Origin twice, and the browser rejects it. The fix, then, is to remove one of them.

Also watch for a common trap in hosting dashboards. A ready-made CORS option may exist at the CDN or hosting level while your app adds its own header. Read the raw response headers to see which layer wrote them.

Configuration syntax differs per server, so read the official documentation and test the change in a staging environment first.

How do you diagnose a CORS error with browser developer tools?

The console tells you what happened, and the Network tab shows why. Use both together.

  1. Read the console message and note which header is missing or wrong.
  2. Open the Network tab, select the failed request, and read the response headers.
  3. Find the Origin request header. That is the origin the server saw.
  4. Compare it with Access-Control-Allow-Origin in the response.
  5. For a preflight, inspect the OPTIONS row in the same way.

If you see no error but the response looks empty, you may be looking at a stale cached response. Disable the cache and try again.

If you opened the page from the file system, the origin is "null", and many servers reject it. Use a small local server instead.

Do cookies and SameSite settings get mixed up with CORS?

Yes, often. Both can produce a "credentials are not sent" symptom, yet the causes differ. CORS decides whether your code may read the response. The cookie attributes and request options decide whether the cookie travels with the request.

Check in this order. First, make sure the request enables the credentials option. Then verify that the server sends Access-Control-Allow-Credentials: true. Finally, check that the cookie's SameSite and Secure attributes suit cross-site requests.

So if the cookie does not travel, do not stay stuck on the CORS text. Look at the request in the Network tab and see whether it carries a Cookie header. If not, the problem sits on the cookie side.

Exact behavior can differ between browser versions. Check current rules in the MDN CORS guide and in your browser documentation.

Does a CORS error look different in fetch, XMLHttpRequest, and axios?

No, the rule is the same. Only the look of the error changes. Fetch usually rejects with a vague network error, and the detail appears only in the console. With XMLHttpRequest or axios, you typically see a generic "Network Error" message in the error object.

So your catch block cannot tell you the cause. JavaScript cannot read CORS details, because the browser hides them from the page for security reasons. The console and the Network tab remain your best sources.

Here is a practical tip. Before you show an error to the user, check whether a status code arrived at all. If none arrived, you likely face CORS or a network problem. If one did, the issue sits in the application layer.

The CORS rule does not change between REST and GraphQL either. For the difference between the two styles, read our guide on GraphQL versus REST.

Does the browser cache a preflight, and why do changes not show up right away?

Yes, because browsers may cache a preflight result for a while. The server suggests a duration with Access-Control-Max-Age, and each browser applies its own upper limit. Check the documentation for the current limits.

This also causes a side effect. You fix the header on the server, but the browser keeps using the old preflight result. So you think the fix failed.

First, disable the cache in developer tools and hard reload the page. Then repeat the request in a private window. If the result changes, then the cache was the cause.

In production, avoid very long cache durations. A wrong setting then stays in your users' browsers until it expires.

Example scenario: how does diagnosis go when the front end and API use different hosts?

This is an example scenario, not a real client case. The front end runs on https://app.example.com and the API on https://api.example.com. Also, the login page loads data with GET, but the sign-up form fails on POST.

  1. First, the console warns that the preflight failed.
  2. Then the Network tab shows the OPTIONS row with status 401.
  3. The API authentication layer tries to authenticate OPTIONS too.
  4. You reorder the middleware so OPTIONS gets a 2xx answer before authentication.
  5. You add an Access-Control-Allow-Origin header that names the origin explicitly.
  6. Finally, you retry the sign-up form.

In this example, the CORS setting was not the problem. The middleware order was. So writing a header alone is not enough; you must understand which layer sees the request first.

How do you prevent a CORS error for good?

A lasting fix moves the CORS setup from hard-coded values into configuration. That way development, staging, and production each get their own allow list. This checklist helps:

  • Keep allowed origins in a list and define one per environment.
  • Write the incoming Origin into the response only when it appears in the list.
  • Answer OPTIONS before authentication.
  • Add CORS headers to error responses too.
  • Keep Vary: Origin on every caching layer.
  • Generate the header in one layer only.
  • Run an automated smoke test after each deployment to verify the preflight.

Also add an integration test if the error keeps coming back. The test sends an OPTIONS request from a different origin and checks the headers. Then you catch the next regression before it reaches production.

Is CORS a security measure or just a roadblock?

CORS is not an authorization system. It does not block requests from reaching your server. It only controls whether the browser hands the response to page code. An attacker can send the same request from outside a browser with ease.

So a CORS setting never replaces API security. You still need authentication, authorization, and input validation. For common web risks, see our OWASP Top 10 guide.

On the other hand, a policy that is too broad creates real risk. Allowing every origin and enabling credentials can let other sites read data on behalf of your user. Keep the allow list narrow.

If you are new to the concept, our what is an API guide covers the basics.

How can Talha Aslan and team help with this?

Our team works on web apps, API integrations, and release infrastructure. CORS problems usually appear when different teams write the front end and the server, or when a project moves to a new domain.

If your project spans several hosts, a reverse proxy, and a CDN, diagnosing it together is faster. Depending on your scope, you can request a quote for our custom software development service.

This article is not legal or security advice. For tool-specific details, always read the official documentation of the tool you use.

Frequently Asked Questions

Is a CORS error a front-end or back-end problem?
In practice, you fix a CORS error on the back end, because the server decides through response headers. The browser only enforces that decision, and front-end code cannot change the header. During development, a front-end proxy setting is a clean workaround, but production needs the correct server configuration.
Why does my request work in Postman but fail in the browser?
Postman is not a browser, so it does not enforce the same-origin policy. The request reaches the server, and the response is shown directly. The browser checks CORS headers before it gives the response to your code. So a working Postman call does not prove that the browser call will work.
Is it safe to set Access-Control-Allow-Origin to *?
A wildcard is acceptable for public data that carries no credentials. However, on endpoints that return user-specific data or use cookies, a wildcard both fails and creates risk. In those cases, list the allowed origins explicitly and write the matching one into the response in a controlled way.
Why do I get a CORS error only on POST requests?
A POST request with a JSON body triggers a preflight, while many GET requests count as simple requests and skip it. So if your server does not answer OPTIONS correctly, only POST fails. Make sure OPTIONS returns a 2xx status with the permission headers, then retry the request.
Is it right to fix a CORS error with a browser extension?
No. An extension or launch flag that disables security only hides the error in your own browser. Your users still see the problem, and you expose your browser to unnecessary risk. The right fix is to correct the response headers on the server or to use a local proxy during development.
I changed my CORS settings but the error remains. Why?
First, confirm that the change reached production and applies to the right layer. Next, clear caches, because a CDN or the browser may hold the old response or preflight. Finally, read the response headers in the Network tab and verify that the value matches the origin exactly, then retry in a private window.
  • cors error
  • access-control-allow-origin
  • preflight request
  • same-origin policy
  • api
  • web development
Share:
Talha Aslan

Google Partner digital marketing expert. Hands-on with SEO, Google Ads, web design and e-commerce projects since 2012; every post here comes from that experience.

Next project

Get a quote for your project.

Your brief goes straight to Talha Aslan and team: strategy led by Talha, delivery by an experienced team. We reply the same day and send the scope, timeline and price as a written quote within 1 business day.