CORS Error Messages
The error messages listed below all come from Chrome. For more information about CORS error messages in Firefox see developer.mozilla.org.
The first line of a CORS error in Chrome will typically look something like this:
Access to XMLHttpRequest at 'http://localhost:3000/api' from origin 'http://localhost:8080' has been blocked by CORS policy:
The exact form of the message will depend on the request you’re attempting.
Requests initiated using fetch
will start Access to fetch
instead of
Access to XMLHttpRequest
. The URL http://localhost:3000/api
will be the URL of the
cross-origin resource you tried to access. The origin, http://localhost:8080
, will be the origin of the
current page. Usually that’ll be the first part of the URL in your browser’s address bar.
If the request you’re attempting uses HTTP redirects then you may get a longer version of this opening line:
Access to XMLHttpRequest at 'http://localhost:3000/new-api' (redirected from 'http://localhost:3000/old-api') from origin 'http://localhost:8080' has been blocked by CORS policy:
When using redirects, all the requests must successfully pass the CORS checks. The error message indicates the initial URL as well as the URL that failed. The initial request, and any intermediate redirects, must have passed the CORS checks or the final request wouldn’t have even been attempted.
Generally it is the next part of the error message that reveals why the request failed the CORS check. Those messages are listed below.
If you want to see how the Chrome error messages are built take a look at the source code (not as scary as it sounds) at cs.chromium.org.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
This error indicates that the server response did not include the header Access-Control-Allow-Origin
.
This is very similar to another error message. That error relates to
the preflight OPTIONS
request, whereas this error specifically concerns the main request.
If you’re new to CORS see What is CORS? for more information.
If you’ve attempted to configure the CORS headers but you’re still seeing this message then try I’ve configured my server to include CORS headers but they still aren’t showing up. Why?.
If you are making the request using the fetch
API then you’ll also see the following text at the end of the error
message:
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.
The 'Access-Control-Allow-Origin' header has a value 'http://example.com' that is not equal to the supplied origin.
This error indicates that the server response did include the header Access-Control-Allow-Origin
but it was set to the
wrong value. For a request to succeed Access-Control-Allow-Origin
must either be *
or an exact match for the
Origin
request header.
If you are making the request using the fetch
API then you’ll also see the following text at the end of the error
message:
Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.
The 'Access-Control-Allow-Origin' header contains multiple values 'http://example.com, http://localhost:8080', but only one is allowed.
Many HTTP headers support multiple values separated by commas. Access-Control-Allow-Origin
does not. It must either be
the special value *
or an exact match for the Origin
request header.
Usually the cause of this problem is that the header value is being set twice. If any header appears twice on the response then the HTTP specification says it should be treated as equivalent to a single header that has the values separated using a comma followed by a space. Browsers, proxies and some servers will often combined multiple headers in this way.
So, for example, you would see the error above if the server returned the following headers:
Access-Control-Allow-Origin: http://example.com
Access-Control-Allow-Origin: http://localhost:8080
When these headers reach the browser they will be combined to form:
Access-Control-Allow-Origin: http://example.com, http://localhost:8080
The underlying cause for this problem may be that the CORS headers are being added in multiple places. For example, it may be that a CORS plugin has been added twice. Or perhaps an intermediate web server is also configured to add the CORS headers.
A particularly common version of this message is:
The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.
It is very unlikely that the header was actually set to *, *
. Much more likely is that it has been added twice:
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: *
If you are making the request using the fetch
API then you’ll also see the following text at the end of the error
message:
Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.
The 'Access-Control-Allow-Origin' header contains the invalid value 'xyz'.
This error indicates that the server response did include the header Access-Control-Allow-Origin
but it contained an
invalid value. Here invalid doesn’t just mean that it doesn’t match the requested Origin
but, more than that, it
doesn’t appear to even be a valid origin value. Origin values should parse as valid URIs.
Some examples of values that will give this error:
xyz
example.com
http://example.com:67890
The last example only fails because the port number is too large to be valid.
This message is intended to provide extra feedback to the developer but ultimately it isn’t really a separate case. The
Origin
request header will always be well-formed so if the Access-Control-Allow-Origin
header can’t be parsed it
can’t be a match.
This is very similar to another error message. That error relates to
the preflight OPTIONS
request, whereas this error specifically concerns the main request.
If you are making the request using the fetch
API then you’ll also see the following text at the end of the error
message:
Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.
The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
If the request is made using XMLHttpRequest
, as opposed to fetch
, then there’ll be an extra line at the end of this
error:
The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
This error indicates that the Access-Control-Allow-Origin
response header had the value *
. Using a *
wildcard is
not allowed for requests that use withCredentials
.
In many cases withCredentials
isn’t required and can simply be removed. If you aren’t using cookies then you probably
don’t need it. For more information see What is withCredentials? How do I enable it?.
If you do need withCredentials
then you’ll have to change the server so that it doesn’t return *
for
Access-Control-Allow-Origin
. Instead the server should check that the Origin
request header contains an allowed
origin before echoing that origin value back in Access-Control-Allow-Origin
.
If you want to understand why this restriction on using *
exists then see What are the security implications of CORS?. By
extension it’s important that the server does not simply echo back all origins: only trusted origins should be allowed.
There are browser extensions that automatically set the Access-Control-Allow-Origin
header to *
, overriding any
value set by the server. These tools can trigger the error message above, even if the server is returning all of the
correct headers.
The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
If the request is made using XMLHttpRequest
, as opposed to fetch
, then there’ll be an extra line at the end of this
error:
The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
For requests that use withCredentials
the server response must include the header Access-Control-Allow-Credentials
set to the value true
.
If the message reports a value of ''
then that usually means the header is missing altogether rather than being
returned with an explicit empty value.
If the error message indicates that the current value is 'true, true'
then that suggests that the header is being
returned twice.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This error indicates that the preflight OPTIONS
request failed because the server did not include the response header
Access-Control-Allow-Origin
.
This is very similar to another error message. That error relates to
the main request, whereas this error specifically concerns the preflight OPTIONS
request.
If you’re new to CORS see What is CORS? for more information.
If you are unclear what a preflight OPTIONS
request is then see What is a preflight request?.
If you’ve attempted to configure the CORS headers but you’re still seeing this message then try I’ve configured my server to include CORS headers but they still aren’t showing up. Why?.
If you are making the request using the fetch
API then you’ll also see the following text at the end of the error
message:
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
For more information about opaque responses see What is an opaque response?. Using an opaque response will suppress the error message but it won’t allow you to access the response details.
Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header has a value 'http://example.com' that is not equal to the supplied origin.
This error specifically refers to the preflight OPTIONS
request but is otherwise identical to
an earlier error message.
If you are unclear what a preflight OPTIONS
request is then see What is a preflight request?.
Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values 'http://example.com, http://localhost:8080', but only one is allowed.
This error specifically refers to the preflight OPTIONS
request but is otherwise identical to
an earlier error message.
If you are unclear what a preflight OPTIONS
request is then see What is a preflight request?.
Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains the invalid value 'xyz'.
This error specifically refers to the preflight OPTIONS
request but is otherwise identical to
an earlier error message.
If you are unclear what a preflight OPTIONS
request is then see What is a preflight request?.
Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.
If the request is made using XMLHttpRequest
, as opposed to fetch
, then there’ll be an extra line at the end of this
error:
The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
This error specifically refers to the preflight OPTIONS
request but is otherwise identical to
an earlier error message.
If you are unclear what a preflight OPTIONS
request is then see What is a preflight request?.
Method PUT is not allowed by Access-Control-Allow-Methods in preflight response.
Any cross-origin request that uses a method other than GET
, HEAD
or POST
will trigger a preflight request. The
error message above refers to a PUT
request but an equivalent message would be shown for other methods, such as
DELETE
.
The browser will automatically include a request header in the preflight request called Access-Control-Request-Method
.
The value specifies the method of the original request, e.g. Access-Control-Request-Method: PUT
.
The server is expected to respond with a comma-separated list of acceptable request methods in the response header
Access-Control-Allow-Methods
. If the method in Access-Control-Request-Method
is not included in that list it will
trigger the error above.
Even when using the request methods GET
, HEAD
or POST
a preflight can be triggered if there are custom request
headers. In that case the browser will still include the Access-Control-Request-Method
request header but the
Access-Control-Allow-Methods
response header will be ignored.
A value of *
can also be used as a wildcard in Access-Control-Allow-Methods
. However, this is not allowed when using
withCredentials
and will result in the same error message.
If you are unclear what a preflight OPTIONS
request is then see What is a preflight request?.
Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response.
While the example message above mentions content-type
it could equally reference almost any request header.
When performing a preflight OPTIONS
request the browser will automatically include a request header called
Access-Control-Request-Headers
. Its value will be a comma-separated list of the names of any custom header fields that
have been set on the original request.
When the server responds to the preflight request it should include the response header Access-Control-Allow-Headers
.
This should list the custom header fields that the server is willing to allow.
If any of the custom headers listed in Access-Control-Request-Headers
are not included in
Access-Control-Allow-Headers
then the preflight will fail, leading to the error shown above. The error will name the
first header that was missing, though there may be others.
A value of *
can also be used as a wildcard in Access-Control-Allow-Headers
. However, this is not allowed when using
withCredentials
and will result in the same error message.
Related
Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
If the request is made using XMLHttpRequest
, as opposed to fetch
, then there’ll be an extra line at the end of this
error:
The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
For requests that use withCredentials
the server response to the preflight OPTIONS
request must include the header
Access-Control-Allow-Credentials
set to the value true
. The same header must also be included for the main request,
though omitting it would trigger a different error message.
If you are unclear what a preflight OPTIONS
request is then see What is a preflight request?.
If the message reports a value of ''
then that usually means the header is missing altogether rather than being
returned with an explicit empty value.
If the error message indicates that the current value is 'true, true'
then that suggests that the header is being
returned twice.
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
Quick fix: Make sure you’ve included the http://
or https://
at the start of the request URL.
The first part of a URI, prior to the colon, is known as the scheme. Some examples include:
https://www.google.com -> https
file:///home/user/picture.png -> file
mailto:webmaster@example.com -> mailto
javascript:return false; -> javascript
Cross-origin requests can only be made to URIs with certain schemes, as indicated in the error message. For example,
trying to access a file on the local filesystem using the file
scheme is not allowed.
A common mistake is trying to use a URI of the form localhost:3000/api
. The problem is that it doesn’t include the
http://
or https://
prefix, so localhost
is parsed as ‘the bit before the colon’, i.e. the scheme.
The Network tab of Chrome’s developer tools will not show requests that trigger this error.
Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
For a preflight OPTIONS
request to succeed the response status code must be in the range 200
to 299
. Common
choices are 200
and 204
.
Several status codes in the range 300
to 399
can be used to attempt a redirect in conjunction with the Location
header. This is allowed for the main request but not for the preflight. Attempting a redirect on the preflight will
trigger the error above.
Even if you aren’t intentionally using redirects there are two common ways that they can creep in:
- Redirecting from
http
tohttps
. - Redirecting to add or remove a trailing URL slash. e.g. A server may redirect
http://example.com/api/users
tohttp://example.com/api/users/
or vice-versa.
If you’re unsure why a redirect is occurring then the first step is to check the Location
response header. Often the
new location will only differ from the original location by a single character so you may need to check it very
carefully.
While the server should not be attempting to redirect the preflight OPTIONS
request it is usually trivial to fix in
the client by updating the URL to avoid the redirect altogether.
Related
Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
For a preflight OPTIONS
request to succeed the response status code must be in the range 200
to 299
. Common
choices are 200
and 204
.
Any other status code will cause the preflight check to fail. That includes attempts at authentication using a 401
status code. If you have a server-side authorization layer you’ll need to ensure it doesn’t interfere with preflight
requests.
The best place to start with debugging this error is to check which status code is coming back. There may also be a response body that provides further information.
The other thing to check is the request URL. Specifically check in the developer tools rather than in your code. Make sure the URL really is what you intended. Depending on how the server is configured there are several different status codes you might receive if the URL is wrong.
Attempts to redirect to a different URL will typically show a different error message. See Redirect is not allowed for a preflight request.
Redirect location '' contains a username and password, which is disallowed for cross-origin requests.
An old feature of URLs allows them to include a username and password near the beginning. e.g.:
http://admin:password123@example.com/
The use of this form of authentication is discouraged and support is somewhat limited.
If a server attempts to redirect a CORS request to a URL that contains this form of username and password then the request will fail.
Typically the server will have returned a status code of 301
, 302
, 307
or 308
and the rejected URL will have
been specified in the Location
response header.
You can suggest improvements to this page via GitHub.