How to Fix CORS Errors Once and For All (With Real Examples)

❌ The Error You're Seeing

Access to fetch at 'https://api.example.com/data' 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 happens when your frontend tries to call an API on a different domain, and the API doesn't explicitly allow it. Here's how to fix it.

What is CORS and Why Does It Exist?

CORS stands for Cross-Origin Resource Sharing. It's a security feature built into browsers that prevents malicious websites from accessing APIs they shouldn't.

How CORS Works

Browser (localhost:3000)
    ↓
    Makes request to API (api.example.com)
    ↓
    Browser checks: Does api.example.com allow localhost:3000?
    ↓
    If YES (CORS headers present) → Request succeeds ✓
    If NO (no CORS headers) → Request blocked ✗ (CORS error)
                

Important: CORS is a browser security feature. Your API isn't actually blocked—Postman, curl, and mobile apps can still access it. Only browsers enforce CORS.

Quick Fixes (Choose Your Situation)

1 You Control the Backend (Best Solution)

Add CORS headers to your API responses. This is the proper fix.

Node.js / Express

// Install cors package
npm install cors

// In your Express app
const express = require('express');
const cors = require('cors');
const app = express();

// Allow all origins (development only!)
app.use(cors());

// OR: Allow specific origins (production)
app.use(cors({
  origin: ['http://localhost:3000', 'https://yourdomain.com'],
  credentials: true  // If you need cookies/auth
}));

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

Python / Flask

# Install flask-cors
pip install flask-cors

from flask import Flask
from flask_cors import CORS

app = Flask(__name__)

# Allow all origins (development only!)
CORS(app)

# OR: Allow specific origins (production)
CORS(app, origins=['http://localhost:3000', 'https://yourdomain.com'])

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

Python / FastAPI

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# Add CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=['http://localhost:3000', 'https://yourdomain.com'],
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
)

@app.get('/api/data')
def get_data():
    return {'message': 'Success!'}

2 You Don't Control the Backend

If you're calling a third-party API that doesn't have CORS enabled, use a proxy.

Option A: Use a CORS Proxy (Quick & Dirty)

// Instead of:
fetch('https://api.example.com/data')

// Use a CORS proxy:
fetch('https://cors-anywhere.herokuapp.com/https://api.example.com/data')

// Or deploy your own: https://github.com/Rob--W/cors-anywhere

⚠️ Warning

Public CORS proxies are slow and unreliable. Don't use them in production. Deploy your own proxy instead.

Option B: Create Your Own Proxy (Production-Ready)

// Create a simple proxy endpoint in your backend
// proxy.js (Node.js example)
const express = require('express');
const axios = require('axios');
const app = express();

app.get('/api/proxy', async (req, res) => {
  try {
    const response = await axios.get('https://api.example.com/data');
    res.json(response.data);
  } catch (error) {
    res.status(500).json({ error: 'Proxy error' });
  }
});

// Now your frontend calls your own API:
// fetch('/api/proxy') instead of fetch('https://api.example.com/data')

3 You're in Development and Just Want It to Work

Disable CORS in your browser (temporary fix only!).

Chrome (Mac/Linux)

# Close Chrome completely, then run:
open -na "Google Chrome" --args --disable-web-security --user-data-dir="/tmp/chrome-dev"

Chrome (Windows)

# Close Chrome completely, then run:
"C:\Program Files\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:\tmp\chrome-dev"

⚠️ Security Warning

Never use this for browsing the web! Only use it for local development. This disables important security features.

Understanding CORS Headers

When you configure CORS, you're setting these HTTP headers:

Header What It Does Example
Access-Control-Allow-Origin Which origins can access the API * or https://example.com
Access-Control-Allow-Methods Which HTTP methods are allowed GET, POST, PUT, DELETE
Access-Control-Allow-Headers Which headers can be sent Content-Type, Authorization
Access-Control-Allow-Credentials Whether cookies/auth are allowed true or false

Common CORS Mistakes

Mistake 1: Using * in Production

// ❌ Bad: Allows ANY website to access your API
app.use(cors({ origin: '*' }));

// ✅ Good: Only allow your frontend
app.use(cors({ 
  origin: ['https://yourdomain.com', 'https://app.yourdomain.com'] 
}));

Mistake 2: Forgetting About Preflight Requests

Browsers send an OPTIONS request before certain requests (like POST with JSON). Your server must handle these:

// Express handles this automatically with cors()
// But if you're not using cors(), you need:
app.options('*', cors());  // Handle preflight for all routes

Mistake 3: Not Including Credentials When Needed

// If your API uses cookies or auth headers:

// Backend:
app.use(cors({
  origin: 'https://yourdomain.com',
  credentials: true  // ← Don't forget this!
}));

// Frontend:
fetch('https://api.yourdomain.com/data', {
  credentials: 'include'  // ← And this!
});

Testing CORS

Using curl

# Test if CORS headers are present
curl -I -X OPTIONS \
  -H "Origin: http://localhost:3000" \
  -H "Access-Control-Request-Method: GET" \
  https://api.example.com/data

# You should see Access-Control-Allow-* headers in the response

Using Browser DevTools

  1. Open DevTools → Network tab
  2. Make your API request
  3. Click on the failed request
  4. Check the "Headers" tab for CORS headers
  5. Check the "Console" tab for error messages

Production Deployment

Vercel / Netlify

Add a vercel.json or netlify.toml to configure CORS:

// vercel.json
{
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        { "key": "Access-Control-Allow-Origin", "value": "*" },
        { "key": "Access-Control-Allow-Methods", "value": "GET, POST, PUT, DELETE" }
      ]
    }
  ]
}

Nginx

# In your nginx config
location /api {
    add_header 'Access-Control-Allow-Origin' 'https://yourdomain.com';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
    add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
    
    # Handle preflight
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' 'https://yourdomain.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
        add_header 'Content-Length' 0;
        add_header 'Content-Type' 'text/plain';
        return 204;
    }
    
    proxy_pass http://localhost:3000;
}

Summary

CORS errors happen when your frontend tries to access an API on a different domain. Here's how to fix them:

  1. If you control the backend: Add CORS headers (use cors package for Node.js, flask-cors for Python)
  2. If you don't control the backend: Create a proxy endpoint in your own backend
  3. For development only: Disable CORS in Chrome (never do this in production!)

Remember: CORS is a browser security feature. Your API isn't actually blocked—only browsers enforce it. Postman, curl, and mobile apps can still access it.

💡 Pro Tip

Always test CORS with the actual domain you'll use in production. localhost and 127.0.0.1 are treated as different origins!

W

Wivrix Team

We write practical guides to help developers solve real problems. No fluff, just solutions that work.