Understanding CORS: A Simple Guide and Fixes

Outline
Hook / Intro — relatable scenario of hitting a CORS error
What is CORS? — simple definition
Why Browsers Enforce It — the security reason
How It Works — origins, request/response headers, preflight
Common Causes of CORS Errors — real-world dev cases
How to Fix CORS — backend, frontend, proxy solutions
Best Practices & Security Notes
Conclusion & Resources
Intro: The Dreaded CORS Error
You’ve just connected your frontend to a shiny new API. You hit “Refresh”... and bam!
pgsqlCopyEditAccess to fetch at 'https://api.example.com/data' from origin 'http://localhost:3000' has been blocked by CORS policy
If you’ve been here before, you know the frustration. This is where CORS comes in.
What is CORS?
CORS (Cross-Origin Resource Sharing) is a browser mechanism that controls how web applications interact with resources from different origins.
Origin = protocol + domain + port
http://localhost:3000
https://myapp.com
By default, browsers block requests to a different origin to protect users from malicious sites.
Why Does It Exist?
Without CORS, any malicious website could silently make API calls to other sites where you’re logged in (like your bank) and read sensitive data.
CORS acts as a gatekeeper — unless the server explicitly says “yes, I trust you,” your browser says “nope.”
How CORS Works
Simple Requests (e.g., GET without special headers)
Browser sends the request directly.
Server responds with a header like:
arduinoCopyEditAccess-Control-Allow-Origin: https://myapp.com
If the header matches the requesting origin, the browser delivers the data.
Preflight Requests (e.g., POST with JSON body or custom headers)
Browser sends an OPTIONS request first.
Server must respond with allowed methods, headers, and origin.
Only then is the real request sent.
Common Causes of CORS Errors
Server missing
Access-Control-Allow-Origin
headerAPI only allows specific domains, but you’re testing from
localhost
Sending credentials without
Access-Control-Allow-Credentials
enabledUsing HTTP vs. HTTPS mismatches
How to Fix CORS
On the Backend (Preferred)
Add appropriate CORS headers:
Node.js + Express example
javascriptCopyEditimport express from "express";
import cors from "cors";
const app = express();
app.use(cors({ origin: "http://localhost:3000" })); // allow only your frontend
Using a Proxy
If you can’t modify the API server, you can proxy requests through your backend:
arduinoCopyEditFrontend → Your Server → Target API
This way, the browser thinks it’s same-origin.
For Local Dev Only
When running locally, CORS errors can slow you down — but you can work around them during development:
Enable CORS in the Backend (Best Way)
If you own the backend, just allow your local origin:
javascriptCopyEditapp.use(cors({ origin: "http://localhost:3000" }));
Use a Local Development Proxy
React (CRA): Add
"proxy": "
https://api.example.com
"
topackage.json
Vite:
javascriptCopyEditserver: {
proxy: {
'/api': 'https://api.example.com'
}
}
Use a Backend Middleware Proxy
Create a small Node server that forwards requests to the API.
Temporary Browser Extension
Chrome: “Allow CORS”
Firefox: “CORS Everywhere”
⚠ Dev-only, not for production.
Run Browser with Security Disabled
bashCopyEditchrome.exe --disable-web-security --user-data-dir="C:/chrome-dev"
⚠ Dangerous — use only for quick testing.
Best Practices
Never use
Access-Control-Allow-Origin: *
for APIs with sensitive data.Use whitelists for allowed origins.
Always consider security over convenience.
Conclusion
CORS isn’t a bug — it’s a browser’s way of protecting users. Once you understand how it works, you can work with it instead of fighting it.
Further Reading:
Subscribe to my newsletter
Read articles from vamshidhar reddy directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
