Reference

The "look it up fast" companion to the course. Three things live here: a glossary of the terms every page on this site uses, two reference tables of the CORS headers themselves, and a decision flowchart that walks "will this cross-origin request succeed?" end to end. Page 4 (The headers) teaches these slowly, in prose with a live playground; this page is the index you scan when you already know what you're looking for.

A note on which spec governs what, because the site is precise about this and the search results are not: CORS itself is a mechanism of the WHATWG Fetch Standard — there is no separate "CORS RFC". The notion of an origin (scheme + host + port) is defined by RFC 6454. The CORS-safelisted request/response headers are enumerated by the Fetch Standard too. The WebSocket handshake — relevant to page 10's demo — is not a Fetch mechanism: it is governed by the WebSocket section of the WHATWG HTML spec together with RFC 6455. Citing "the CORS RFC" is always wrong.

Glossary

These definitions match how the terms are used across Mental model, The headers, Credentials, and Opaque responses — not reinvented here.

Origin
A scheme, a host, and a port together — never the path, query, or fragment. https://www.example.com and http://www.example.com are different origins (scheme); so are https://a.example.com and https://b.example.com (host); so are two services on different ports of one host. Defined by RFC 6454.
Same-origin
Sharing all three of scheme, host, and port. The browser's default rule — the Same-Origin Policy — lets a page read any response from its own origin freely.
Cross-origin
Differing in scheme, host, or port. Reading a cross-origin response is what CORS gates; the request is still sent, and the server still processes it — only the page's JavaScript is withheld the result unless the server opted in.
Same-site vs. cross-site
A coarser boundary than origin: two hosts are the same site when they share a registrable domain. a.example.com and b.example.com are different origins but the same site. Cookies are site-scoped (this is what SameSite keys on); CORS is origin-scoped. A request can be same-site yet still cross-origin — the split-domain case this whole site demos.
Registrable domain
The "site" a host reduces to: the public suffix plus one label (the eTLD+1), computed against the Public Suffix List. For www.example.com it is example.com; for api.www.corslabs.com it is corslabs.com. This is why every lab origin in this project is the same site when deployed.
Simple request
A request the browser sends without a preflight: a CORS-safelisted method (GET, HEAD, or POST) carrying no headers outside the CORS-safelisted set and a safelisted Content-Type (application/x-www-form-urlencoded, multipart/form-data, or text/plain). Only the Origin request header carries the CORS conversation for these.
Preflight / preflighted request
An OPTIONS request the browser sends before the real request whenever the real request is not "simple". It carries Access-Control-Request-Method and Access-Control-Request-Headers; the server answers with its allowances, and only if they cover the real request does the browser send the real request at all.
CORS-safelisted request header
A request header the browser will send cross-origin without promoting the request to a preflight: Accept, Accept-Language, Content-Language, Content-Type (for the three safelisted values), and a small set of others enumerated by the Fetch Standard. Any header outside this list is what makes a request "non-simple" and triggers a preflight.
CORS-safelisted response header
A response header JavaScript may read cross-origin by default: Cache-Control, Content-Language, Content-Length, Content-Type, Expires, Last-Modified, and Pragma. Every other response header returns null from response.headers.get() unless the server lists it in Access-Control-Expose-Headers — even though it is genuinely on the response (visible in the Network tab).
Opaque response
The Response JavaScript receives from a fetch() made with mode: "no-cors": its type is "opaque", status is 0, no headers are readable, and the body is unreachable. The request was still sent and the server still processed it — the browser simply gutted what it hands your code. "Just add no-cors" is a common, wrong fix for a CORS error: it looks like it worked, but your code gets nothing.
Credentialed request
A request that carries cookies or HTTP authentication. In fetch() this requires credentials: "include" (or "same-origin"). For the browser to let the page read a credentialed cross-origin response, the server must send Access-Control-Allow-Credentials: true and a non-wildcard Access-Control-Allow-Origin (the exact origin, never *).
The null origin
The origin serialized as the literal string null, sent by sandboxed iframes (without allow-same-origin), data: URLs, file: origins, and redirects from opaque origins. It is not a wildcard and not the same as no Origin header — a server that allows null in Access-Control-Allow-Origin is opting in to all of these, which is almost always a mistake. See Special origins.

Request headers the browser sends

Three headers carry the CORS conversation, and only on the right kinds of request. A simple request sends just Origin; the other two appear exclusively on the OPTIONS preflight.

CORS request headers — what the browser attaches, and when.
Header Sent when Meaning & gotcha
Origin Every cross-origin request (simple and preflighted). The page's origin (scheme + host + port), never the path. The server compares this against its allowlist to decide whether to opt in. Gotcha: a courtesy header, not authentication — browsers set it, but curl and any non-browser forge it freely.
Access-Control-Request-Method Preflight only. The method the real request wants to use, so the server can approve it in advance.
Access-Control-Request-Headers Preflight only. Comma-list of the non-safelisted headers the real request will carry. Gotcha: never echo this verbatim into Access-Control-Allow-Headers — that reflects a visitor-supplied value straight into a response header. Match it against a fixed allowlist instead.

Response headers the server sends back

The server's opt-in. Each governs a distinct part of the decision; Access-Control-Allow-Origin is the one that decides a simple request, while the others are preflight-only or govern what JavaScript may read off the actual response.

CORS response headers — the server's opt-in, by phase.
Header Relevant in Meaning & gotcha
Access-Control-Allow-Origin Simple response, actual response, and preflight response. The single origin allowed to read, or the literal * wildcard. Absent, and the read is blocked. Gotcha: must match the request's Origin byte-for-byte — a trailing slash, an explicit default port, or uppercase scheme all fail to match; and * is rejected entirely when credentials are involved.
Access-Control-Allow-Methods Preflight response only. The methods the server permits. If the real request's method isn't listed, the browser never sends the real request.
Access-Control-Allow-Headers Preflight response only. The request headers the server permits, answering Access-Control-Request-Headers. Gotcha: hold a fixed allowlist; never reflect the incoming request-header list back verbatim.
Access-Control-Allow-Credentials Preflight response and actual response. The single literal token true; its presence lets a credentialed request read the response. It is never false — absence is how "no" is said. Gotcha: combined with Access-Control-Allow-Origin: *, the browser rejects the credentialed read outright — a wildcard grant cannot authorise a credentialed request.
Access-Control-Max-Age Preflight response only. How many seconds the browser may cache the preflight's answer, so it doesn't re-ask before every request. A performance header, not a security one. Gotcha: browsers cap the cached duration per engine (often a few minutes to ~24 h) regardless of the value sent — a huge Max-Age is not honoured literally.
Access-Control-Expose-Headers Actual response only. Which response headers JavaScript may read beyond the CORS-safelisted set. Gotcha: the quietest trap in CORS — a header can be fully on the response (visible in the Network tab) and still return null from response.headers.get() unless it is listed here. Not a block, just a silent withhold.
Vary Any response. Not CORS-specific, but load-bearing here: it tells shared caches which request headers select a different response. Gotcha: when the server returns a different Access-Control-Allow-Origin per requesting origin, Vary: Origin is mandatory — omit it and a CDN may serve origin A's allowed response to origin B.

Decision flowchart: will this cross-origin request succeed?

The whole mechanism as one walk: same-origin? simple or preflighted? preflight passes? the response grants access? — and, for credentialed requests, an explicit credentials grant. Each branch ends in a clear succeed or blocked outcome. Solid green arrows are paths that succeed; dashed red arrows are paths the browser blocks.

Is the request same-origin? Is it a “simple” request? Preflight (OPTIONS) passes? Access-Control-Allow-Origin matches Origin exactly? Credentialed request? (cookies / HTTP auth) Allow-Credentials: true AND ACAO is the exact origin? Succeeds same-origin — CORS n/a Blocked preflight failed — actual request never sent Blocked response withheld from JavaScript Blocked credentialed read not allowed Succeeds response readable by JavaScript no no yes yes yes yes yes no no no yes — simple, no preflight no — not credentialed

Two simplifications worth naming. The chart treats the preflight cache as invisible — a cached preflight answer still "passes" without a new OPTIONS on the wire (see Caching & Vary). And it treats Access-Control-Expose-Headers as a separate concern from whether the read succeeds: a request can pass every branch here and still have specific response headers return null unless they are exposed (see The headers).

← Back home