Zero Signup ToolsFree browser tools

Developer Tools

CORS Headers Generator

Build a valid CORS response: Allow-Origin, Allow-Methods, Allow-Headers, Credentials, Expose-Headers, Max-Age, and Vary. Live validation plus server snippets.

Quick presets

Tap a preset to load a common CORS pattern. Tweak any field afterward.

Allowed origin

Which page may read the response. Required.

Allowed methods

HTTP methods the browser may use on cross-origin requests. OPTIONS is always added for preflight.

Custom request headers the page may send. Common ones below act as quick adds.

Response headers JavaScript may read. Without this, only the seven CORS-safelisted response headers are visible.

Credentials

Sends cookies and Authorization on cross-origin calls. Requires an exact origin.

Vary: Origin

Required when the Allow-Origin value depends on the request Origin (reflect or allowlist).

How long the browser may cache the OPTIONS response. Chromium caps at 7200s.

Response headers

Return these on every actual cross-origin response (GET, POST, etc.).

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true

Preflight response (OPTIONS)

Return these on OPTIONS requests with a 204 No Content status.

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 600

What this policy does

  • Only https://app.example.com may read this response. Other origins will see a CORS error in the browser console.
  • Cookies and Authorization headers are allowed on cross-origin requests. The fetch caller must use credentials: 'include'.
  • Allowed methods on this endpoint: GET, POST, OPTIONS.
  • Custom request headers allowed during preflight: Content-Type, Authorization.
  • Only the CORS-safelisted response headers are readable from JavaScript (Cache-Control, Content-Language, Content-Length, Content-Type, Expires, Last-Modified, Pragma). Anything else needs Access-Control-Expose-Headers.
  • Browsers may cache the preflight result for 10 minutes, skipping the OPTIONS call for that long. Chromium clamps to 7200s, Firefox to 86400s, Safari to 600s.

Server snippets

Drop-in configuration for the runtime you actually ship to.

Raw response headers (cross-origin GET / POST)

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true

Raw preflight response (OPTIONS)

Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 600

Apache (.htaccess / VirtualHost)

<IfModule mod_headers.c>
  Header set Access-Control-Allow-Origin "https://app.example.com"
  Header set Access-Control-Allow-Credentials "true"
  Header set Access-Control-Allow-Methods "GET, POST, OPTIONS"
  Header set Access-Control-Allow-Headers "Content-Type, Authorization"
  Header set Access-Control-Max-Age "600"
</IfModule>

Nginx

add_header Access-Control-Allow-Origin "https://app.example.com" always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;
add_header Access-Control-Max-Age "600" always;

# Short-circuit preflight:
if ($request_method = OPTIONS) {
  return 204;
}

Vercel (vercel.json)

{
  "headers": [
    {
      "source": "/api/*",
      "headers": [
        {
          "key": "Access-Control-Allow-Origin",
          "value": "https://app.example.com"
        },
        {
          "key": "Access-Control-Allow-Credentials",
          "value": "true"
        },
        {
          "key": "Access-Control-Allow-Methods",
          "value": "GET, POST, OPTIONS"
        },
        {
          "key": "Access-Control-Allow-Headers",
          "value": "Content-Type, Authorization"
        },
        {
          "key": "Access-Control-Max-Age",
          "value": "600"
        }
      ]
    }
  ]
}

Netlify (_headers file)

/api/*
  Access-Control-Allow-Origin: https://app.example.com
  Access-Control-Allow-Credentials: true
  Access-Control-Allow-Methods: GET, POST, OPTIONS
  Access-Control-Allow-Headers: Content-Type, Authorization
  Access-Control-Max-Age: 600

Next.js (next.config.js)

// next.config.js / next.config.ts
module.exports = {
  async headers() {
    return [
      {
        source: "/api/*",
        headers: [
        { key: "Access-Control-Allow-Origin", value: "https://app.example.com" },
        { key: "Access-Control-Allow-Credentials", value: "true" },
        { key: "Access-Control-Allow-Methods", value: "GET, POST, OPTIONS" },
        { key: "Access-Control-Allow-Headers", value: "Content-Type, Authorization" },
        { key: "Access-Control-Max-Age", value: "600" },
        ],
      },
    ];
  },
};

Cloudflare Worker

export default {
  async fetch(request) {
    const allowOrigin = "https://app.example.com";
    const cors = {
      "Access-Control-Allow-Origin": allowOrigin,
      "Access-Control-Allow-Credentials": "true",
      "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type, Authorization",
      "Access-Control-Max-Age": "600",
    };
    if (request.method === "OPTIONS") {
      return new Response(null, { status: 204, headers: cors });
    }
    const response = await fetch(request);
    const headers = new Headers(response.headers);
    for (const [k, v] of Object.entries(cors)) headers.set(k, v);
    return new Response(response.body, { status: response.status, headers });
  },
};

Express.js middleware

// Plain Express middleware (no cors package required).
app.use((req, res, next) => {
  res.setHeader("Access-Control-Allow-Origin", "https://app.example.com");
  res.setHeader("Access-Control-Allow-Credentials", "true");
  res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
  res.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
  res.setHeader("Access-Control-Max-Age", "600");
  if (req.method === "OPTIONS") return res.sendStatus(204);
  next();
});

How to use

  1. Start with a preset that matches your use case, then tweak the fields: public read-only API, authenticated SPA, allowlist of origins, dev wildcard, image CDN, or webhook callback.
  2. Pick the allowed origin strategy. Use Exact for a single SPA, Reflect from allowlist for several known origins, or Any for fully public APIs. Avoid Reflect any in production.
  3. Check the HTTP methods you allow. OPTIONS is added automatically so the browser preflight always succeeds.
  4. Add custom request headers under Allowed request headers. Authorization and X-CSRF-Token are required for token and CSRF flows; the CORS-safelisted set alone is rarely enough.
  5. Enable Allow-Credentials only if you need cookies or the Authorization header on cross-origin calls. If you do, Allow-Origin must be exact, not the wildcard.
  6. Read the Validation panel and resolve any errors (wildcard with credentials, missing origin, invalid value). Warnings explain edge cases like null origin and per-browser preflight cache caps.
  7. Copy the response and preflight header blocks, or grab the snippet for the runtime you ship to: Apache, Nginx, Vercel, Netlify, Next.js, Cloudflare Workers, or Express.

About this tool

CORS Headers Generator builds the Cross-Origin Resource Sharing response defined by the WHATWG Fetch standard and RFC 6454. The output is the full set of Access-Control-* response headers that a server returns to tell a browser whether and how a cross-origin page may read its responses. The tool covers five origin strategies that match how real apps ship CORS: a wildcard for fully public APIs, an exact origin for a single SPA, an allowlist where the server reflects the request Origin only if it appears on a trusted list, an unrestricted reflect mode for development, and the literal null origin for sandboxed iframes and file:// pages. The validation layer flags the configurations that quietly break in production: Access-Control-Allow-Origin: * combined with Access-Control-Allow-Credentials: true (the browser will refuse the response), Access-Control-Allow-Headers: * with credentials enabled (the wildcard is treated literally), missing Vary: Origin when the Allow-Origin value varies per request (shared caches will serve one origin's allowance to another), invalid origin strings, and Access-Control-Max-Age values higher than what current browsers will honor. The methods picker covers GET, POST, PUT, PATCH, DELETE, HEAD, and OPTIONS, and OPTIONS is added automatically so preflight always succeeds. Common request headers (Content-Type, Authorization, X-CSRF-Token, X-API-Key, X-Requested-With) and exposed response headers (ETag, Location, X-Request-Id, X-RateLimit-*) are one-click chips. Six quick presets seed real-world configurations: public read-only API, authenticated SPA with cookies, multi-origin allowlist, dev wildcard, image and asset CDN, and server-to-server webhook callback. The output panel shows two header blocks side by side: the headers returned on actual cross-origin GET or POST responses, and the headers returned on the OPTIONS preflight, since they overlap but are not identical. A plain English explanation describes what the policy does, which methods and headers the browser will accept, and how long preflight is cached. Drop-in configuration snippets cover Apache (mod_headers with SetEnvIf for allowlists), Nginx (map block and add_header), Vercel vercel.json headers, Netlify _headers, Next.js next.config.js headers, Cloudflare Workers (with allowlist reflection), and a plain Express middleware that needs no extra package. Every header value, origin, and snippet stays in your browser; no preview server, no network calls, no upload.

Free to use. Works in your browser. No signup, no login.

Related tools

You may also like

All tools
All toolsDeveloper Tools