How to Debug CORS Issues in React Applications
Fix browser console CORS errors by configuring server headers, checking proxy settings, and verifying network policies in a React app.
React applications frequently encounter Cross-Origin Resource Sharing (CORS) errors when fetching data from a different domain. This guide shows you how to identify the root cause using browser DevTools and apply the correct fix on the server side. You will configure headers and proxy settings to allow your frontend to communicate safely with your backend.
Prerequisites
- A running React application (created with
create-react-appor Vite). - A backend API server running on a different port or domain (e.g., Node.js, Python, or PHP).
- Access to the backend server code to modify configuration files.
- Google Chrome or Firefox browser with Developer Tools enabled.
Step 1: Inspect the Network Request
Open your React application in the browser and trigger the API call that generates the error. Right-click the element in the UI and select Inspect to open Developer Tools. Navigate to the Network tab to see all HTTP requests.
Locate the failed request in the list. It will typically show a status code of 403 or 0 depending on the browser's handling of the blocked request. Click on that specific request to view its details.
Look at the Response Headers section. You will see a line that says Access-Control-Allow-Origin. If this header is missing or does not include http://localhost:3000, the browser blocks the response.
Access-Control-Allow-Origin: http://localhost:5173
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Compare this with a failed request where the header is missing or restricted to localhost only.
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: false
Step 2: Configure the Backend Server
Most CORS errors occur because the backend server does not send the required headers. You must modify your server code to include Access-Control-Allow-Origin. The specific implementation depends on your backend technology.
If you are using a Node.js server with Express, install the cors package and apply it to your routes. Run the following command in your backend directory:
npm install cors
Import the package and create an instance. Pass the allowed origins to the configuration object. Ensure the origin matches the URL of your React app, including the port number.
const cors = require('cors');
const app = express();
const allowedOrigin = 'http://localhost:3000';
const corsOptions = {
origin: allowedOrigin,
credentials: true,
};
app.use(cors(corsOptions));
For a Python Flask application, use the flask-cors extension. Install it via pip:
pip install flask-cors
Import the extension and initialize it with the allowed origin. Do not use a wildcard * if you are sending cookies or credentials, as browsers will block the request in that case.
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app, resources={r"/*": {"origins": "http://localhost:3000"}})
Step 3: Check Proxy Configuration in React
When you run a React app with npm start, the development server often proxies API requests to your local backend. If the backend is on a different port, you must configure the proxy in package.json. Add a proxy field at the root level of the file.
{
"name": "my-react-app",
"version": "0.1.0",
"proxy": "http://localhost:5000",
"dependencies": { ... }
}
Restart your React development server after making this change. The browser will now forward requests starting with /api or the root path to http://localhost:5000. This bypasses the CORS check because the request originates from the same origin.
If you are using Vite, create a file named vite.config.js in the root directory. Export the config object and define the base and server properties to handle cross-origin requests.
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
secure: false,
},
},
},
});
Verify the installation
Open the browser console and run the fetch request again. You should see a 200 OK status and the response body in the console. The Network tab should no longer show a red error icon. The Access-Control-Allow-Origin header must explicitly list your app's origin.
GET http://localhost:5000/users
200 OK
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Credentials: true
If the request succeeds, the CORS issue is resolved. If the status is still 403, check the backend logs for errors related to the CORS middleware.
Troubleshooting
Error: "No 'Access-Control-Allow-Origin' header is present on the requested resource."
This means your backend is not sending the header. Verify that your CORS middleware is initialized before your route handlers. Ensure you are not using a wildcard * if you need to send cookies. Some frameworks require a specific header name with a hyphen; use Access-Control-Allow-Origin exactly.
Error: "Request header field Content-Type is not allowed by Access-Control-Allow-Headers"
Your backend explicitly limits allowed headers. Add Content-Type to the list of allowed headers in your CORS configuration. In Express, include it in the allowedHeaders array.
const corsOptions = {
origin: 'http://localhost:3000',
allowedHeaders: ['Content-Type', 'Authorization'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
};
Error: "Response is preflighted but not allowed"
This occurs when the browser sends an OPTIONS request before the actual fetch. Your backend must handle OPTIONS requests and return the appropriate headers. Ensure your CORS library handles preflight requests automatically.
Error: "Mixed Content: The page at 'https' was loaded over HTTPS, but requested an endpoint using HTTP"
If your React app is served over HTTPS (e.g., via a production build or a secure host), you cannot call an HTTP backend. Change your backend URL to use HTTPS or serve both frontend and backend over the same secure protocol.
Error: "CORS policy blocks access to cross-origin resource"
Check the Access-Control-Allow-Credentials header. If your frontend sends cookies, this header must be set to true. However, you cannot use a wildcard * for the origin when credentials are enabled. You must specify the exact origin.
Debugging with Chrome DevTools
Right-click the failed request in the Network tab and select Copy > Copy as cURL. Paste this command into your terminal. Modify the -H arguments to see what headers the browser expects. Compare this with the headers your server is actually sending. This helps identify mismatches in header names or values.
If you are using a reverse proxy like Nginx, ensure it passes the Origin header to the backend. Configure the add_header directive in your Nginx configuration file to add the necessary CORS headers before proxying the request.
location /api {
proxy_pass http://localhost:5000;
add_header Access-Control-Allow-Origin http://localhost:3000;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
}
Restart your Nginx service after applying these changes. Always test the fix by clearing the browser cache and reloading the page to ensure the browser uses the new headers.