Solving CORS Issues in Next.js 13 with API Routes

By: O. Wolfson

Next.js, the open-source React framework developed by Vercel, has recently released its 13th version. As an outstanding development tool, it offers a wide range of functionalities, including API routes. However, if you've been exploring this feature, you might have come across some CORS (Cross-Origin Resource Sharing) issues. This problem generally appears when dealing with POST requests on a publicly available API. But don't worry; there's a solution to handle it efficiently.

In this article, we will delve into a method for handling CORS issues in Next.js 13 API routes, particularly for POST requests.

Setting up Middleware for CORS Handling

The first thing you need to do is set up a middleware to handle CORS at the root of your project. Middleware allows us to handle requests and responses in a way we see fit, especially when it comes to setting specific headers.

Create a new file named middleware.ts in the root of your project and add the following code:

import { NextResponse } from "next/server";

export function middleware(req: Request) {
  const origin = req.headers.get("origin");
  console.log("origin:", origin);

  const response =;
  response.headers.set("Access-Control-Allow-Origin", "*");
    "Content-Type, Authorization"
  response.headers.set("Access-Control-Allow-Credentials", "true");
  response.headers.set("Access-Control-Max-Age", "86400");

  return response;

export const config = {
  matcher: "/api/:path*",

This middleware function performs several important tasks:

  • It retrieves the origin from the request headers, which is crucial for identifying the origin of the incoming request.
  • It creates a new response object using
  • It sets several necessary headers on the response, such as Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Credentials, and Access-Control-Max-Age.
  • Finally, it logs that the middleware has been executed and returns the updated response.

Note that the config export sets the matcher to apply this middleware to all API routes.

Setting Up an API Route

The second step is setting up the API route itself. Next.js provides the ability to create serverless functions as API routes, and we can use this functionality to accept POST requests.

Set up your API route file (e.g., app/api/test/route.ts), using the following structure:

import { NextResponse, NextRequest } from "next/server";

export async function POST(req: NextRequest) {
  try {
    const { email, project } = await req.json();

    // you can now use the `email` and `project` values from the request body
    const data = {
      name: "John Doe",
      age: 25,

    return NextResponse.json(data);
  } catch (error) {
    // handle error
    return NextResponse.error();

The POST function will be called whenever a POST request is made to this API route. The request body is parsed using req.json(), and the data can be extracted and used as required.

In case of an error, we catch it, log it to the console, and return an error response using NextResponse.error().

Here is the request. Note that we are using the fetch API to make the request:

const response = await fetch("/api/test", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  body: JSON.stringify({
    email: "",
    project: "123456",

Wrapping Up

By now, you should have a functioning Next.js API route that can handle POST requests without any CORS issues.