Sec-Fetch-Site and the Fetch Metadata request headers
Fetch Metadata headers are added by the browser, not by page code, and describe the relationship between the requesting page and the target: same origin, same site, cross site, or user typed.
At a glance
- Direction
- Request only, set by the browser and not settable from JavaScript.
- Defined in
- Fetch Metadata Request Headers (W3C)
- When absent
- The client does not send them, which browsers also do over plain HTTP, so treat absence as unknown rather than as safe.
- Sec-Fetch-Site
- same-origin, same-site, cross-site, or none for a user typed navigation
- Sec-Fetch-Mode
- navigate, cors, no-cors, same-origin, websocket
- Sec-Fetch-Dest
- document, iframe, image, script, style, empty and other destinations
- Sec-Fetch-User
- Sent as ?1 only when a navigation was triggered by the user
In detail
These headers exist because a server has never been able to trust what a request claims about itself. Referer can be suppressed and Origin is absent on many navigations, but the Sec- prefix means page code cannot set or override these values: they are added by the browser from information only the browser has. That makes them usable as an input to an access decision rather than merely as telemetry.
Sec-Fetch-Site is the most useful of the four. The value none means the request was typed or bookmarked by the user, same-origin came from your own pages, same-site came from a related host, and cross-site came from somebody else. A resource endpoint that has no business being loaded from another site can reject cross-site outright, which shuts down request forgery and a range of resource inclusion attacks at the edge.
Sec-Fetch-Mode and Sec-Fetch-Dest describe what the browser intends to do with the response. Together they catch category errors: a JSON API being loaded with a script tag arrives with a destination of script, and a page endpoint being pulled into a frame arrives with a destination of iframe. Both are worth refusing even when the origin looks acceptable.
Build the rule as an allowlist with a safe default. Allow anything where Sec-Fetch-Site is same-origin or none, allow the specific cross-site cases you actually support, and reject the rest. Older clients that send no Sec-Fetch headers at all should fall through to your existing checks rather than being trusted or blocked outright.
Examples
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: document
Sec-Fetch-User: ?1Sec-Fetch-Site: cross-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: imageIf that endpoint is private, this is the request to refuse. Cross-Origin-Resource-Policy blocks the same case on the browser side.
Things that catch people out
- Absence is not evidence of a same-origin request. Non-browser clients, older browsers and plain HTTP requests carry no Sec-Fetch headers at all.
- Blocking every cross-site request breaks legitimate inbound links, because a link click is cross-site with a document destination. Allow that combination explicitly.
- The headers describe the request, not the user. They belong in front of authentication, never in place of it.
Try it: HTTP Headers Checker
Check a live URL or paste headers you already have. It grades six security headers from A+ to F and lists every other header the response returned.
HTTP Headers Checker
LOCAL · Browser-OnlyView HTTP response headers for any URL
Enter any website URL to fetch and analyze its HTTP response headers. We'll automatically add https:// if needed.
Why Check Security Headers?
Security headers protect your website against common attacks like XSS, clickjacking, and MIME sniffing. They're set by your web server and cost nothing to implement. Missing security headers are one of the most common findings in security audits.
Related HTTP headers
All http headers →Origin: where a request was initiated from
When browsers send Origin, why it is only scheme, host and port, when the value is null, and how to use it for cross-site request forgery defence.
Cross-Origin-Resource-Policy: who may embed this response
How CORP lets a response refuse to be embedded by other sites, how same-site differs from same-origin, and why asset hosts have to send cross-origin.
Referrer-Policy: controlling what the Referer header leaks
Every Referrer-Policy value compared, what modern browsers do when the header is missing, and why URLs with tokens in them leak to third parties without it.
Access-Control-Allow-Origin: who may read this response
How the allow origin header is matched, why a wildcard fails with credentials, why it takes only one origin, and why Vary: Origin is mandatory when you echo.
Cache-Control: directives for browsers and shared caches
Every Cache-Control directive that matters, the difference between no-cache and no-store, and how to cache immutable assets forever without breaking deploys.
ETag: version identifiers for conditional requests
How an ETag is compared, when to use a weak tag, how it drives 304 responses and 412 conflicts, and why compression changes the tag a server sends.
Tools for this
- HTTP Headers Checker Free online HTTP headers checker - view HTTP response headers for any URL
- HTTP Request Builder Free online HTTP request builder - build and test HTTP requests with custom headers and body