You build an awesome Next.js API route under `app/api/data/route.ts` and test it with Postman — it works perfectly. But the moment you try to fetch it from a different origin, domain, or mobile app, the browser blocks it and throws an angry console error:
`Access to fetch at 'https://api.site.com/endpoint' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.`
This is a CORS (Cross-Origin Resource Sharing) block. Browsers enforce this security mechanism to prevent unauthorized websites from accessing your endpoints. To allow access, your API must explicitly declare which origins are permitted.
TL;DR - Quick CORS Headers Fix
- 1Are you calling a serverless function on a different domain without specifying headers?
- 2Have you enabled preflight OPTIONS requests on your custom API endpoints?
- 3Are you missing the Access-Control-Allow-Origin header in your response?
Root Causes
Missing Access-Control-Allow-Origin Header
Your serverless Next.js endpoint does not return the correct HTTP headers authorizing the client's domain to access the resources.
fetch('https://yoursite.com/api/data') // calls origin with no headersUnconfigured OPTIONS Preflight Request
Browsers automatically send a preflight OPTIONS request before making complex requests (like POST with JSON content or custom headers). If your Next.js route returns a 405 or 404 for OPTIONS, the primary request is blocked.
export async function OPTIONS() { // Route must return status 200 with headers }Incorrect Header Spelling or Syntax
Declaring multiple origins inside a single 'Access-Control-Allow-Origin' header (like 'origin1, origin2') or misspelling common terms will invalidate the browser policy validation.
Step-by-Step Fix Guide
Add Headers to Individual Route Handlers
For targeted APIs, set headers inside your route's Response constructor. Be sure to handle the preflight OPTIONS request.
import { NextResponse } from 'next/server';
const CORS_HEADERS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
};
export async function OPTIONS() {
return NextResponse.json({}, { headers: CORS_HEADERS });
}
export async function GET() {
return NextResponse.json({ success: true }, { headers: CORS_HEADERS });
}Configure Global CORS in next.config.mjs
If you want all API routes to automatically support CORS without modifying individual files, define headers in your next.config configuration.
const nextConfig = {
async headers() {
return [
{
source: '/api/:path*',
headers: [
{ key: 'Access-Control-Allow-Credentials', value: 'true' },
{ key: 'Access-Control-Allow-Origin', value: '*' },
{ key: 'Access-Control-Allow-Methods', value: 'GET,DELETE,PATCH,POST,PUT,OPTIONS' },
{ key: 'Access-Control-Allow-Headers', value: 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version, Authorization' },
]
}
]
}
};Use Middleware for Dynamic Allowed Origins
If you need to dynamically check if the requesting origin is on an approved list (rather than using wildcard '*'), configure it in middleware.
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
const ALLOWED_ORIGINS = ['https://myapp.com', 'https://admin.myapp.com'];
export function middleware(req: NextRequest) {
const origin = req.headers.get('origin');
const response = NextResponse.next();
if (origin && ALLOWED_ORIGINS.includes(origin)) {
response.headers.set('Access-Control-Allow-Origin', origin);
}
return response;
}Stuck on CORS or API Integration Issues?
Configuring secure cross-origin headers or middleware filters can be tedious. I can configure your Next.js route security to prevent blocks.
Get API Rescue HelpRelated Errors
Access-Control-Allow-Origin cannot contain wildcard when credentials mode is include.
If credentials (like cookies or authentication headers) are needed, you must set Access-Control-Allow-Origin to the specific requesting origin value rather than '*'
Prevention Strategy
- Always define an OPTIONS handler for complex endpoints.
- Do not use wildcards '*' in production environments if cookies or session authorization headers are transmitted.
- Keep cors headers centralized inside next.config.mjs or middleware.ts to avoid code duplication errors.
Still Stuck With This Issue?
Send your exact error message or deployment issue. I'll respond with a targeted fix.
Need a Deeper Fix?
Describe your full project issue below and I'll get back to you with a targeted fix.