How to Enable CORS in React JS?

How to Enable CORS in React JS?

Table of Contents

What is CORS in React?

Cross-Origin Resource Sharing (CORS) is a browser security mechanism that controls whether a React frontend application can access resources from a different domain (origin).

Understanding “Origins”

An origin consists of three parts:

  • Protocol: http:// or https://
  • Domain: example.com or api.example.com
  • Port: :3000, :5000, etc.

Examples of cross-origin requests:

  • Your React app runs on http://localhost:3000
  • Your API runs on http://localhost:5000 ← Different origin = CORS needed
  • Your frontend is https://myapp.com
  • Your API is https://api.myapp.com ← Different subdomain = CORS needed

Why CORS Matters for React Developers

When you install React in VS Code and build an app that fetches data from an external API, CORS becomes critical. Without proper CORS configuration, you’ll see errors like:

Access to XMLHttpRequest at 'http://api.example.com/data' 
from origin 'http://localhost:3000' has been blocked by CORS policy

Key point: CORS is enforced by browsers—it’s a client-side security feature, but you fix it on the server side.

Why CORS Errors Occur

The Browser’s CORS Check

When your React app makes a request to a different origin, the browser automatically:

  1. Sends a preflight request (OPTIONS) to check if the cross-origin request is allowed
  2. Inspects server response headers for Access-Control-Allow-Origin
  3. Blocks the request if the header isn’t present or doesn’t match the origin

Common CORS Error Scenarios

ScenarioError MessageSolution
React on localhost:3000, API on localhost:5000“has been blocked by CORS policy”Enable CORS on backend API
Wrong origin in whitelist“Origin not allowed”Add your frontend domain to CORS allowlist
Missing credentials header“Credentials mode is ‘include'”Set credentials: 'include' + proper headers
Preflight timeout“Failed to load OPTIONS”Increase timeout; check server is running

How to Enable CORS in React (3 Methods)

Method 1: Backend CORS Middleware (Recommended) ✅

This is the production-safe approach. Configure CORS on your Node.js/Express backend.

Pros:

  • Works in production
  • Secure—whitelist specific origins
  • Standard approach
  • No code changes needed in React

Cons:

  • Requires backend access
  • Requires restart after changes

Step 1: Install CORS Package

bash

npm install cors

Step 2: Add CORS Middleware to Express Server

javascript

const express = require('express');
const cors = require('cors');
const app = express();

// Option A: Allow requests from specific origin (SECURE)
const corsOptions = {
  origin: 'http://localhost:3000', // Your React app origin
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
  credentials: true, // Allow cookies/auth headers
  optionsSuccessStatus: 200
};

app.use(cors(corsOptions));

// OR Option B: Allow all origins (DEVELOPMENT ONLY)
app.use(cors());

// Your routes
app.get('/api/data', (req, res) => {
  res.json({ message: 'CORS enabled!' });
});

app.listen(5000, () => {
  console.log('API running on http://localhost:5000');
});

Step 3: Fetch from React App

javascript

// In your React component
useEffect(() => {
  fetch('http://localhost:5000/api/data', {
    method: 'GET',
    credentials: 'include' // If using cookies
  })
    .then(res => res.json())
    .then(data => console.log(data))
    .catch(err => console.error('CORS Error:', err));
}, []);

Method 2: Configure CORS for Specific Routes

Enable CORS only on routes that need it (more secure):

javascript

const express = require('express');
const cors = require('cors');
const app = express();

const corsOptions = {
  origin: ['http://localhost:3000', 'https://myapp.com'],
  methods: ['GET', 'POST'],
  credentials: true
};

// Apply CORS only to specific route
app.get('/api/public-data', cors(corsOptions), (req, res) => {
  res.json({ data: 'Public data with CORS' });
});

// This route has NO CORS
app.get('/api/admin', (req, res) => {
  res.status(403).json({ error: 'Forbidden' });
});

app.listen(5000);

Best for: Different CORS rules for different endpoints.

Method 3: Manual CORS Headers (Advanced)

If you can’t use the CORS package, set headers manually:

javascript

const express = require('express');
const app = express();

app.use((req, res, next) => {
  // Allow specific origin
  res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000');
  
  // Allow credentials
  res.setHeader('Access-Control-Allow-Credentials', 'true');
  
  // Allowed HTTP methods
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS');
  
  // Allowed headers
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  
  // Max age for preflight cache (seconds)
  res.setHeader('Access-Control-Max-Age', '86400');
  
  // Handle preflight requests
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }
  
  next();
});

app.get('/api/data', (req, res) => {
  res.json({ message: 'Works without cors package!' });
});

app.listen(5000);

Enable CORS in Express.js Backend

Complete Express + CORS Setup (Step-by-Step)

If you’re using React with a PHP backend or any other backend, here’s the standard Express approach:

1. Create a new Express server:

bash

mkdir my-api
cd my-api
npm init -y
npm install express cors

2. Create server.js:

javascript

const express = require('express');
const cors = require('cors');
const app = express();

// Middleware
app.use(express.json());

// CORS Configuration
const corsOptions = {
  origin: [
    'http://localhost:3000',
    'http://localhost:5173', // Vite default
    'https://yourdomain.com'
  ],
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
  credentials: true,
  optionsSuccessStatus: 200
};

app.use(cors(corsOptions));

// Routes
app.get('/api/users', (req, res) => {
  res.json({
    users: [
      { id: 1, name: 'John Doe' },
      { id: 2, name: 'Jane Smith' }
    ]
  });
});

app.post('/api/users', (req, res) => {
  const newUser = req.body;
  res.status(201).json({ id: 3, ...newUser });
});

// Error handling
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Server error' });
});

const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
  console.log(`API server running on http://localhost:${PORT}`);
});

3. Start the server:

bash

node server.js

4. From your React app, fetch data:

javascript

import { useEffect, useState } from 'react';

function App() {
  const [users, setUsers] = useState([]);
  const [error, setError] = useState(null);

  useEffect(() => {
    // Make API call
    fetch('http://localhost:5000/api/users', {
      method: 'GET',
      credentials: 'include'
    })
      .then(res => res.json())
      .then(data => setUsers(data.users))
      .catch(err => setError(err.message));
  }, []);

  return (
    <div>
      {error ? <p>Error: {error}</p> : users.map(u => <p>{u.name}</p>)}
    </div>
  );
}

export default App;

CORS Configuration Best Practices

1. Never Use origin: '*' in Production ⚠️

javascript

// ❌ INSECURE
app.use(cors()); // Allows ALL origins

// ✅ SECURE
app.use(cors({
  origin: process.env.ALLOWED_ORIGINS?.split(',') || [],
  credentials: true
}));

2. Use Environment Variables

javascript

const corsOptions = {
  origin: process.env.NODE_ENV === 'production' 
    ? 'https://yourdomain.com'
    : 'http://localhost:3000',
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE']
};

app.use(cors(corsOptions));

3. Whitelist Multiple Domains Safely

javascript

const allowedOrigins = [
  'http://localhost:3000',
  'https://yourdomain.com',
  'https://www.yourdomain.com',
  'https://staging.yourdomain.com'
];

const corsOptions = {
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error('Not allowed by CORS'));
    }
  },
  credentials: true
};

app.use(cors(corsOptions));

4. Handle Preflight Requests Explicitly

javascript

// Preflight responses should be FAST
app.options('/api/*', cors());

// Or specific endpoints
app.options('/api/data', cors());
app.get('/api/data', (req, res) => {
  res.json({ data: 'value' });
});

5. Know Your HTTP Methods for React Best Practices

  • GET: Fetch data (safe)
  • POST: Create data (requires CORS preflight if not simple request)
  • PUT/PATCH: Update data (requires CORS preflight)
  • DELETE: Remove data (requires CORS preflight)

Troubleshooting CORS Errors

Error: “Access to XMLHttpRequest blocked by CORS policy”

Cause: Server isn’t sending Access-Control-Allow-Origin header

Fix:

javascript

app.use(cors({
  origin: 'http://localhost:3000'
}));

Error: “Credentials mode is ‘include’ but Access-Control-Allow-Credentials is missing”

Cause: You sent credentials: 'include' in fetch but server doesn’t allow it

Fix:

javascript

const corsOptions = {
  origin: 'http://localhost:3000',
  credentials: true  // ← Add this
};
app.use(cors(corsOptions));

And in React:

javascript

fetch('http://localhost:5000/api/data', {
  credentials: 'include' // ← Add this
})

Error: “preflight request to (OPTIONS) failed”

Cause: Server doesn’t handle OPTIONS requests

Fix:

javascript

app.options('*', cors());
// OR specific route
app.options('/api/data', cors());

Error: “Origin ‘http://localhost:3000‘ is not allowed”

Cause: Your origin isn’t in the CORS whitelist

Fix: Check your corsOptions.origin value matches exactly (protocol + domain + port):

javascript

// If running on http://localhost:3000, ensure:
origin: 'http://localhost:3000' // NOT https, NOT localhost:5000

Using a Proxy During Development

If you can’t access the backend directly, use a proxy:

In package.json of your React app:

json

{
  "proxy": "http://localhost:5000"
}

Then fetch without the full URL:

javascript

fetch('/api/data') // Proxies to http://localhost:5000/api/data

⚠️ Note: This only works in development with create-react-app. For Vite React projects, configure in vite.config.js:

javascript

export default {
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:5000',
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  }
}

Security Considerations

CORS Doesn’t Prevent All Attacks

CORS protects against cross-site request forgery (CSRF) but doesn’t prevent:

  • Direct API access via tools like Postman
  • Bot attacks
  • DDoS attacks

Always validate on the server side.

Secure CORS Headers

javascript

const corsOptions = {
  origin: process.env.ALLOWED_ORIGINS?.split(','),
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  credentials: true,
  maxAge: 3600, // Preflight cache time
  allowedHeaders: ['Content-Type', 'Authorization']
};

app.use(cors(corsOptions));

// Add security headers
app.use((req, res, next) => {
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'DENY');
  next();
});

Check Authorization Headers

Even with CORS enabled, verify authentication:

javascript

app.get('/api/protected', cors(corsOptions), (req, res) => {
  const token = req.headers.authorization?.split(' ')[1];
  
  if (!token || !verifyToken(token)) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  
  res.json({ data: 'Sensitive data' });
});

FAQs

Q: Do I need to enable CORS in React itself?

A: No. CORS is a server-side configuration only. React can’t bypass browser CORS restrictions. Always configure your backend API server.

Q: Can I enable CORS for specific HTTP methods?

A: Yes. In the methods option:

javascript

app.use(cors({
  origin: 'http://localhost:3000',
  methods: ['GET', 'POST'] // DELETE and PUT blocked
}));

Q: Is it safe to use origin: '*'?

A: Only for public APIs with no sensitive data. Never use in production for authenticated endpoints. It allows any website to make requests.

Q: Why does my preflight request timeout?

A: Common causes:

  • Backend server not running
  • Firewall blocking the port
  • Server not handling OPTIONS requests
  • Network issues

Debug with browser DevTools Network tab → check OPTIONS request status.

Q: How do I enable CORS for file uploads?

A: CORS works the same for file uploads:

javascript

app.post('/api/upload', cors(corsOptions), (req, res) => {
  // Handle file upload
});

Q: Should I use CORS or a proxy?

A:

  • Development: Use proxy for convenience
  • Production: Use CORS on backend for proper security
  • Both: Use both—proxy in dev, CORS in prod

Q: How does CORS interact with authentication?

A: Add credentials: true in both server and client:

// Server
app.use(cors({ 
  origin: 'http://localhost:3000',
  credentials: true 
}));

// React
fetch('http://localhost:5000/api/data', {
  credentials: 'include'
})

Related Resources & Next Steps

Ready to build with CORS enabled? Check out these related guides:

Conclusion

Enabling CORS in React JS is essential for modern web applications. Remember:

CORS is configured on the backend, not in React
Use specific origins in production, never origin: '*'
Always validate requests server-side, CORS isn’t enough for security
Whitelist trusted domains to prevent unauthorized access
Use credentials: true carefully with authentication

By following these practices, you’ll build secure, scalable React applications that communicate seamlessly with backend APIs.

Picture of Priyanshu Pathak

Priyanshu Pathak

Priyanshu Pathak is a Senior Developer at Sourcebae. He works across the stack to build fast, reliable features that make hiring simple. From APIs and integrations to performance and security, Priyanshu keeps our products clean, scalable, and easy to maintain.

Table of Contents

Hire top 1% global talent now

FAQ

Still Curious? These might help

Related blogs

Quick answer Create routes in React using React Router v6 in 4 steps: That’s it. You now have a multi-page

Quick answer npm (Node Package Manager) is a package manager for JavaScript that manages all the libraries and tools your

Quick answer Install React JS in VS Code in 10 minutes: Your React dev environment is live and hot-reloading. Full

Quick Answer React is primarily a front-end technology. It is a JavaScript library designed for building user interfaces that run