Getting this error in your React and/or Express app?
No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
You’ve run afoul of the Same Origin Policy – it says that every AJAX request must match the exact host, protocol, and port of your site. Things that might cause this:
- Hitting a server from a locally-served file (a request from
file:///YourApp/index.html
tohttp://api.awesome.com
) - Hitting an external API (a request from
http://yourapp.com
tohttp://api.awesome.com
). - Hitting an internal API (a request from
http://yourapp.com
tohttp://api.yourapp.com
). - Hitting a different port on the same host (webapp is on
http://localhost:3000
, API ishttp://localhost:4000
) - Requesting over
http
fromhttps
or vice-versa (requestinghttps://yourapp.com
fromhttp://yourapp.com
)
To be clear, this is not a React error. It afflicts all web apps equally, and most of the fixes we’ll look at below are actually modifying the server or the browser.
If you’re new to React, you might like my complete React tutorial. It covers all the bases (what props are, how JSX works, how to useState and fetch data with useEffect) to get you going quickly.
How to fix it
Here are a few ways to solve this problem.
Best: CORS header (requires server changes)
CORS (Cross-Origin Resource Sharing) is a way for the server to say “I will accept your request, even though you came from a different origin.” This requires cooperation from the server – so if you can’t modify the server (e.g. if you’re using an external API), this approach won’t work.
Modify the server to add the header Access-Control-Allow-Origin: *
to enable cross-origin requests from anywhere (or specify a domain instead of *
). This should solve your problem.
How to Enable CORS on Express
If you’re using Express, the easiest way to enable CORS is with the cors library.
You just need to install it in your Express project with npm install cors
, then require
it and add it as a middleware:
var express = require('express');
// Import the library:
var cors = require('cors');
var app = express();
// Then use it before your routes are set up:
app.use(cors());
Two important things to know here:
- Express runs its middleware in order. So make sure this
app.use
code runs before you set up your routes. - By default, the
cors
library will allow requests from any origin. This can open you up to security problems and abuse.
For production use, it’s best not to allow all origins. Instead, create a whitelist of allowed domains, and check each request against the whitelist. Here’s how:
// Set up a whitelist and check against it:
var whitelist = ['http://example1.com', 'http://example2.com']
var corsOptions = {
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
// Then pass them to cors:
app.use(cors(corsOptions));
2nd choice: Proxy Server
If you can’t modify the server, you can run your own proxy. And this proxy can return the Access-Control-Allow-Origin
header if it’s not at the Same Origin as your page.
Instead of sending API requests to some remote server, you’ll make requests to your proxy, which will forward them to the remote server. Here are a few proxy options.
3rd choice: JSONP (requires server support)
If CORS and the proxy server don’t work for you, JSONP may help. You essentially make a GET request with a callback
parameter:
(get) http://api.example.com/endpoint?callback=foo
The server will wrap the JSON reply in a function call to your callback, where you can handle it:
foo({"your": "json", here: true})
There are some downsides, notably that JSONP only supports GET requests and that you still need a cooperative server.
Dev-Only: Disable Same Origin
If this is only for development or learning purposes, the easiest thing to do is to disable the Same Origin Policy in your browser. Be aware that if you do this, you’re opening your browser up to security risks. Follow these instructions:
This is more of a last resort. Modifying the server to support CORS or running a proxy are the best approaches.
Armed and Dangerous
You’re all set now to tackle any Access-Control-Allow-Origin
errors that come your way!