Domain.Posture

cors checker

send a CORS preflight (OPTIONS) to https://<domain>/ with an `Origin` and `Access-Control-Request-Method`, then surface the `access-control-*` response headers. part of the domainposture.com domain dossier.

fetching…

Overview

CORS (cross-origin resource sharing) is how a server tells a browser which cross-origin pages are allowed to read its responses. before any non-simple request the browser issues a preflight `OPTIONS` carrying `Origin: <caller>` and `Access-Control-Request-Method: <method>` (plus `Access-Control-Request-Headers` if any non-simple headers will be sent), and the server responds with a matching set of `Access-Control-Allow-*` headers: `Allow-Origin` (either `*` or the echoed origin — never a list), `Allow-Methods`, `Allow-Headers`, optional `Allow-Credentials: true` (which is *incompatible* with `Allow-Origin: *` — the browser will reject the response), `Max-Age` (how long the preflight can be cached), and `Expose-Headers` (which response headers become readable to JS beyond the CORS-safelisted set). this tool fires exactly that preflight with `Origin` defaulting to `https://domainposture.com` and method defaulting to `GET`, and renders the six AC-* headers side by side. if none come back, the site does not advertise CORS to that origin — which is the common case for sites that are consumed only by their own frontend.

How to use

  1. enter a bare domainpublic fqdn only. no schemes, ports, or paths.
  2. (optional) set a custom origin and methodCORS responses commonly vary by the requesting `Origin` — a server may echo `Access-Control-Allow-Origin` only for allowlisted origins. similarly `POST` or `PUT` may be denied where `GET` is allowed. supply `origin` and `method` via the MCP tool to probe those branches.
  3. read the AC-* block`—` means the header is absent. `Allow-Origin: *` is a public API signal; an echoed origin (e.g. `https://domainposture.com`) means the server has an allowlist and this origin passed. `Allow-Credentials: true` combined with a specific (non-`*`) origin means cookie-carrying cross-site requests are permitted.

Examples

example 1 — because origin is `*`, credentials are by spec disallowed. authenticated calls must use `Authorization: Bearer ...`, not cookies.
input
api.github.com
output
GitHub's REST API returns a permissive public CORS set: `Access-Control-Allow-Origin: *`, `Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE`, `Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-*, X-RateLimit-*`. designed for browser-side use without credentials.
example 2 — this is the correct default — absence of CORS is a deny, not an allow. a browser cross-origin fetch will fail at the response-read step.
input
example.com
output
a plain static site: all six AC-* rows render `—`. the preflight itself returns 200 or 405, but no CORS headers come back. the muted note reads: `no access-control-* headers returned — site does not advertise CORS to this origin`.

Common mistakes

  • a 2xx on OPTIONS does not imply CORS is configured many servers respond 200/204 to an `OPTIONS /` request out of the box (nginx, apache, node frameworks) — sometimes returning the same HTML as `GET`. a 2xx preflight status with zero `access-control-*` headers means exactly the same thing as a 405: CORS is not advertised. always look at the headers, not the status code.
  • `Access-Control-Allow-Origin: *` with `Allow-Credentials: true` is invalid the CORS spec forbids this combination. browsers will drop the response — not just the `Allow-Credentials` line — and the fetch rejects. servers intending to support cookie-bearing cross-site calls must echo the specific origin back, maintain a per-request allowlist, and include `Vary: Origin` in the response so caches don't cross-pollinate.
  • some CDNs require the preflight method to match a real endpoint cloudflare, cloudfront, and fastly sometimes pass OPTIONS through to the origin unmodified — the origin then 404s because it has no route for `OPTIONS /some/api`. the fix at the edge is an `Access-Control-Request-Method`-aware rule that short-circuits with the correct AC-* headers. if your preflight succeeds on `/` but a browser call to `/api/v1/x` fails, the CDN rule probably only covers `/`.

FAQ

what's the difference between `*` and an echoed origin?

`Access-Control-Allow-Origin: *` means 'any website may read this response, without credentials'. an echoed origin (the server copies the request's `Origin` header into the response) means 'this specific origin is allowed'. the echoed form is required any time you want to allow cookies/auth (`Access-Control-Allow-Credentials: true`). the echoed form also requires the server to include `Vary: Origin` so intermediary caches keyed by URL don't hand one origin's response to another.

why doesn't every cross-origin request send a preflight?

only non-simple requests do. a request is *simple* (no preflight) when the method is GET/HEAD/POST, the only custom headers are CORS-safelisted (`Accept`, `Accept-Language`, `Content-Language`, `Content-Type` limited to `application/x-www-form-urlencoded`, `multipart/form-data`, or `text/plain`), and there's no ReadableStream upload. anything else — `PUT`, `DELETE`, `Content-Type: application/json`, a custom `X-Foo` header — triggers the preflight.

my call works from curl but fails from the browser — why?

curl doesn't enforce CORS; it's purely a browser security model. the server is responding fine at the HTTP layer, but the browser sees the AC-* headers (or the lack of them) and rejects the response before JS can read it. this tool probes exactly what the browser sees.

what's `Access-Control-Max-Age` for?

it tells the browser how long (in seconds) it can cache this preflight result, keyed by URL + method + headers. `Max-Age: 86400` means 'don't re-preflight for 24 hours'. chrome caps this at 2 hours, firefox at 24 hours. omitting it means every non-simple cross-origin request is preceded by its own preflight round-trip — a real perf cost on chatty APIs.

does this tool send cookies or auth?

no. we send a fixed `User-Agent: drwho-dossier/1.0`, the `Origin` header, and `Access-Control-Request-Method`. no cookies, no `Authorization`. servers that vary CORS by auth state (e.g. a tighter allowlist for anonymous users) will show you the anonymous variant.

How do I fix 'No Access-Control-Allow-Origin header is present'?

the server, not the browser, must return an Access-Control-Allow-Origin header naming the requesting origin (or an asterisk for public, non-credentialed APIs). add it on the real response and on the preflight OPTIONS response, and when the request sends credentials you must echo a specific origin rather than the asterisk and add Access-Control-Allow-Credentials: true. it is a server-side fix, not something the client can set.

why does a cors error only happen in the browser and not in curl or postman?

cors is a browser security policy, not part of the http protocol itself. the server returns the same response either way, but only a browser checks the access-control-allow-origin headers and blocks the page's javascript from reading the response when they do not permit the calling origin. curl and postman are not bound by that policy, so they read the response with no objection.

does a cors error mean my api or server is down?

no. a cors error means the request actually reached the server and got a response, but the response lacked the access-control-allow-* headers the browser needed to let your page read it. the api is usually working fine, it just is not advertising permission for your origin. check the network tab and you will typically see the request completed with a normal status.

can i fix a cors error from the frontend code alone?

not really. the access-control-allow-* headers must come from the server that owns the api, so the real fix is server-side. from the frontend you can only work around it by routing the call through your own backend or a proxy you control, which then adds the headers or makes the request server-to-server where cors does not apply.

Related tools

  • security headers checker inspect the response headers served at https://<domain>/ — HSTS, CSP, X-Frame-Options, etc.
  • redirect checker trace the HTTP(S) redirect chain from https://<domain>/ up to 10 hops.
  • dns records lookup resolve A, AAAA, NS, SOA, CAA, and TXT records for a domain in one go.

References

  1. Fetch Standard §3.2 — CORS protocol
  2. MDN — Cross-Origin Resource Sharing (CORS)
ad slot · tool-cors-checker