1001Ferramentas
🛂 Security

CORS Preflight Explainer

Given a CORS request method and headers, shows whether it triggers an OPTIONS preflight and explains why.

Why that OPTIONS request shows up before yours

Every time JavaScript on a site calls a URL on another origin, the browser has to decide whether to send the request straight away or ask first. That question is the preflight: an OPTIONS request that does nothing except check whether the server allows the method and headers that are about to follow. People who do not know the rule see OPTIONS in the log and assume the client is faulty.

The rule is the definition of a simple request. The method must be GET, HEAD or POST; the Content-Type limited to form-urlencoded, multipart/form-data or text/plain; and no headers beyond the safelisted set. Any deviation triggers a preflight. Choose the method, the Content-Type and list your custom headers: the page tells you whether OPTIONS will happen and, more usefully, which condition was broken.

In practice almost every modern API lands in preflight, for two reasons that usually arrive together: application/json is not on the simple type list, and Authorization is not on the safelisted header list. That is not a problem — it is normal operation. What fixes it is the server answering the OPTIONS with the permission headers plus an Access-Control-Max-Age, which makes the browser cache the authorisation and stop asking on every call.

Frequently asked questions

Why does my JSON POST trigger a preflight if POST is a simple method?
Because the method is only one of three conditions. The Content-Type application/json is not among the simple types, and that alone is enough. Sending the same data as text/plain removes the preflight — but then the server has to parse it manually, which rarely pays off.
Does the preflight carry cookies and auth headers?
No. The OPTIONS request goes without credentials and without the body, deliberately: it is only a question. That is why the server has to answer OPTIONS before any authentication check — middleware that demands a token and runs too early blocks the preflight and kills the real call.
Does Access-Control-Allow-Origin with * solve everything?
It solves the case without credentials. When the request sends cookies or uses credentials include, the browser rejects the asterisk: you have to return the exact origin and add Access-Control-Allow-Credentials true. In that scenario, echoing back whatever origin arrives is a risk — keep an allowlist of permitted origins.

Related Tools