Loading page...Загружаем страницу...正在加载页面...
AtlasRepo

Why an API works in curl but fails at the browser preflight

Description and use

corswhy reveals that the server returns 401 to OPTIONS, blocking the browser POST. Configuring the server to allow unauthenticated OPTIONS and return the required CORS headers lets the request succeed.

Problem

A browser preflight OPTIONS request fails with 401 or missing headers, preventing the actual POST from being sent, while the same request succeeds via curl.

Outcome

The corswhy tool identifies that the server’s 401 response to OPTIONS blocks the browser POST. By configuring the server to allow unauthenticated OPTIONS and to return the correct CORS headers, the preflight succeeds and the browser request proceeds.

Workflow

  • 1. Run corswhy with the API URL, origin, method, and header names: node bin/corswhy.js http://127.0.0.1:18765/auth --origin http://localhost:5173 --method POST --header authorization,content-type
  • 2. corswhy sends an OPTIONS request with the specified details and prints a row for each CORS check.
  • 3. Review the report: a 401 status indicates failure; a 204 with allowed headers indicates success.
  • 4. Adjust the server to allow unauthenticated OPTIONS and to include the required Access-Control-Allow-Origin and Access-Control-Allow-Headers in the response.
  • 5. Re‑run corswhy to confirm the preflight passes.
  • 6. Test the actual POST from the browser to ensure it is now sent and processed.

Evidence

I built corswhy to inspect that exchange from a terminal. It takes the URL of the API, the page origin, the intended method, and names from the browser's Access-Control-Request-Headers field. It sends OPTIONS with those details and prints one row for each check.

Source

The failing endpoint returns 401 to OPTIONS. The report names the status failure first and suggests letting OPTIONS reach the CORS handler without authentication.

Source

The second endpoint answers with a 204 response and the required allowed origin and header names, so its report passes.

Source

  • Record date: 2026-10-02T13:56:02.254Z