The course
// cross-origin resource sharing // paste the symptom, find the rule // start where you are
CORS, from first principles.
Cross-Origin Resource Sharing is the browser's rule for when one web origin may read another's response. It is widely misunderstood — and almost always, the confusion is about where the rule is enforced. This site teaches CORS by showing you the actual requests and responses, in the browser, as they happen.
Free, pro-bono, and still growing. Built by Precisit.
Every page in the course below runs real cross-origin requests against
a live demo API and shows the browser's actual verdict — nothing is
faked or simulated. The final chapters (10–12) are still on the way.
Diagnose your error
Choose the browser whose console message you saw, then open the matching Error Gallery exhibit.
Chrome console messages
- No Access-Control-Allow-Origin (actual response)TypeError; the server received the request
- No Access-Control-Allow-Origin (preflight response)TypeError; only the OPTIONS preflight arrived
- Access-Control-Allow-Origin doesn't matchTypeError; the response carried the wrong origin
- Multiple Access-Control-Allow-Origin valuesTypeError; the Fetch spec rejects a multi-value ACAO outright
- Wildcard ACAO turns literal under credentialsTypeError; the wildcard can never satisfy a credentialed request
- Access-Control-Allow-Headers doesn't cover a custom headerTypeError; only the OPTIONS preflight arrived
- Access-Control-Allow-Methods doesn't cover the methodTypeError; only the OPTIONS preflight arrived
- Preflight answers with a non-2xx statusTypeError; the preflight itself was rejected (401, or 404 in the toggle)
- Preflight response is a redirectTypeError; the browser never follows a redirected preflight
- mode: 'no-cors' — an opaque response isn't a successfetch() resolves — opaque: status 0, no headers, unreadable body
- The preflight passes, but the actual response forgets ACAOTypeError, after both round trips arrived — the two-checkpoint surprise
- A response header is present but not exposed to JavaScriptfetch() resolves, body readable, but X-Corslabs-Demo is invisible to JS
What's your situation?
Pick the description closest to your problem for a suggested starting page.
- P1The API owner: my API works perfectly from backends, curl, and Postman — but web customers report failures in the browserStart with 1 · Mental model
- P2The frontend dev vs. a backend-only API: I'm calling an API that was never intended for browser consumption, and it failsStart with 1 · Mental model
- P3The third-party API integrator: the provider supports CORS but requires configuration — an allowed-origins list, exact origin strings, not
*Start with 1 · Mental model - P4The split-domain team: our own frontend and API live on different (sub)domains and requests fail — often only with cookies, or only in some browsersStart with 1 · Mental model
- P5The "it worked in dev" dev: everything worked locally (dev-server proxy!) and broke on deploy; or works in Chrome, not Safari; or fails intermittently (cache)Start with 8 · Caching & Vary
- P6The security-curious: is
*dangerous? Does CORS protect my API? What's the CSRF connection?Start with 2 · Simple requests