How to use the cors preflight checker
- Enter the origin of the page that runs the script and the address it calls.
- Choose the method and the content type, list any other request headers by name and tick the box if cookies or credentials are sent.
- Enter the status code of the preflight reply and paste the server's Access-Control response headers, one per line.
- Read whether a preflight is needed, whether the browser would allow the request, and the table of checks with the first one that fails.
Formula
same origin: scheme, host and port all equal, so CORS does not apply
preflight needed: the method is not GET, HEAD or POST, or a header or content type is outside the safe lists
preflight reply: status 2xx, allowed origin, allowed method, every extra header listed
real response: Access-Control-Allow-Origin matches, and with credentials, Access-Control-Allow-Credentials is true
The safe request headers are Accept, Accept-Language, Content-Language and Range, plus Content-Type when its value is text/plain, a urlencoded form or a multipart form.
A JSON PUT with an Authorization header
A page at https://app.example.com sends a PUT with a JSON body and an Authorization header to https://api.example.com. The method, the content type and the header are all outside the safe lists, so the browser first sends an OPTIONS request with Access-Control-Request-Method: PUT and Access-Control-Request-Headers: authorization, content-type.
The server replies with status 204 and allows the exact origin, the PUT method and the Content-Type and Authorization headers. Every check passes, so the request is allowed. Remove PUT from the allowed methods and the check fails at Access-Control-Allow-Methods. For a simple GET with a wildcard origin the page shows that no preflight is needed.
The most common mistakes
Using the wildcard * together with credentials is the classic error: when a request sends cookies or an Authorization header as credentials, the origin must be named exactly, and Access-Control-Allow-Credentials must be true. The wildcard also does not cover the Authorization header, which must be listed by name.
Another is a preflight reply that returns a redirect or an error status. The browser needs a 2xx status on the OPTIONS request itself, so a login page or a 404 at that address blocks everything.
What the checker does not do
It tests the headers you paste against the rules in the Fetch standard. It does not contact a server, and it cannot see what the server really sends. Browsers apply other rules too, such as mixed content, private network access and extension policies. Test the real server in the browser's developer tools as the final check.
To read the other headers in a response, use the Set-Cookie Header Parser, the HTTP Cache-Control Explainer and the HTTP Status Codes list.
Assumptions and limits
- The same response headers are used for the OPTIONS reply and for the real response, which is how most servers are set up.
- Origins are compared by scheme, host and port after lower-casing the host and dropping default ports.
- Header names are matched without regard to capital letters, and method names are matched exactly.
- Private network access, mixed content, redirects and extension rules are not modeled.
- Nothing typed here leaves your browser, and nothing is sent to the server you describe.
Frequently asked questions
Why does the browser send an OPTIONS request?
Before a request that could change data on another origin, the browser asks the server whether it accepts that method and those headers from this origin. That question is the preflight, an OPTIONS request.
Does a wildcard allow every header?
A wildcard in Access-Control-Allow-Headers covers every header except Authorization, and only when the request sends no credentials. With credentials, the wildcard is just a plain word and each header must be listed.
Why is a GET with a custom header preflighted?
Only a short list of headers can be sent without a preflight. Any other header, such as X-Requested-With or Authorization, makes the request non-simple even for GET.
What does Access-Control-Max-Age do?
It tells the browser how many seconds it may remember the preflight answer. Without it, the browser keeps the answer only briefly and may send the OPTIONS request again soon.