[▲ Vercel Community](/) · [Categories](/categories) · [Latest](/latest) · [Top](/top) · [Live](/live)

[Discussions](/c/community/4)

# Different ways to handle CORS on Vercel

1206 views · 8 likes · 2 posts


Anshuman Bhardwaj (@anshumanb) · 2025-01-31 · ♥ 6

Cross-Origin Resource Sharing ([CORS](https://developer.mozilla.org/en-US/docs/Glossary/CORS)) issues are common when you are hosting your backend and frontend applications on different [origins](https://developer.mozilla.org/en-US/docs/Glossary/Origin). Browsers implement the CORS mechanism as a safeguard to prevent applications on a different origin from loading your resources. This is why it is important to set up your backend application with the correct CORS configuration.

## Getting Started
---

When using Vercel, you can configure CORS headers in the following ways:

- Using the Vercel project configuration
- Using the Edge Middleware
- Using framework configuration
- Route handler configuration

> This post uses the code snippets from the [cors-example GitHub repository](https://github.com/vercel-support/cors-examples), which showcases working examples of CORS configuration in popular web frameworks such as Next.js, Nuxt, Astro, and Flask deployed on Vercel.
> 

### Using the Vercel project configuration

You can use the [headers](https://vercel.com/docs/projects/project-configuration#headers) configuration option in the `vercel.json` file of your project to add CORS headers. For example, the following configuration will add the CORS headers to all responses from the `/vercel-config-cors` endpoint.

```jsx
{
  "headers": [
    {
      "source": "/vercel-config-cors",
      "headers": [
        {
          "key": "Access-Control-Allow-Origin",
          "value": "https://rrv7.vercel.app"
        },
        {
          "key": "Access-Control-Allow-Methods",
          "value": "GET, POST, PUT, DELETE, OPTIONS"
        },
        {
          "key": "Access-Control-Allow-Headers",
          "value": "Content-Type, Authorization"
        }
      ]
    }
  ]
}
```

### Using the Edge Middleware

The [Edge Middleware](https://vercel.com/docs/functions/edge-middleware) provides a fast and efficient way to modify headers on the requests and responses of your applications. For example, the [middleware.ts](https://github.com/vercel-support/cors-examples/blob/main/astro-app/middleware.ts) from an Astro project adds the appropriate CORS headers to the requests coming to the `/mw-cors` endpoint without changing the endpoint handler code. To view the complete code, see this [GitHub repository](https://github.com/vercel-support/cors-examples/blob/main/astro-app/middleware.ts).

```jsx
import { next } from "@vercel/edge";

const allowedOrigins = ["https://rrv7.vercel.app"];

const corsOptions = {
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
  "Access-Control-Allow-Headers": "Content-Type, Authorization",
};

export default function middleware(request: Request) {
  // Check the origin from the request

  const origin = request.headers.get("origin") ?? "";
  const isAllowedOrigin = allowedOrigins.includes(origin);

  // Handle preflighted requests
  const isPreflight = request.method === "OPTIONS";

  if (isPreflight) {
    const preflightHeaders = {
      ...(isAllowedOrigin && { "Access-Control-Allow-Origin": origin }),
      ...corsOptions,
    };

    return Response.json({ preflight: true }, { headers: preflightHeaders });
  }

  // Handle simple requests
  const response = new Response();

  if (isAllowedOrigin) {
    response.headers.set("Access-Control-Allow-Origin", origin);
  }

  Object.entries(corsOptions).forEach(([key, value]) => {
    response.headers.set(key, value);
  });

  return next(response);
}

export const config = {
  matcher: "/mw-cors",
};
```

### Using framework configuration

Many frameworks such as [Next.js](https://nextjs.org/) and [Nuxt](http://nuxt.com/) provide easy APIs to add CORS headers from the config file. For example, the following [nuxt.config.ts](https://github.com/vercel-support/cors-examples/blob/main/nuxt-app/nuxt.config.ts) sets `routeRules` for a specific route (`/api/nuxt-config-cors`) to send the CORS headers automatically for all the requests made to this endpoint.

```jsx
export default defineNuxtConfig({
  compatibilityDate: "2024-11-01",
  devtools: { enabled: true },
  routeRules: {
    "/api/nuxt-config-cors": {
      headers: {
        "Access-Control-Allow-Origin": "https://rrv7.vercel.app",
        "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
        "Access-Control-Allow-Headers": "Content-Type, Authorization",
      },
    },
  },
});
```

### Route handler configuration

At last, you can always return the CORS headers from the route handler response. For example, the following [Next.js route handler](https://github.com/vercel-support/cors-examples/blob/main/nextjs-app/src/app/api/route.ts) adds the headers to the endpoint response.

```tsx
export async function GET() {
  return new Response("Hello, Next.js!", {
    status: 200,
    headers: {
      "Access-Control-Allow-Origin": "https://rrv7.vercel.app",
      "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type, Authorization, X-Custom-Header",
    },
  });
}
```

## Troubleshooting common issues
---

### Incorrect allow origin header

The [Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) lets the server define which origin is allowed to send a cross-origin request. It is important to ensure that the [origin](https://developer.mozilla.org/en-US/docs/Glossary/Origin) value must matches all three aspects: scheme, hostname, and port of the incoming request’s `Origin` header. 

### Incorrect HTTP methods

The [Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods) header tells the browser about the HTTP methods that the server supports. For example, it can become an issue when your frontend application is making an HTTP request that triggers a [Preflight request](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) and you don’t support the `OPTIONS` request method, which is used by browsers to check if CORS is supported.

### Missing allowed headers

It’s common to overlook the additional headers or custom headers that your frontend application might be sending along with the requests to your backend. The [Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers) header lets your server define a list of headers that are allowed for cross-origin requests.

### Missing credentials header

By default, CORS doesn’t allow `cookies` with cross-origin requests, which will lead to errors in your application. To allow credentials to be sent with your requests you need to:

1. Allow credentials on CORS in your server code by sending the [Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials) header. For example, the following Flask application specifies `supports_credentials=True` to allow sending credentials.
    
    ```python
    from flask import Flask
    from flask_cors import CORS
    
    app = Flask(__name__)
    CORS(app, supports_credentials=True, resources={r"/api/cors": {"origins": "https://rrv7.vercel.app"}})
    ```
    
2. Update your `fetch` call to include `credentials` with the request, as follows:
    
    ```tsx
        const response = await fetch(url, {
          method: 'GET',
          credentials: 'include', // This tells fetch to include credentials
          headers: {
            'Content-Type': 'application/json',
          }
        });
    ```
    

## Resources

---

- https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
- https://github.com/vercel-support/cors-examples
- https://github.com/vercel-support/express-vercel


Pauline P. Narvas (@pawlean) · 2025-04-23 · ♥ 2

Spotted this in the wild too! Sharing in case it's helpful → 
https://dev.to/nurulislamrimon/resolving-cors-errors-in-a-nestjs-app-deployed-on-vercel-jb