The Error
When you attempt to fetch data from an external API or a backend running on a different port than your React application, you likely encounter this specific error in your browser console:
Access to fetch at 'http://api.example.com' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
This error prevents your application from receiving data, often resulting in a failed network request even if the server actually processed the logic correctly.
Root Cause
CORS (Cross-Origin Resource Sharing) is a security mechanism implemented by browsers to prevent malicious websites from making requests to a different domain than the one that served the web page. In modern web development, your React app usually runs on http://localhost:3000 while your API might be on http://localhost:5000 or http://api.example.com. Because the domains or ports differ, the browser blocks the response unless the server explicitly gives permission.
Step-by-Step Fixes
Solution 1: Fix the Server (The Recommended Way)
The most robust way to solve CORS is to configure the backend server to allow requests from your React app's origin. You must add the Access-Control-Allow-Origin header to the server response.
Node.js / Express Example
Install the cors package:
npm install cors
Then, apply it as middleware in your server.js:
const express = require('express');
const cors = require('cors');
const app = express();
// Allow requests from your specific React dev server
app.use(cors({
origin: 'http://localhost:3000'
}));
app.get('/api/data', (req, res) => {
res.json({ message: 'Success' });
});
app.listen(5000);
Python / FastAPI Example
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Solution 2: Use a Development Proxy (React Side)
If you don't have access to the backend code or want a quick fix for local development, you can use a proxy. This tells the React development server to forward requests to the API server, making the browser think the request is coming from the same origin.
For Create React App (CRA)
Open your package.json and add the proxy field at the bottom:
{
"name": "my-react-app",
"version": "0.1.0",
"dependencies": { ... },
"proxy": "http://localhost:5000"
}
After adding this, change your fetch calls from absolute URLs to relative paths:
// Change this:
fetch('http://localhost:5000/api/users')
// To this:
fetch('/api/users')
Note: You must restart your React development server for this change to take effect.
For Vite Projects
In vite.config.ts or vite.config.js, configure the server proxy:
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:5000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});
Solution 3: Setup a Manual Proxy Middleware
If you need more control (e.g., proxying to multiple backends), use http-proxy-middleware.
- Install the package:
npm install http-proxy-middleware - Create a file named
src/setupProxy.js(No need to import it anywhere, CRA finds it automatically).
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:5000',
changeOrigin: true,
})
);
};
Verification Steps
- Open your React application in Chrome or Firefox.
- Press
F12to open Developer Tools and go to the Network tab. - Trigger the API call (e.g., refresh the page or click a button).
- Click on the failed request.
- Look at Response Headers. If the fix worked, you should see:
Access-Control-Allow-Origin: http://localhost:3000(or*). - Check the Console; the red CORS error should be gone.
Expert Tips
- Avoid
*in Production: Whileapp.use(cors({ origin: '*' }))is easy for testing, it is insecure. Always specify your exact production domain. - Check the Protocol:
http://localhost:3000andhttps://localhost:3000are considered different origins. Ensure they match. - Preflight Requests: For complex requests (like those with custom headers or
PUT/DELETEmethods), browsers send anOPTIONSrequest first. Ensure your server handlesOPTIONSrequests and returns the correct CORS headers. - Cookies and Credentials: If you need to send cookies or Authorization headers, you must set
credentials: 'include'in your fetch options andallow_credentials=Trueon your server.

