CORS: No ‘Access-Control-Allow-Origin’ header in Express app (Node.js 24)

Hi everyone,

I am getting this CORS error message when I try to fetch data in my application. The ‘Access-Control-Allow-Origin' value is in the response header locally, but not on the live app that is deployed with Vercel.

Error Message: Access to XMLHttpRequest at ‘<server>’ from origin ‘<client>’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

I have tried two tried-and-true approaches and both don’t work when deployed: app.use(cors()) and res.header('Access-Control-Allow-Origin', 'http://localhost:8000').

I have looked through posts with similar issues and couldn’t solve my problem.

I have included my index.js, vercel.json, and package.json files.

Any help is greatly appreciated! Thank you!

Code and Configuration:

Index.js (Express)

const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const router = require('./routes/router');
const dotenv = require('dotenv');

const env = process.env.NODE_ENV || '';

dotenv.config();

const app = express();

// Approach 1: app.use(cors()) - doesn't work when deployed
const corsOptions = {
  methods: 'GET',
  allowedHeaders: 'Content-Type, Authorization',
  origin: 'http://localhost:8000',
  credentials: true,
  optionSuccessStatus: 200,
};
app.use(cors(corsOptions));

app.use(bodyParser.json());
app.use(
  bodyParser.urlencoded({
    extended: false,
  })
);

// Approach 2: res.header(key, value) - doesn't work when deployed
/*
app.use((req, res, next) => {
  const origin = req.headers.origin;
  console.log('origin', origin);
  res.header(
    'Access-Control-Allow-Origin',
    'http://localhost:8000'
  );

  res.header('Access-Control-Allow-Methods', 'GET');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  if (req.method === 'OPTIONS') {
    return res.status(200).end();
  }

  next();
});
*/

app.use('/', router);
app.use('/tiers', router);
app.use('/members', router);

const port = 4000;
const server = app.listen(port, () => {
  console.log(`Server is running on port ${port} in ${env} mode`);
});


Vercel.json

{“version”: 2,“builds”: [{“src”: “./index.js”,“use”: “@vercel/node”}],“routes”: [{“src”: “/(.*)”,“dest”: “/”}]}

PACKAGE.JSON

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "NODE_ENV=production node ./index.js",
    "dev": " NODE_ENV=development nodemon ./index.js localhost 4000 --env-file=.env.development",
    "prod": "NODE_ENV=production nodemon ./index.js localhost 4000 --env-file=.env.production",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^1.6.8",
    "body-parser": "^1.20.2",
    "cors": "^2.8.5",
    "dotenv": "^16.4.5",
    "express": "^4.18.3",
    "nodemon": "^3.1.0",
    "patreon": "^0.4.1"
  },
  "engines": {
    "node": "24.x"
  }
}

If you’re having trouble deploying an Express app, this guide can help.

You can also ask v0 for suggestions tailored to your own project setup.

Hi @cubasve, welcome to the Vercel Community!

It seems like you’ve hard coded the origin to locahost:8000, which causes the issue once your client is deployed to a .vercel.app or your custom domain.

To solve this issue, you can add an environment variable to your backend that is set to http://localhost:8000 in your local machine but to the actual client deployment URL once your backend is deployed.

This will solve your issue.

Also, I noticed that your vercel.json is still using old configuration, which you can remove altogether. You can follow our Express on Vercel, which is a zero configuration setup.

Hi @anshumanb , I appreciate your quick reply!

I have updated my cors options to account for local and production domains and have also looked at the link you shared and added “type”:”commonjs” to my package.json.

I am still getting the same error saying “No ‘Access-Control-Allow-Origin’ header is present on the requested resource”.
You mentioned that I can remove my vercel.json file entirely after following the instructions of the link. I did that and saw the same error.

Below are my code updates:

CORS config:

const corsOptions = {
  methods: 'GET',
  allowedHeaders: 'Content-Type, Authorization',
  origin: (_origin, callback) => {
    const origin = _origin || '';
    const prodDomain =
      /^https:\/\/(<DOMAIN>)\.vercel\.app\/?$/.test(origin);
    const localDomain = 'http://localhost:3000';

    if (prodDomain || localDomain || !origin) {
      callback(null, true);
    } else {
      callback(null, false);
    }
  },
  credentials: true,
  optionSuccessStatus: 200,
};
app.use(cors(corsOptions));

Package.json:

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "NODE_ENV=production nodemon ./index.js localhost 4000",
    "dev": " NODE_ENV=development nodemon ./index.js localhost 4000 --env-file=.env.development",
    "prod": "NODE_ENV=production nodemon ./index.js localhost 4000 --env-file=.env.production",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "axios": "^1.6.8",
    "body-parser": "^1.20.2",
    "cors": "^2.8.5",
    "dotenv": "^16.4.5",
    "express": "^5.2.1", // Updated express to the latest version
    "nodemon": "^3.1.0",
    "patreon": "^0.4.1"
  },
  "engines": {
    "node": "24.x"
  },
  "type": "commonjs" // Added commonjs type as per the link's instructions
}

Hi @cubasve, I see. I’d recommend giving this post a read:

Similarly I go into details about Express and CORS here:

https://community.vercel.com/t/express-101-everything-about-deploying-your-express-app-on-vercel/4870/2

I recommend you look at it from a fresh perspective and see if the repos linked work and then work backwards in your project to debug.

@anshumanb Thanks for providing the links!

I solved this issue by creating another project for the route and controller function I was experiencing problems with. I also added TypeScript and installed @types/cors.

// index.ts file

import cors from 'cors';
import type { CorsOptions } from 'cors';

const corsOptions: CorsOptions = {
  methods: 'GET',
  allowedHeaders: 'Content-Type, Authorization',
  origin: 'http://localhost:8000',
  credentials: true,
  // BEFORE - optionSuccessStatus: 200,
  optionsSuccessStatus: 200, // AFTER - options is plural
};
// package.json
{
	"name": "",
	"version": "1.0.0",
	"main": "index.js",
	"scripts": {
		"test": "echo \"Error: no test specified\" && exit 1",
		"build": "tsc",
		"start": "node dist/server.js",
		"dev": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' index.ts",
		"lint": "eslint 'index.ts'"
	},
	"keywords": [],
	"author": "",
	"license": "ISC",
	"description": "",
	"devDependencies": {
		"@types/express": "^5.0.6",
		"@types/node": "^25.0.6",
		"@types/cors": "^2.8.19",
		"eslint": "^9.39.2",
		"install": "^0.13.0",
		"npm": "^11.7.0",
		"prettier": "^3.7.4",
		"ts-node": "^10.9.2",
		"typescript": "^5.9.3"
	},
	"dependencies": {
		"axios": "^1.13.2",
		"cors": "^2.8.5",
		"dotenv": "^17.2.3",
		"express": "^5.2.1",
		"nodemon": "^3.1.11",
	}
}

1 Like