Skip to content
Troubleshooting⏱️ 11 min read·

How to Fix CORS Errors in React and Node.js (Access-Control-Allow-Origin Explained)

Understand what Cross-Origin Resource Sharing (CORS) actually is, why the browser blocks requests, and how to configure Express cors middleware and Laravel cors.php properly.

MN
Manoj NeupaneSoftware Developer & Programming Instructor
#CORS#React#Node.js#Express#Laravel#APIs
🎯 Who This Tutorial Is For

Frontend and full-stack developers whose fetch() or axios requests fail with 'No Access-Control-Allow-Origin header is present'.

📋 Prerequisites
  • ✓Basic experience calling REST APIs with fetch or axios
  • ✓Express.js backend or Laravel API

🚀 What You Will Learn & Build

  • ▸Why CORS is a browser security mechanism, NOT a server error
  • ▸The role of preflight OPTIONS requests
  • ▸Configuring Express cors middleware correctly for development and production
  • ▸Configuring Laravel config/cors.php
1

1. What CORS Actually Is (And What It Isn't)

CORS stands for **Cross-Origin Resource Sharing**. An origin is defined by `protocol + domain + port` (e.g. `http://localhost:3000`). When your React app running on `http://localhost:3000` attempts to fetch data from an API running on `http://localhost:5000`, the browser sees different ports and considers this a **cross-origin** request. By default, the browser blocks JavaScript from reading the response unless the backend explicitly includes the header: `Access-Control-Allow-Origin: http://localhost:3000` **Crucial Point:** The server actually processes the request and sends the response, but **your browser refuses to let your JavaScript read it!**
📌 Note— Browser-Only Policy

Tools like Postman and curl do NOT enforce CORS because they are not web browsers. If an API works in Postman but fails in React, it is a CORS configuration issue on your server.

2

2. The Proper Fix in Express.js

Install the official `cors` package: ```bash npm install cors ``` Configure it before registering your API routes:
server.js
const express = require('express');
const cors = require('cors');
const app = express();

// Option A: Quick development allow-all (Never use in production)
// app.use(cors());

// Option B: Production whitelist (Recommended)
const allowedOrigins = [
  'http://localhost:3000',
  'https://yourdomain.com',
  'https://www.yourdomain.com'
];

app.use(cors({
  origin: function (origin, callback) {
    // Allow requests with no origin (like mobile apps, curl, or Postman)
    if (!origin || allowedOrigins.indexOf(origin) !== -1) {
      callback(null, true);
    } else {
      callback(new Error('Blocked by CORS policy'));
    }
  },
  credentials: true, // Allow cookies / authorization headers
  methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
  allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With']
}));

// Handle preflight requests
app.options('*', cors());
3

3. The Proper Fix in Laravel

Laravel includes built-in CORS middleware configured in `config/cors.php`:
config/cors.php
<?php

return [
    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => [
        'http://localhost:3000',
        'https://yourdomain.com',
    ],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,
];

✨ Expected Output & Verification

Inspect the response headers in Chrome DevTools Network Tab: Access-Control-Allow-Origin: http://localhost:3000 Access-Control-Allow-Credentials: true HTTP 200 OK without console red error flags.

🧪 How to Test the Implementation

  1. 1Trigger fetch request from React frontend and inspect browser console
  2. 2Check Network tab for the preflight OPTIONS request returning 204 or 200

⚠️ Common Errors & How to Fix Them

❌Wildcard '*' cannot be used when credentials is true

Root Cause: Setting origin: '*' while simultaneously setting credentials: true.

Fix: Specify exact origins (e.g. 'http://localhost:3000') instead of '*' when sending cookies or Bearer tokens.

🛡️ Security Considerations & Best Practices

  • !Never leave Access-Control-Allow-Origin: * on production endpoints handling sensitive authenticated user data.

❓ Frequently Asked Questions (FAQ)

No. CORS headers must be sent by the server responding to the request. In development, you can use a Vite/Next.js proxy, but production requires backend headers.

📌 Summary of Key Takeaways

  • ✓CORS is enforced by browsers to prevent malicious scripts from reading third-party data.
  • ✓Fix it on the server by sending Access-Control-Allow-Origin headers.

Official References & Further Reading