Fix CORS in Next.js

Last updated: April 2026

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

Next.js API routes and App Router route handlers need CORS headers set explicitly. There is no global CORS config โ€” set headers in each handler or use middleware.

Test your Next.js CORS live โ†’

App Router โ€” route.ts handler

// app/api/data/route.ts
import { NextRequest, NextResponse } from 'next/server';

const corsHeaders = {
  'Access-Control-Allow-Origin': 'https://yourapp.com',
  'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
  'Access-Control-Allow-Headers': 'Content-Type, Authorization',
};

export async function OPTIONS() {
  return NextResponse.json({}, { headers: corsHeaders });
}

export async function GET(req: NextRequest) {
  const data = { message: 'ok' };
  return NextResponse.json(data, { headers: corsHeaders });
}

Pages Router โ€” API route (pages/api/data.ts)

import type { NextApiRequest, NextApiResponse } from 'next';

export default function handler(req: NextApiRequest, res: NextApiResponse) {
  res.setHeader('Access-Control-Allow-Origin', 'https://yourapp.com');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');

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

  res.status(200).json({ message: 'ok' });
}

Middleware โ€” apply CORS to all API routes

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

export function middleware(req: NextRequest) {
  const origin = req.headers.get('origin') ?? '';
  const allowed = ['https://yourapp.com', 'http://localhost:5173'];

  const res = NextResponse.next();

  if (allowed.includes(origin)) {
    res.headers.set('Access-Control-Allow-Origin', origin);
    res.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
    res.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
    res.headers.set('Access-Control-Allow-Credentials', 'true');
  }

  if (req.method === 'OPTIONS') {
    return new NextResponse(null, { status: 204, headers: res.headers });
  }

  return res;
}

export const config = {
  matcher: '/api/:path*',
};

vercel.json โ€” headers for static CORS

{
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        { "key": "Access-Control-Allow-Origin", "value": "https://yourapp.com" },
        { "key": "Access-Control-Allow-Methods", "value": "GET, POST, OPTIONS" },
        { "key": "Access-Control-Allow-Headers", "value": "Content-Type" }
      ]
    }
  ]
}
📚 HttpFixer Blog โ€” fix guides, explainers, and references โ†’