Fix "CORS policy: No 'Access-Control-Allow-Origin'" Error

Getting the "CORS policy: No 'Access-Control-Allow-Origin' header" error when making API requests? This complete guide provides backend and frontend solutions for all frameworks including React, Node.js, Express, Spring Boot, and more.

React Express Spring Boot Django Flask ASP.NET

What This Error Looks Like

Browser Console Error (Chrome/Edge):
Access to fetch at 'http://localhost:8080/api/data' from origin 'http://localhost:3000'
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present
on the requested resource. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.
Browser Console Error (Firefox):
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote
resource at http://localhost:8080/api/data. (Reason: CORS header 'Access-Control-Allow-Origin'
missing). Status code: 200.
Fetch/Axios Error in Code:
TypeError: Failed to fetch
    at fetch (native)
    at async fetchData()

// Or with Axios:
AxiosError: Network Error
    at XMLHttpRequest.handleError

Quick Fix (Choose Your Backend Framework)

The Problem: Your backend server is not sending CORS headers that allow your frontend to access it

Node.js/Express Solution:

  1. Install CORS package: npm install cors
  2. Add to your server:
    const cors = require('cors');
    app.use(cors());
  3. Restart your backend server
  4. Refresh your frontend - CORS error should be gone

Spring Boot Solution:

  1. Add @CrossOrigin annotation:
    @CrossOrigin(origins = "http://localhost:3000")
    @RestController
    public class ApiController { ... }
  2. Or create global CORS configuration (see full guide below)
  3. Restart your Spring Boot application

React Development Proxy (Quick Workaround):

  1. Add to package.json:
    "proxy": "http://localhost:8080"
  2. Change API calls from http://localhost:8080/api/data to /api/data
  3. Restart React dev server: npm start

Understanding CORS Errors

What is CORS?

CORS (Cross-Origin Resource Sharing) is a browser security feature that blocks requests from one origin (domain/port) to another.

Example of Cross-Origin Request:

Key Point: CORS is enforced by the BROWSER, not the server. Your API works fine in Postman/curl because they don't enforce CORS. The browser blocks the response to protect users.

Why Does CORS Exist?

CORS protects users from malicious websites making unauthorized requests to other websites using the user's credentials (cookies, session tokens).

Without CORS: An attacker's website could make requests to your bank's API using your logged-in session and steal your data.

With CORS: The browser blocks cross-origin requests unless the target server explicitly allows them with CORS headers.

Complete Backend Solutions

1 Node.js / Express Backend

Method 1: Using CORS Middleware (Recommended)

javascript
// 1. Install cors package
// npm install cors

// 2. Import and use cors
const express = require('express');
const cors = require('cors');
const app = express();

// Enable CORS for all routes (development)
app.use(cors());

// Or enable CORS for specific origin (production)
app.use(cors({
  origin: 'http://localhost:3000', // Your frontend URL
  credentials: true, // If you need to send cookies
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
}));

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

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

Method 2: Manual CORS Headers

javascript
// Add CORS headers manually (without cors package)
app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'http://localhost:3000'); // Frontend URL
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.header('Access-Control-Allow-Credentials', 'true');

  // Handle preflight requests
  if (req.method === 'OPTIONS') {
    return res.sendStatus(200);
  }

  next();
});

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

Method 3: Multiple Origins

javascript
// Allow multiple specific origins
const allowedOrigins = [
  'http://localhost:3000',
  'http://localhost:3001',
  'https://yourdomain.com',
  'https://www.yourdomain.com'
];

app.use(cors({
  origin: function (origin, callback) {
    // Allow requests with no origin (like mobile apps or Postman)
    if (!origin) return callback(null, true);

    if (allowedOrigins.indexOf(origin) === -1) {
      return callback(new Error('Not allowed by CORS'), false);
    }
    return callback(null, true);
  },
  credentials: true
}));

2 Spring Boot Backend

Method 1: @CrossOrigin Annotation

java
// On specific controller
@CrossOrigin(origins = "http://localhost:3000")
@RestController
@RequestMapping("/api")
public class ApiController {

    @GetMapping("/data")
    public ResponseEntity getData() {
        return ResponseEntity.ok("CORS is working!");
    }
}

// Or on specific method
@RestController
@RequestMapping("/api")
public class ApiController {

    @CrossOrigin(origins = "http://localhost:3000")
    @GetMapping("/data")
    public ResponseEntity getData() {
        return ResponseEntity.ok("CORS is working!");
    }
}

Method 2: Global CORS Configuration (Recommended)

java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**") // All endpoints
                    .allowedOrigins("http://localhost:3000") // Your frontend
                    .allowedMethods("GET", "POST", "PUT", "DELETE")
                    .allowedHeaders("*")
                    .allowCredentials(true)
                    .maxAge(3600); // Cache preflight response for 1 hour
            }
        };
    }
}

Method 3: Using Spring Security

java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
            .authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("http://localhost:3000");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

3 Django Backend

Using django-cors-headers

python
# 1. Install django-cors-headers
# pip install django-cors-headers

# 2. Add to INSTALLED_APPS in settings.py
INSTALLED_APPS = [
    # ...
    'corsheaders',
    # ...
]

# 3. Add middleware (MUST be at the top)
MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    # ... other middleware
]

# 4. Configure CORS settings
# For development - allow all origins
CORS_ALLOW_ALL_ORIGINS = True

# For production - specify allowed origins
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",
    "http://127.0.0.1:3000",
    "https://yourdomain.com",
]

# If you need credentials (cookies, auth)
CORS_ALLOW_CREDENTIALS = True

# Allowed methods
CORS_ALLOW_METHODS = [
    'DELETE',
    'GET',
    'OPTIONS',
    'PATCH',
    'POST',
    'PUT',
]

# Allowed headers
CORS_ALLOW_HEADERS = [
    'accept',
    'accept-encoding',
    'authorization',
    'content-type',
    'dnt',
    'origin',
    'user-agent',
    'x-csrftoken',
    'x-requested-with',
]

4 Flask Backend

Using Flask-CORS

python
# 1. Install Flask-CORS
# pip install flask-cors

# 2. Import and use CORS
from flask import Flask
from flask_cors import CORS

app = Flask(__name__)

# Enable CORS for all routes (development)
CORS(app)

# Or enable CORS for specific origin (production)
CORS(app, resources={
    r"/api/*": {
        "origins": ["http://localhost:3000"],
        "methods": ["GET", "POST", "PUT", "DELETE"],
        "allow_headers": ["Content-Type", "Authorization"],
        "supports_credentials": True
    }
})

@app.route('/api/data')
def get_data():
    return {'message': 'CORS is working!'}

if __name__ == '__main__':
    app.run(port=8080, debug=True)

5 ASP.NET Core Backend

CORS Configuration in Program.cs

csharp
// In Program.cs (ASP.NET Core 6+)

var builder = WebApplication.CreateBuilder(args);

// Add CORS policy
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowReactApp", policy =>
    {
        policy.WithOrigins("http://localhost:3000")
              .AllowAnyMethod()
              .AllowAnyHeader()
              .AllowCredentials();
    });
});

builder.Services.AddControllers();

var app = builder.Build();

// Use CORS (must be before UseAuthorization)
app.UseCors("AllowReactApp");

app.UseAuthorization();
app.MapControllers();

app.Run();


// In your controller:
[ApiController]
[Route("api/[controller]")]
public class DataController : ControllerBase
{
    [HttpGet]
    public IActionResult GetData()
    {
        return Ok(new { message = "CORS is working!" });
    }
}

Frontend Development Solutions (Proxies)

1 React (Create React App) Proxy

Simple Proxy Configuration

json
// In package.json, add:
{
  "name": "my-app",
  "version": "1.0.0",
  "proxy": "http://localhost:8080"
  // ... rest of package.json
}
javascript
// In your React component, change API calls:

// BEFORE (causes CORS error):
fetch('http://localhost:8080/api/data')

// AFTER (proxied - no CORS error):
fetch('/api/data')


// With Axios:
// BEFORE:
axios.get('http://localhost:8080/api/data')

// AFTER:
axios.get('/api/data')
Important: After adding proxy, restart your React dev server (npm start). The proxy only works in development, not production.

Advanced Proxy Configuration

javascript
// Create src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app) {
  app.use(
    '/api',
    createProxyMiddleware({
      target: 'http://localhost:8080',
      changeOrigin: true,
      pathRewrite: {
        '^/api': '/api', // Keep /api prefix
      },
    })
  );

  // Proxy multiple endpoints
  app.use(
    '/auth',
    createProxyMiddleware({
      target: 'http://localhost:8081',
      changeOrigin: true,
    })
  );
};

2 Vite (React/Vue) Proxy

javascript
// vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:8080',
        changeOrigin: true,
        secure: false,
        // rewrite: (path) => path.replace(/^\/api/, '') // Remove /api prefix if needed
      },
      // Multiple proxies
      '/auth': {
        target: 'http://localhost:8081',
        changeOrigin: true,
      }
    }
  }
})

3 Angular Proxy

json
// Create proxy.conf.json in project root
{
  "/api": {
    "target": "http://localhost:8080",
    "secure": false,
    "changeOrigin": true
  }
}
json
// In angular.json, modify serve options:
{
  "projects": {
    "your-app": {
      "architect": {
        "serve": {
          "options": {
            "proxyConfig": "proxy.conf.json"
          }
        }
      }
    }
  }
}
bash
# Or run with proxy flag:
ng serve --proxy-config proxy.conf.json

Production Deployment Considerations

Critical Security Warning:

Production Backend Configuration

javascript
// Node.js/Express - Environment-based CORS
const corsOptions = {
  origin: process.env.NODE_ENV === 'production'
    ? 'https://yourdomain.com'
    : 'http://localhost:3000',
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization']
};

app.use(cors(corsOptions));

Production Frontend Configuration

javascript
// React - Environment variables for API URL
// Create .env.development
REACT_APP_API_URL=http://localhost:8080

// Create .env.production
REACT_APP_API_URL=https://api.yourdomain.com

// In your code:
const API_URL = process.env.REACT_APP_API_URL;

fetch(`${API_URL}/api/data`)
  .then(res => res.json())
  .then(data => console.log(data));

Common Mistakes and Fixes

Mistake 1: Setting mode: 'no-cors'

Wrong Solution:

fetch('/api/data', { mode: 'no-cors' }) // DON'T DO THIS!

Why it's wrong: This makes the request but you can't read the response. You get an opaque response with no data.

Right Solution: Fix CORS on the backend instead.

Mistake 2: Only Configuring Frontend

Problem: Adding CORS headers in React/Vue/Angular code doesn't work.

Why: CORS headers must come from the SERVER (backend), not the client.

Solution: Configure CORS in your backend API server.

Mistake 3: Forgetting Preflight Requests

Problem: POST/PUT/DELETE requests fail even though GET works.

Why: Complex requests trigger a preflight OPTIONS request that must also return CORS headers.

Solution: Ensure your backend handles OPTIONS requests and returns proper headers (CORS middleware does this automatically).

Mistake 4: CORS with Credentials

Problem: Cookies/auth tokens aren't sent with requests.

Solution:

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

// Frontend:
fetch('/api/data', {
  credentials: 'include' // Include cookies
})

Quick Reference: CORS Headers

http
ESSENTIAL CORS HEADERS
======================

Access-Control-Allow-Origin: http://localhost:3000
  - Specifies which origin can access the resource
  - Use specific origin in production, never use * with credentials

Access-Control-Allow-Methods: GET, POST, PUT, DELETE
  - Specifies which HTTP methods are allowed

Access-Control-Allow-Headers: Content-Type, Authorization
  - Specifies which headers can be sent in the request

Access-Control-Allow-Credentials: true
  - Allows cookies and auth tokens to be sent
  - Cannot use with Access-Control-Allow-Origin: *

Access-Control-Max-Age: 3600
  - How long (in seconds) preflight response can be cached

Still Having Issues?

Debugging checklist:

Visit our Interactive Diagnostic Wizard for personalized help.