333

I am stuck with this CORS problem, even though I set the server (nginx/node.js) with the appropriate headers.

I can see in Chrome Network pane -> Response Headers:

Access-Control-Allow-Origin:http://localhost

which should do the trick.

Here's the code that I now use to test:

var xhr = new XMLHttpRequest();
xhr.onload = function() {
   console.log('xhr loaded');
};
xhr.open('GET', 'http://stackoverflow.com/');
xhr.send();

I get

XMLHttpRequest cannot load http://stackoverflow.com/. Origin http://localhost is not allowed by Access-Control-Allow-Origin.

I suspect it's a problem in the client script and not server configuration...

7
  • 68
    No, stackoverflow.com needs to set this header, not you. :x. What would be the point of same origin policy otherwise. Commented Jun 4, 2012 at 14:44
  • 5
    Try accessing the server you've set up not stack overflow. ;) Commented Jun 4, 2012 at 15:10
  • DOH! Is there a way to tell chrome (or other browser), to get the resource even if the header is missing when my origin is localhost? Commented Jun 4, 2012 at 19:12
  • Run your codes in Chrome(20.0.1132.57, Windows 7), works fine. Commented Sep 16, 2012 at 16:13
  • 2
    If you're using localhost with a port this answer worked for me serverfault.com/a/673551/238261. Commented Sep 23, 2016 at 16:03

13 Answers 13

336

Chrome does not support localhost for CORS requests (a bug opened in 2010, marked WontFix in 2014).

To get around this you can use a domain like localho.st (which points at 127.0.0.1 just like localhost) or start chrome with the --disable-web-security flag (assuming you're just testing).

Sign up to request clarification or add additional context in comments.

17 Comments

@greensuisse - it's not posting to localhost. It's posting from localhost that is the problem.
That bug is invalid (and has been marked as such - crbug.com/67743#c17). Esailija's comment is correct, adding these headers to localhost will not magically give you access to all other sites. It's the remote site that needs to be served with these headers.
Other option: edit your hosts file so that local.[mysite].com points to 127.0.0.1, then make your CORS file allow *.[mysite].com
I faced the same problem with FireFox. I could only make it on Edge! Nice post though, fantastic! :)
see @Molomby's comment below "Chrome 100% does support cross-origin requests to and from localhost..."
|
89

Per @Beau's answer, Chrome does not support localhost CORS requests, and there is unlikely any change in this direction.

I use the Allow-Control-Allow-Origin: * Chrome Extension to go around this issue. The extension will add the necessary HTTP Headers for CORS:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: "GET, PUT, POST, DELETE, HEAD, OPTIONS"
Access-Control-Expose-Headers: <you can add values here>

The source code is published on Github.

Note that the extension filter all URLs by default. This may break some websites (for example: Dropbox). I have changed it to filter only localhost URLs with the following URL filter

*://localhost:*/*

9 Comments

If you read the issue @beau links to you'll see Chrome 100% does support cross-origin requests to and from localhost. The issue was closed in 2014 because it couldn't be reproduced. The rest of the noise in that thread is people with misconfigured non-origin servers (as with the original question here).
Worked like charm for me on chrome
This Extension doesn't work with Access-Control-Allow-Credentials: true because it sets Access-Control-Allow-Origin to * and having both true and * is blocked by browsers. If using credentials true, you must use non-wildcard origin. I recommend Moesif Origins and CORS Changer Extension which allows you to change headers however you want.
@Chiwda you can find the above-mentioned and loads more here: addons.mozilla.org/en-GB/firefox/search/…
|
47

None of the extensions worked for me, so I installed a simple local proxy. In my case https://www.npmjs.com/package/local-cors-proxy It is a 2-minute setup:

(from their site)

npm install -g local-cors-proxy

API endpoint that we want to request that has CORS issues: https://www.yourdomain.ie/movies/list

Start Proxy: lcp --proxyUrl https://www.yourdomain.ie

Then in your client code, new API endpoint: http://localhost:8010/proxy/movies/list

Worked like a charm for me: your app calls the proxy, who calls the server. Zero CORS problems.

2 Comments

Worked for me (http server at http ://localhost:81/sse): lcp --proxyUrl http ://localhost:81/sse. In the code change to http ://localhost:8010/proxy/sse (as given to you on the command line by lcp.
I use two urls to bypass the Stackoverflow problem, one for remote and one for local: var url ='http://api.stackexchange.com/';if (location.host == 'localhost') url ='http://localhost:8010/proxy/'
24

The real problem is that if we set -Allow- for all request (OPTIONS & POST), Chrome will cancel it. The following code works for me with POST to LocalHost with Chrome

<?php
if (isset($_SERVER['HTTP_ORIGIN'])) {
    //header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}");
    header("Access-Control-Allow-Origin: *");
    header('Access-Control-Allow-Credentials: true');    
    header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); 
}   
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']))
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");         
    if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']))
        header("Access-Control-Allow-Headers:{$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}");

    exit(0);
} 
?>

1 Comment

OP is using nginx/node.js. Not PHP
18

Chrome will make requests with CORS from a localhost origin just fine. This isn't a problem with Chrome.

The reason you can't load http://stackoverflow.com is that the Access-Control-Allow-Origin headers weren't allowing your localhost origin.

2 Comments

So SO does not want api access from localhost. Is there a reason why?
This situation seems to prevent development/testing from localhost, and it isn't initially obvious that is the problem.
9

Agreed! CORS should be enabled on the server-side to resolve the issue ground up. However...

For me the case was:

I desperately wanted to test my front-end(React/Angular/VUE) code locally with the REST API provided by the client with no access to the server config.

Just for testing

After trying all the steps above that didn't work I was forced to disable web security and site isolation trials on chrome along with specifying the user data directory(tried skipping this, didn't work).

For Windows

cd C:\Program Files\Google\Chrome\Application

Disable web security and site isolation trials

chrome.exe  --disable-site-isolation-trials --disable-web-security --user-data-dir="PATH_TO_PROJECT_DIRECTORY"

This finally worked! Hope this helps!

4 Comments

Thanks, finally something that works! I just needed to enter the last line in Run. PS: chrome added like 800 files and numerous new folder to my directory, but it's good for testing. Still looking for a solution with only changing the appropriate header.
I have been there too. Glad it helped. Please let us know as an answer when you find exactly what you are looking for this issue. It may help others.
I made it work, I installed the cors package with "npm install cors" the thing is I put the cors-code on a line after I started the server, it had to be before. Pretty stupid mistake....
For linux: google-chrome --disable-web-security --disable-site-isolation-trials --user-data-dir="/tmp/google-temp/" /tmp/google-temp/ is your folder with new google profile data Add your domain to /etc/hosts. That worked for me. I had CORS from outside server despite setting domain there.
8

Chrome does allow CORS on localhost, I made it work with AWS API gateway/lambda. Viewing the network tab in the developer tools when sending http requests was very helpful. My problem was that my lambda function was not dealing with the preflight OPTIONS request, only POST and GET. I solved the issue by accepting OPTIONS requests and making sure to return the following headers from my API:

  • Access-Control-Allow-Origin: '*' (or website domain)
  • Access-Control-Allow-Methods: 'POST, GET, OPTIONS'
    • this is the preflight response telling chrome that we can now send a POST/GET request
  • Access-Control-Allow-Headers: 'Content-Type'
    • not sure if this is necessary, but it tells chrome that the request can include a Content-Type header

The important thing to note is that the browser sends 2 sets of headers.

  1. OPTIONS headers which includes
    • access-control-request-method: 'POST' (or whatever http method you are requesting)
    • origin: 'http://localhost:3000' (website domain)
    • referer: 'http://localhost:3000/' (I believe this is the full website path)
    • sec-fetch-mode: 'cors'
    • sec-fetch-site: 'cross-site'

if the response to request 1 is 200 code and the response header contains: 'access-control-allow-methods': 'POST' (or whatever the access-control-request-method was in the request),

  1. Actual request, for example: POST headers which includes
    • content-type: 'application/json'
    • origin: same as above
    • referer: same as above

There are more headers but I think these were the most important.

Comments

6

Quick and dirty Chrome extension fix:

Moesif Orign & CORS Changer

However, Chrome does support cross-origin requests from localhost. Make sure to add a header for Access-Control-Allow-Origin for localhost.

1 Comment

i added this extension to my Opera and now its f'd up. i can never tell when its on and off so i use firefox for work. and opera for development. google suit doesnt like it, and other things dont either.
6

I think my solution to this might be the simplest. On my development machine, I added a fake domain in my hosts file similar to http://myfakedomain.notarealtld and set it to 127.0.0.1. Then I changed my server's CORS configuration (in my case an S3 bucket) to allow that domain. That way I can use Chrome on localhost and it works great.

Make sure your CORS configuration takes into account the entire hostname with port, ie. http://myfakedomain.notarealtld:3000

You can modify your hosts file easily on Linux, Mac, and Windows.

Comments

1

Most of the answers that say chrome does not support localhost CORS are outdated or incorrect.

Remember CORS is the browser trying to stop CROSS ORIGIN RESOURCE SHARING.

If you control the server side then you can explictly allow the client by protocol and host and port.

For example,

res.status(200).header('Access-Control-Allow-Origin','http://localhost:5000').send(parsedDataClean);

Or use

res.status(200).header('Access-Control-Allow-Origin','*').send(parsedDataClean);

The wildcard is only for testing and should not be used in production in general.

Comments

0

I decided not to touch headers and make a redirect on the server side instead and it woks like a charm.

The example below is for the current version of Angular (currently 9) and probably any other framework using webpacks DevServer. But I think the same principle will work on other backends.

So I use the following configuration in the file proxy.conf.json:

{
  "/api": {
    "target": "http://localhost:3000",
    "pathRewrite": {"^/api" : ""},
   "secure": false
 }
}

In case of Angular I serve with that configuration:

$ ng serve -o --proxy-config=proxy.conf.json

I prefer to use the proxy in the serve command, but you may also put this configuration to angular.json like this:

"architect": {
  "serve": {
    "builder": "@angular-devkit/build-angular:dev-server",
    "options": {
      "browserTarget": "your-application-name:build",
      "proxyConfig": "src/proxy.conf.json"
    },

See also:

https://www.techiediaries.com/fix-cors-with-angular-cli-proxy-configuration/

https://webpack.js.org/configuration/dev-server/#devserverproxy

Comments

0

As many others have posted before, Chrome supports CORS from localhost and the issue you are seeing is related to some missing response headers from your server.

In my case I saw this error even when I correctly configured my server include localhost:3030 in the list of allowed origins.

For context I serve the files from a S3 bucket, and I use Sentry for error tracking.

I copied the failed request from Chrome's DevTools network tab as a curl request, and I saw this response:

CORSResponse: This CORS request is not allowed. This is usually because the evalution of Origin, request method / Access-Control-Request-Method or Access-Control-Request-Headers are not whitelisted by the resource's CORS spec.

Then I noticed these are the CORS headers my browser was sending:

Access-Control-Allow-Origin: http://localhost:3030
Access-Control-Allow-Methods: PUT, GET
Access-Control-Allow-Headers: baggage, sentry-trace
Access-Control-Expose-Headers: Access-Control-Allow-Origin

I was not familiar with the baggage, sentry-trace values. I quickly found in the Sentry docs that I had to edit my CORS configuration to allow these headers. Now the requests are succeeding.

Comments

-7

The solution is to install an extension that lifts the block that Chrome does, for example:

Access Control-Allow-Origin - Unblock (https://add0n.com/access-control.html?version=0.1.5&type=install).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.