CORS

Fix CORS Error on Vercel Serverless Functions

Vercel serverless functions do not add CORS headers automatically. When called from a different domain, the browser blocks the response. Add headers in vercel.json to fix all API routes at once.

Browser Console Error
Access to fetch at 'https://yourproject.vercel.app/api/data' from origin 'https://yourapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Option 1 — vercel.json (applies to all API routes)

{
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        { "key": "Access-Control-Allow-Origin", "value": "https://yourapp.com" },
        { "key": "Access-Control-Allow-Methods", "value": "GET,POST,PUT,DELETE,OPTIONS" },
        { "key": "Access-Control-Allow-Headers", "value": "Content-Type, Authorization" },
        { "key": "Access-Control-Allow-Credentials", "value": "true" }
      ]
    }
  ]
}

This adds headers to all responses but does not handle OPTIONS preflight automatically. You still need to return 204 for OPTIONS in your function.

Option 2 — inside the function handler

// api/data.js
export default function handler(req, res) {
  res.setHeader('Access-Control-Allow-Origin', 'https://yourapp.com');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  res.setHeader('Access-Control-Allow-Credentials', 'true');

  if (req.method === 'OPTIONS') {
    return res.status(204).end();
  }

  return res.json({ data: 'ok' });
}

Option 3 — middleware.ts for App Router

// middleware.ts
import { NextResponse } from 'next/server';

export function middleware(request) {
  if (request.method === 'OPTIONS') {
    return new NextResponse(null, {
      status: 204,
      headers: {
        'Access-Control-Allow-Origin': 'https://yourapp.com',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization',
        'Access-Control-Max-Age': '86400',
      },
    });
  }
  const response = NextResponse.next();
  response.headers.set('Access-Control-Allow-Origin', 'https://yourapp.com');
  return response;
}

export const config = { matcher: '/api/:path*' };
Test your Vercel CORS config live →