How HTTP Works

Request header

> Sec-Fetch-Mode: navigate

Sec-Fetch-Mode Header: Values and Server Use

Sec-Fetch-Mode reports the request mode: navigate, cors, no-cors, same-origin or websocket. What sets each value and how servers use it.

Reviewed 2 min readintermediate3 sourcesTry itMarkdown
Direction
Request
Category
Security
Spec
W3C Fetch Metadata
JS can set it
No: forbidden header name
On this page

TL;DR: Sec-Fetch-Mode carries the Fetch API request mode for the request: navigate for page loads, cors for ordinary fetch() and XHR, no-cors for embedded resources like images and scripts, same-origin, or websocket. Pair it with Sec-Fetch-Site to tell a user opening a page from a hostile page loading your endpoint.

Values

GET /report.pdf HTTP/1.1
Host: example.com
Sec-Fetch-Mode: navigate
Sec-Fetch-Dest: document
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
ValueWhat produces it
navigateA navigation between documents: link click, address bar, form submission, location.href = ..., and iframe loads.
corsA request that follows the CORS protocol: the default for fetch() and XMLHttpRequest, and <script crossorigin>, <img crossorigin> and similar.
no-corsA request the page cannot read the response of: plain <img>, <script>, <link rel=stylesheet>, <video> and the like.
same-originA request made with fetch(url, { mode: 'same-origin' }). The browser rejects cross-origin URLs before sending, so servers see this only for same-origin targets.
websocketThe HTTP request that starts a WebSocket handshake.

The header is a structured-field token defined in section 2.2 of the W3C Fetch Metadata spec, and it is a forbidden request header: scripts cannot set or change it.

What it is useful for

Mode answers “was this a page load or a sub-request?”. The combination worth enforcing:

  • navigate plus GET: someone followed a link to you. Safe to serve even when Sec-Fetch-Site is cross-site.
  • cors or no-cors from cross-site: another site’s code or markup is pulling your resource. Reject unless you meant to publish it.
  • websocket: browsers do not apply CORS to WebSocket handshakes, so the server has to check Origin or Sec-Fetch-Site itself to prevent cross-site WebSocket hijacking.

The full policy, with Express and nginx versions, is on the Sec-Fetch-Site page.

Notes

  • A default fetch('/api') sends Sec-Fetch-Mode: cors even to your own origin. Do not infer “cross-origin” from cors.
  • Mode is not trustworthy for non-browser clients. curl sends no Sec-Fetch-* headers, or any value you choose.
  • Sent only on requests to potentially trustworthy URLs, which means HTTPS and localhost.
  • Browser support: Chrome and Edge 76, Firefox 90, Safari 16.4.

Frequently asked questions

What are the possible values of Sec-Fetch-Mode?

Exactly five: cors, navigate, no-cors, same-origin, and websocket. They mirror the mode of the underlying Fetch request. Any other value is not defined by the spec.

What is the difference between Sec-Fetch-Mode no-cors and cors?

cors means the request follows the CORS protocol, so the page can read the response only if the server allows it with Access-Control-Allow-Origin. no-cors is what an img, script, or stylesheet tag produces: the browser loads the resource for rendering but hides the response from scripts. A cross-site no-cors request still reaches your server and still carries cookies when SameSite allows it.

Does fetch() send Sec-Fetch-Mode: cors or same-origin?

A default fetch() has mode cors, so the header is cors even for same-origin URLs. The value same-origin only appears when the caller explicitly passes mode: same-origin, which makes the browser refuse cross-origin URLs.

Which browsers send Sec-Fetch-Mode?

Chrome and Edge 76, Firefox 90, and Safari 16.4. Older browsers and non-browser clients such as curl send nothing, so any server logic must tolerate the header being absent.

Sources

  1. MDN Web Docs: Sec-Fetch-Modedeveloper.mozilla.org
  2. W3C Fetch Metadata Request Headers, section 2.2w3c.github.io
  3. Fetch Standard: request modefetch.spec.whatwg.org

Keep going

Browse /search