Why it matters
CORS errors are vague by design: the browser tells your JavaScript almost nothing, and the console message names one problem when there may be three. So developers change server headers by trial and error, often ending with Access-Control-Allow-Origin: * and a new error because the request sends cookies.
This debugger applies the Fetch standard's rules to what you paste, without sending anything. It works out whether the request is simple or needs a preflight, and why (a PUT, an Authorization header, Content-Type: application/json), builds the preflight the browser would send, then checks the preflight and real responses in the browser's order. It knows the details that trip people up: * means a literal asterisk when credentials are included, * never covers Authorization, Chrome caps Max-Age at two hours, and a missing Vary: Origin lets a cache serve one site's response to another. You get the console error you'd see and server config that fixes it.
How it works
- InputA fetch() or curl request and server headers
- In your browserThe Fetch standard's CORS checks in order
- OutputThe failing check, console error and fixed config
Where it fits in a designer's workflow
- Plan
- Design
- Build
- Test
- Launch
By the numbers
Show the numbers as a table
| Max-Age | Chrome | Firefox | Safari |
|---|---|---|---|
| No Max-Age (5 s) | 8,640 | 8,640 | 8,640 |
| Max-Age 600 | 144 | 144 | 144 |
| Max-Age 7,200 | 12 | 12 | 144 |
| Max-Age 86,400 | 12 | 1 | 144 |
How to use it
- Enter the origin of the page that makes the request.
- Paste the fetch() call or curl command.
- Paste the headers your server sends to the OPTIONS preflight and to the real request.
- Read the steps, then copy the fixed config for your server.
FAQ
When does a request need a preflight?
When it uses a method other than GET, HEAD or POST, or sets any header outside a short safelist. Content-Type is only safelisted for form data, multipart and text/plain, so sending JSON with application/json always triggers a preflight.
Why doesn't Access-Control-Allow-Origin: * work?
If the request includes credentials (cookies or HTTP auth, credentials: "include"), browsers refuse a wildcard. The server has to echo back the exact origin, send Access-Control-Allow-Credentials: true and add Vary: Origin.
Why is Authorization still blocked with Allow-Headers: *?
The Fetch standard excludes Authorization from the wildcard, so it must be listed by name. And when credentials are included, * is treated as a header literally called *.
Why does my preflight fail with 401 or 404?
Browsers send the OPTIONS request without cookies or auth headers, so it must succeed unauthenticated, and your server or framework has to route OPTIONS for that path and return 2xx.
Does CORS protect my API?
No. CORS controls which pages can read responses in a browser. Simple requests still reach your server, and curl or a server ignores CORS entirely. Use authentication and CSRF protection for that.