CORS in NextJS: Complete Guide to Fix your Errors (2025)


Ever been blocked by a CORS error while building your NextJS app? You're not alone. CORS issues in NextJS are like that friend who shows up uninvited to your party—frustrating but ultimately there for your own good.
I remember building my first NextJS project thinking everything would just work. Then boom—CORS errors everywhere. My API requests were failing, my data wasn't loading, and I was questioning my life choices.
Let's fix your CORS nextjs problems once and for all.
Configuring CORS NextJS Globally with next.config.js Headers
Setting up CORS in your NextJS project doesn't have to be a nightmare. The simplest approach? Configure it globally using your next.config.js file.
// next.config.js
module.exports = {
async headers() {
return [
{
// Apply these headers to all routes
source: '/(.*)',
headers: [
{
key: 'Access-Control-Allow-Origin',
value: '*', // Be more restrictive in production
},
{
key: 'Access-Control-Allow-Methods',
value: 'GET,OPTIONS,PATCH,DELETE,POST,PUT',
},
{
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',
},
],
},
];
},
};
This approach works great for simple projects, but when you need more control, middleware is your best friend.
Dynamic CORS Policies in NextJS Using Middleware
NextJS 12+ introduced middleware, giving us superpowers for handling CORS dynamically.
// middleware.js
import { NextResponse } from 'next/server';
export function middleware(request) {
// Get the origin from the request
const origin = request.headers.get('origin') || '';
// Define allowed origins (you could load these from env variables)
const allowedOrigins = [
'https://yourdomain.com',
'https://app.yourdomain.com',
'http://localhost:3000',
];
// Check if the origin is allowed
const isAllowedOrigin = allowedOrigins.includes(origin);
// Create the response
const response = NextResponse.next();
// Set CORS headers conditionally
if (isAllowedOrigin) {
response.headers.set('Access-Control-Allow-Origin', origin);
response.headers.set('Access-Control-Allow-Credentials', 'true');
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');
}
// Handle OPTIONS request (preflight)
if (request.method === 'OPTIONS') {
return new NextResponse(null, {
status: 204,
headers: response.headers
});
}
return response;
}
// Only run the middleware on API routes
export const config = {
matcher: '/api/:path*',
};
This middleware approach gives you fine-grained control over your CORS policies. I've used this pattern on multiple projects, and it's been rock solid.
Advanced CORS NextJS Strategies: Whitelisting Origins and Credentials
When you're building more complex applications, you'll need more sophisticated CORS strategies.
Here's what I do for production apps that need tight security:
// Environment variables approach
// .env.local
ALLOWED_ORIGINS=https://app.example.com,https://admin.example.com
// middleware.js or api handler
const allowedOrigins = process.env.ALLOWED_ORIGINS.split(',');
This way, you can manage your whitelist through environment variables without hardcoding them.
For handling credentials properly:
// Remember to set these headers
response.headers.set('Access-Control-Allow-Credentials', 'true');
And on your frontend:
fetch('https://api.example.com/data', {
credentials: 'include' // This sends cookies
})
Deploying CORS NextJS Apps on Vercel: Best Practices
Deploying to Vercel? Here's what you need to know about CORS nextjs on their platform:
- Vercel respects your next.config.js headers configuration
- Environment variables work seamlessly for dynamic origins
- Preview deployments need special attention for CORS:
// Dynamically handle Vercel preview deployments
const vercelEnv = process.env.VERCEL_ENV;
let allowedOrigins = ['https://yourdomain.com'];
if (vercelEnv === 'preview') {
// Allow Vercel preview URLs
allowedOrigins.push(/.*\.vercel\.app$/);
}
I've spent hours debugging CORS issues on Vercel only to realize my preview environments needed different settings.
Resolving Common CORS NextJS Errors During Development
The most common CORS error you'll see is:
🚨 Access to fetch at 'http://localhost:3000/api/data' from origin 'http://localhost:3001' has been blocked by CORS policy 🚨
To fix CORS nextjs errors during development:
- Make sure your development server has CORS enabled:
// pages/api/your-endpoint.js
export default function handler(req, res) {
// Enable CORS for development
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
// Handle OPTIONS request
if (req.method === 'OPTIONS') {
return res.status(200).end();
}
// Your actual handler code
// ...
}
2. Use a CORS proxy for external APIs during development:
// Instead of fetching directly
// const data = await fetch('https://external-api.com/data');
// Use your API route as a proxy
const data = await fetch('/api/proxy/external-api');
// Then in pages/api/proxy/external-api.js
export default async function handler(req, res) {
const response = await fetch('https://external-api.com/data');
const data = await response.json();
res.status(200).json(data);
}
This proxy approach has saved me countless headaches when dealing with third-party APIs.
CORS NextJS and Authentication: Securing Cookies and Tokens
When dealing with authentication and CORS, you need to be extra careful:
// For token-based auth, you typically need these CORS headers
res.setHeader('Access-Control-Allow-Origin', 'https://yourdomain.com');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Allow-Headers', 'Authorization');
For secure cookie handling:
// Setting secure cookies that work across domains
res.setHeader('Set-Cookie', [
`token=${token}; HttpOnly; Secure; SameSite=None; Path=/; Max-Age=${60 * 60 * 24 * 7}`
]);
This setup works for most auth systems I've built, but remember that SameSite=None requires Secure to be set as well.
Optimizing CORS NextJS for SEO and Crawler Accessibility
Search engines need to access your APIs? Make sure your CORS settings allow it:
// Handle user agents for crawlers
const userAgent = req.headers['user-agent'] || '';
const isCrawler = /googlebot|bingbot|baiduspider/i.test(userAgent);
if (isCrawler) {
// Allow access for search engine crawlers
res.setHeader('Access-Control-Allow-Origin', '*');
}
This helps ensure that search engines can properly index your dynamic content.
CORS NextJS vs Alternative Frameworks
How does NextJS handle CORS compared to other frameworks?
NextJS vs Express:
- NextJS has built-in API routes with simpler CORS configuration
- Express gives more middleware flexibility but requires more setup
NextJS vs NestJS:
- NestJS has a built-in @Cors() decorator
- NextJS requires manual configuration
NextJS vs Remix:
- Remix handles CORS through its loader/action system
- NextJS uses API routes or middleware
In terms of performance, NextJS's middleware approach is extremely efficient as it runs before the request is fully processed.
The Future of CORS NextJS: New Features and Updates
NextJS 15 introduced some improvements for CORS handling:
// next.config.js in NextJS 15
module.exports = {
async headers() {
return [
{
source: '/api/:path*',
headers: [
{ key: 'Access-Control-Allow-Origin', value: '*' },
// Other headers
],
},
];
},
}
To enable CORS next js 15 properly, you can also use the new middleware capabilities:
// middleware.ts in NextJS 15
export default function middleware(request) {
const response = NextResponse.next();
// You can now use new response header manipulation methods
response.headers.set('Access-Control-Allow-Origin', '*');
return response;
}
The new app router in NextJS also changes how we handle CORS:
// app/api/route.js
export async function GET(request) {
const response = new Response(JSON.stringify({ message: 'Hello' }));
// Set CORS headers
response.headers.set('Access-Control-Allow-Origin', '*');
return response;
}
export async function OPTIONS(request) {
const response = new Response(null, { status: 204 });
response.headers.set('Access-Control-Allow-Origin', '*');
response.headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
response.headers.set('Access-Control-Allow-Headers', 'Content-Type');
return response;
}
Stay updated on the NextJS docs for future CORS improvements.
Implementing proper CORS in NextJS isn't just about fixing errors—it's about building secure, robust applications. Follow these patterns, and you'll save yourself hours of debugging and security headaches.
Remember: CORS nextjs isn't your enemy—it's your app's security guard. Treat it with respect, configure it properly, and it'll keep your users safe while letting legitimate requests through.
Hi! 👋🏻 Need a website for your business?
- Slow Loading Speed
- Hard to Use on Phones
- Confusing Layout
- Messy Design
- Not Secure
- Doesn't show on Google
- Can't edit Website Content
- Quick to Load
- Mobile Friendly
- Easy Navigation
- Clean and Organized
- Secure and Safe
- Easy to Find on Google (SEO)
- Easy to edit Website Content
What are you waiting for?
Get a website that looks great and lets you update content easily no coding needed! Grow your business online with Fastasy
Get started