# 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.

Source: https://howhttpworks.com/headers/sec-fetch-mode
Last reviewed: 2026-10-04

> **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](https://howhttpworks.com/headers/sec-fetch-site) to tell a user opening a page from a hostile page loading your endpoint.

## Values

```http
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
```

| Value | What produces it |
| --- | --- |
| `navigate` | A navigation between documents: link click, address bar, form submission, `location.href = ...`, and iframe loads. |
| `cors` | A request that follows the CORS protocol: the default for `fetch()` and `XMLHttpRequest`, and `<script crossorigin>`, `<img crossorigin>` and similar. |
| `no-cors` | A request the page cannot read the response of: plain `<img>`, `<script>`, `<link rel=stylesheet>`, `<video>` and the like. |
| `same-origin` | A 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. |
| `websocket` | The 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](https://howhttpworks.com/headers/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.

## Related

- [Sec-Fetch-Site](https://howhttpworks.com/headers/sec-fetch-site), [Sec-Fetch-Dest](https://howhttpworks.com/headers/sec-fetch-dest), [Sec-Fetch-User](https://howhttpworks.com/headers/sec-fetch-user)
- [CORS guide](https://howhttpworks.com/guides/cors)
