search
React star Featured

How to Fix CORS Error in React Vite Project: Complete Guide 2026

Learn how to fix CORS errors in React Vite projects with step-by-step solutions. This guide covers proxy setup, server configurations, and best practices for handling cross-origin requests.

person By Gautam Sharma
calendar_today January 1, 2026
schedule 7 min read
React Vite CORS Frontend API Development

Cross-Origin Resource Sharing (CORS) errors are one of the most common challenges developers face when building React + Vite applications that communicate with external APIs. These errors occur when your React application tries to make requests to a different domain, port, or protocol than the one serving your application.

This comprehensive guide explains what CORS errors are, why they happen, and provides multiple solutions to fix them in your React Vite project with clean code examples and directory structure.


What is CORS Error?

CORS (Cross-Origin Resource Sharing) is a security feature implemented by web browsers to prevent malicious websites from making unauthorized requests to other domains. When your React application running on localhost:5173 tries to access an API on localhost:3000 or any external domain, the browser blocks the request unless the server explicitly allows it.

Common CORS Error Messages:

  • Access to fetch at 'http://localhost:3000/api/data' from origin 'http://localhost:5173' has been blocked by CORS policy
  • No 'Access-Control-Allow-Origin' header is present on the requested resource

Understanding the Problem

In a typical React + Vite setup, your development server runs on http://localhost:5173, while your backend API might run on http://localhost:3000. When your React app makes API calls to the backend, the browser enforces CORS policy and blocks these requests.

Typical Project Structure:

my-react-app/
├── index.html
├── package.json
├── vite.config.js
└── src/
    ├── App.jsx
    ├── main.jsx
    ├── components/
    │   └── ApiComponent.jsx
    └── index.css

The most common and effective solution during development is to configure a proxy in your Vite configuration. This allows Vite to intercept API requests and forward them to your backend server.

Step 1: Update vite.config.js

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      // Proxy API requests to your backend server
      '/api': {
        target: 'http://localhost:3000', // Your backend server URL
        changeOrigin: true,
        secure: false, // Set to true if using HTTPS
        // Optional: rewrite the path
        rewrite: (path) => path.replace(/^\/api/, '')
      },
      // You can add multiple proxy rules
      '/auth': {
        target: 'http://localhost:3000',
        changeOrigin: true,
        secure: false,
      }
    }
  }
})

Step 2: Update Your API Calls

Instead of calling the full backend URL, use the proxy path:

// src/components/ApiComponent.jsx
import { useState, useEffect } from 'react';

export default function ApiComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Instead of http://localhost:3000/api/data, use /api/data
    fetch('/api/data')
      .then(response => response.json())
      .then(data => {
        setData(data);
        setLoading(false);
      })
      .catch(error => {
        console.error('Error fetching data:', error);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>Loading...</div>;

  return (
    <div className="p-4">
      <h2 className="text-xl font-bold mb-2">API Data</h2>
      <pre className="bg-gray-100 p-2 rounded">{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

Solution 2: Backend Server Configuration (Production Ready)

For production environments, you need to configure CORS on your backend server. Here are examples for different backend technologies:

Express.js Backend Configuration

// server.js (your backend server)
const express = require('express');
const cors = require('cors');
const app = express();

// CORS configuration
const corsOptions = {
  origin: [
    'http://localhost:5173', // React Vite dev server
    'http://localhost:3000', // If needed
    'https://yourdomain.com', // Production domain
    'https://www.yourdomain.com'
  ],
  credentials: true,
  optionsSuccessStatus: 200
};

app.use(cors(corsOptions));

// Your API routes
app.get('/api/data', (req, res) => {
  res.json({ message: 'Hello from backend!' });
});

app.listen(3000, () => {
  console.log('Server running on port 3000');
});

Alternative: Simple CORS Setup

// Simple CORS setup for development
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization');
  
  if (req.method === 'OPTIONS') {
    res.sendStatus(200);
  } else {
    next();
  }
});

Solution 3: Environment-Based Configuration

Create environment-specific configurations to handle different environments:

Step 1: Create Environment Files

# .env.development
VITE_API_URL=http://localhost:3000

# .env.production
VITE_API_URL=https://api.yourdomain.com

Step 2: Update vite.config.js for Environment Handling

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig(({ mode }) => {
  const config = {
    plugins: [react()],
  };

  if (mode === 'development') {
    config.server = {
      proxy: {
        '/api': {
          target: process.env.VITE_API_URL || 'http://localhost:3000',
          changeOrigin: true,
          secure: false,
        }
      }
    };
  }

  return config;
});

Step 3: Use Environment Variables in Components

// src/components/ApiComponent.jsx
import { useState, useEffect } from 'react';

export default function ApiComponent() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Use environment variable for API calls
    const apiUrl = import.meta.env.VITE_API_URL || '/api';
    
    fetch(`${apiUrl}/data`)
      .then(response => response.json())
      .then(data => {
        setData(data);
        setLoading(false);
      })
      .catch(error => {
        console.error('Error fetching data:', error);
        setLoading(false);
      });
  }, []);

  if (loading) return <div>Loading...</div>;

  return (
    <div className="p-4">
      <h2 className="text-xl font-bold mb-2">API Data</h2>
      <pre className="bg-gray-100 p-2 rounded">{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
}

Solution 4: Using a Browser Extension (Temporary Fix)

For quick testing, you can use browser extensions like “CORS Unblock” or “Allow CORS”. However, this is not recommended for production as it only works in development and can be a security risk.


Complete Project Structure After CORS Fix

my-react-app/
├── .env.development
├── .env.production
├── index.html
├── package.json
├── vite.config.js
└── src/
    ├── App.jsx
    ├── main.jsx
    ├── components/
    │   └── ApiComponent.jsx
    └── index.css

Best Practices for Handling CORS

1. Never Use Wildcard in Production

// ❌ Don't do this in production
app.use(cors({
  origin: '*' // This allows all origins
}));

// ✅ Do this instead
app.use(cors({
  origin: ['https://yourdomain.com', 'https://www.yourdomain.com']
}));

2. Use Specific Endpoints for Proxy

// vite.config.js
proxy: {
  '/api': {
    target: 'http://localhost:3000',
    changeOrigin: true,
    rewrite: (path) => path.replace(/^\/api/, '')
  },
  '/auth': {
    target: 'http://localhost:3000',
    changeOrigin: true,
  }
}

3. Handle Credentials Properly

// If you need to send cookies or authentication headers
proxy: {
  '/api': {
    target: 'http://localhost:3000',
    changeOrigin: true,
    secure: false,
    credentials: 'include', // If needed
  }
}

Testing Your CORS Configuration

1. Check Network Tab

Open browser developer tools and check the Network tab for your API requests. Look for:

  • Status codes (should be 200, not 0)
  • Response headers
  • No CORS-related error messages

2. Console Errors

Check the browser console for any CORS-related error messages.

3. Test Different Endpoints

Test various API endpoints to ensure CORS is properly configured for all routes.


Common CORS Issues and Solutions

Issue 1: Preflight Requests

// If you're making complex requests (PUT, DELETE, custom headers)
// Make sure your server handles OPTIONS requests
app.options('*', cors(corsOptions));

Issue 2: Multiple Origins

// Handle multiple origins dynamically
const allowedOrigins = [
  'http://localhost:5173',
  'https://yourdomain.com',
  'https://www.yourdomain.com'
];

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

Performance Considerations

1. Cache CORS Responses

// Cache preflight responses
app.use((req, res, next) => {
  res.header('Access-Control-Max-Age', '86400'); // 24 hours
  next();
});

2. Minimize CORS Headers

Only include necessary CORS headers to reduce response size.


Security Considerations

1. Validate Origins

Always validate and restrict allowed origins to prevent security vulnerabilities.

2. Limit Credentials

Only use credentials when absolutely necessary.

3. Use HTTPS in Production

Always use HTTPS for production applications to ensure secure communication.


Conclusion

Fixing CORS errors in React Vite projects requires understanding both the frontend and backend configurations. The Vite proxy solution is the most effective for development, while backend CORS configuration is essential for production.

By following this guide, you can successfully resolve CORS issues in your React Vite applications and ensure smooth communication between your frontend and backend services. Remember to implement proper security measures and test thoroughly in different environments.

With these solutions implemented, your React Vite application will be able to communicate with external APIs without CORS-related issues, providing a seamless user experience.


Gautam Sharma

About Gautam Sharma

Full-stack developer and tech blogger sharing coding tutorials and best practices

Related Articles

React

Fix: process is not defined error in React Vite - Complete Solution Guide

Learn how to fix the 'process is not defined' error in React Vite projects. This guide covers environment variables, Node.js compatibility, and best practices for Vite configuration.

January 1, 2026
React

Fix: Invalid React hook call. Hooks can only be called inside of the body of a function component

Learn how to fix the 'Invalid hook call' error in React. This guide covers all causes, solutions, and best practices for proper React hook usage with step-by-step examples.

January 1, 2026
React

Fix: Module not found: Can't resolve 'react/jsx-runtime' - Complete Solution Guide

Learn how to fix the 'Module not found: Can't resolve react/jsx-runtime' error in React projects. This guide covers causes, solutions, and prevention strategies with step-by-step instructions.

January 1, 2026