← Cheatsheets / Error Fixes

How to Fix CORS Errors

Getting 'Access-Control-Allow-Origin' errors? Here's what CORS actually is, why browsers block your requests, and how to fix it for every framework.

CORS API debugging backend error-fix

Your frontend calls an API. The browser says no. CORS errors are the most confusing errors in web development because your code is correct — the browser is intentionally blocking the request for security.

AI tools are especially bad at handling CORS because the fix depends on your exact architecture, and AI often suggests the wrong solution.


What Is CORS, Actually?

CORS = Cross-Origin Resource Sharing. It’s a browser security feature.

When your frontend (localhost:3000) makes a request to a different origin (api.example.com or even localhost:8080), the browser checks: “Did the server say this is allowed?” If the server doesn’t include the right headers, the browser blocks the response.

Key insight: CORS is enforced by the browser, not the server. Your API call actually succeeds — the server receives it and responds — but the browser refuses to show you the response.

The Error Message

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.

4 Common Causes

1. Backend Doesn’t Send CORS Headers

The most common cause. Your API server needs to explicitly allow cross-origin requests.

2. Different Ports Count as Different Origins

localhost:3000 and localhost:8080 are different origins. Even http:// vs https:// on the same domain is a different origin.

3. Preflight Request Fails

For non-simple requests (POST with JSON, custom headers), the browser sends an OPTIONS request first. If your server doesn’t handle OPTIONS, CORS fails.

4. Credentials / Cookies Misconfiguration

If you’re sending cookies cross-origin, both the frontend and backend need special configuration, and you can’t use wildcard * for allowed origins.


Fixes by Framework

Express.js (Node)

// Install: npm install cors
import cors from 'cors';

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

// Production: specify allowed origins
app.use(cors({
  origin: ['https://yourapp.com', 'https://www.yourapp.com'],
  credentials: true,  // if using cookies
}));

Next.js API Routes (App Router)

// app/api/data/route.ts
export async function GET(request: Request) {
  const data = { message: 'hello' };
  
  return new Response(JSON.stringify(data), {
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  });
}

// Handle preflight
export async function OPTIONS() {
  return new Response(null, {
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  });
}

Next.js Config (Rewrites Proxy)

The cleanest solution — avoid CORS entirely by proxying:

// next.config.js
module.exports = {
  async rewrites() {
    return [
      {
        source: '/api/:path*',
        destination: 'https://api.example.com/:path*',
      },
    ];
  },
};
// Now fetch from '/api/data' instead of 'https://api.example.com/data'

Python (Flask)

# pip install flask-cors
from flask_cors import CORS

app = Flask(__name__)
CORS(app)  # Allow all origins

# Production:
CORS(app, origins=['https://yourapp.com'])

Python (FastAPI)

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://yourapp.com"],  # or ["*"] for dev
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

Astro (SSR)

// For Astro API endpoints
export async function GET() {
  return new Response(JSON.stringify({ data: 'hello' }), {
    headers: {
      'Access-Control-Allow-Origin': '*',
    },
  });
}

Step-by-Step Fix Process

Step 1: Identify the Type of CORS Error

Open browser DevTools → Network tab. Look for:

  • Missing Access-Control-Allow-Origin header → Server needs to add it
  • Preflight (OPTIONS) request failing → Server needs to handle OPTIONS method
  • Credentials flag issue → Can’t use * with credentials: true

Step 2: Determine Your Architecture

  • Same server? Use a proxy/rewrite (best solution — no CORS needed)
  • Separate frontend/backend? Add CORS headers to backend
  • Third-party API? Use a server-side proxy (you can’t modify their headers)

Step 3: Apply the Fix

For development, cors() with defaults is fine. For production:

  1. Specify exact allowed origins (not *)
  2. Handle OPTIONS preflight requests
  3. Set credentials: true only if you need cookies

Step 4: Verify

Check the Network tab again. The response should now include:

Access-Control-Allow-Origin: https://yourapp.com

The “Use a Proxy” Solution (Best for Third-Party APIs)

If you’re calling a third-party API that doesn’t allow CORS, don’t try to fix it on the frontend. Route through your own server:

// Your Next.js/Express API route
app.get('/api/proxy/weather', async (req, res) => {
  const response = await fetch('https://api.weather.com/data', {
    headers: { 'API-Key': process.env.WEATHER_API_KEY },
  });
  const data = await response.json();
  res.json(data);  // No CORS issue — same origin!
});

This is also more secure because you keep API keys server-side.


🤖 Prompt to Fix This

I'm getting a CORS error in my web app:

[PASTE THE FULL CORS ERROR FROM BROWSER CONSOLE]

My setup:
- Frontend: [framework] running on [URL/port]
- Backend: [framework] running on [URL/port]
- I'm calling: [the API endpoint]
- Am I sending cookies/auth headers? [yes/no]

Please:
1. Explain why this specific CORS error is happening
2. Give me the exact backend code to fix it (for my framework)
3. If I'm calling a third-party API, show me how to set up a proxy
4. Show the production-safe configuration (not just allow-all)

Common Mistakes

  • Adding CORS headers on the frontend — CORS is a server-side fix
  • Using mode: 'no-cors' in fetch — This makes the response opaque (you can’t read it)
  • Using * with credentials — Browsers reject this combination
  • Disabling browser security — Chrome flags like --disable-web-security are dangerous, not a fix

✓ Copied to clipboard!