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
- 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.
- 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.
- Check the HTTP methods you allow. OPTIONS is added automatically so the browser preflight always succeeds.
- 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.
- 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.
- 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.
- 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
CSP Header Generator
Visual builder for the Content-Security-Policy HTTP header.
Open tool
DeveloperCache-Control Header Builder
Build and parse Cache-Control headers with directive flags, max-age presets, conflict checks, and ready-to-paste server snippets.
Open tool
DeveloperHTTP Headers Parser
Parse, classify, and decode HTTP headers, with a missing security headers audit.
Open tool
DeveloperAuthorization Header Generator
Build Basic, Bearer, and custom Authorization headers with copy-paste request snippets.
Open tool
DeveloperSet-Cookie Builder
Form-driven Set-Cookie header builder with conflict warnings and server snippets.
Open tool