How do the Referrer-Policy tokens origin, same-origin, strict-origin and strict-origin-when-cross-origin differ from each other?
answer
- two axes, not eight separate rules
- one axis is the origin comparison
- strict means drop on HTTPS-to-HTTP
- origin-only drops path and query
- the default combines both axes
basics
~20 sTwo axes decide every token: whether the destination is the same origin, and whether the request goes from an HTTPS page to a plain HTTP destination. origin always sends just the origin; strict-origin-when-cross-origin, the default, combines both axes.
solid answer
~40 sRead the token names as a combination of two rules rather than as eight separate behaviours. One rule is an **origin comparison**: `same-origin` sends the full URL to your own origin and nothing to any other; `origin-when-cross-origin` sends the full URL to your own origin and the origin alone elsewhere. The other rule is the **HTTPS-to-HTTP transition**: the `strict-` prefix, and `no-referrer-when-downgrade`, suppress the value on a request from a securely served page to a plain HTTP destination. So `origin` sends the origin to everyone, including a plaintext destination; `strict-origin` sends the origin except on that transition; and `strict-origin-when-cross-origin` — the default when no policy is stated — sends the full URL same-origin, the origin cross-origin, and nothing on the transition. Origin-only always means no path and no query.
code
http · 7 linesGET /assets/appeal-form.css HTTP/1.1
Host: appeals.example.org
Referer: https://appeals.example.org/appeals/2291?parcel=41-207-018&grounds=valuation
GET /tiles/9/271/168.png HTTP/1.1
Host: tiles.example.net
Referer: https://appeals.example.org/go deeper
Recall the three outcomes a token can produce — full URL, origin only, or nothing — and that origin only means no path and no query.
Explain the two axes and derive any token's behaviour from them, including that the default already sends the origin alone to other origins.
Argue a choice for a real page: what each embedded third party still needs, and what your own reporting stops receiving if you go further than the default.
Treat it as an estate-wide default with a migration cost: tightening blanks values that downstream consumers may silently depend on, so the rollout needs evidence before the header changes.
## Eight tokens, two underlying rules The `Referrer-Policy` token list looks like eight unrelated behaviours and is really two rules crossed with each other. **Rule one is an origin comparison.** Is the request going to the same origin as the document — same scheme, same host, same port — or somewhere else? `same-origin` and `origin-when-cross-origin` turn on that comparison and treat the two cases differently. **Rule two is the HTTPS-to-HTTP transition.** Is a securely served page causing a request to a plain HTTP destination? `no-referrer-when-downgrade` and every token carrying the `strict-` prefix suppress the value entirely in that case. This is the only thing 'downgrade' means here: it is about the scheme of the destination, not about any negotiated protocol version. A third element is not a rule but an outcome: the **origin-only flag**. When a token says 'origin', the browser empties the path and drops the query, so `https://appeals.example.org/appeals/2291?parcel=41-207-018` is reduced to `https://appeals.example.org/`. Credentials and the fragment are already gone by then, whatever the token. ## The full table | token | same-origin request | cross-origin, both HTTPS | HTTPS page to HTTP destination | |---|---|---|---| | `no-referrer` | nothing | nothing | nothing | | `no-referrer-when-downgrade` | full URL | full URL | nothing | | `same-origin` | full URL | nothing | nothing | | `origin` | origin | origin | origin | | `strict-origin` | origin | origin | nothing | | `origin-when-cross-origin` | full URL | origin | origin | | `strict-origin-when-cross-origin` | full URL | origin | nothing | | `unsafe-url` | full URL | full URL | full URL | Read a row left to right and the naming stops being arbitrary: `strict-origin-when-cross-origin` is literally 'origin when cross-origin, and strict about the plaintext case'. ## The four tokens in the question - **`origin`** — always the origin, to everyone. It never suppresses, so a plain HTTP destination still learns which site the request came from. - **`same-origin`** — the full URL to your own origin, and **nothing at all** to any other. Not 'the origin to other origins': nothing. - **`strict-origin`** — the origin, except on a request from an HTTPS page to a plain HTTP destination, where nothing is sent. Note that your own pages also get only the origin, which is often more than you wanted to give up. - **`strict-origin-when-cross-origin`** — the full URL within your own origin, the origin to other origins, nothing across the plaintext transition. It is the default, so choosing it explicitly changes nothing except making the intent visible in the response. ## Choosing one for a URL that is itself sensitive On an appeal portal whose path and query name a parcel and the grounds of an appeal, the question is not 'how strict can we be' but 'what still needs the value'. The default already stops the parcel identifier reaching a third-party map host or a font host, because cross-origin requests get the origin alone. Moving to `same-origin` additionally blanks the value for those hosts, which is fine if nothing downstream wanted it. Moving to `no-referrer` blanks it for your own pages too, which breaks any of your own per-source reporting. Moving to `unsafe-url` hands the parcel identifier and the grounds to every embedded third party, which is precisely the leak the leaf exists to close. ## Two values that are not a token 1. **The empty string** is a valid value. It means no policy is stated, so the fallback applies — an inherited policy if there is one, otherwise the default. Sending an empty value is not a way to turn the mechanism off. 2. **A list of tokens** is allowed by the header's grammar, and unknown tokens are simply ignored under the extension-token rule. That makes `Referrer-Policy: no-referrer, strict-origin-when-cross-origin` a deliberate pattern: a client that does not recognise the later token keeps the earlier one it did recognise, while a client that recognises both keeps the last one it understood. ## The reversals to check yourself against - 'Strict' does not mean the origins must match; it means the value is dropped on the plaintext transition. - Origin-only drops the query **and** the path, not the query alone. - The default is not `no-referrer`; a site that sets nothing still sends the origin cross-origin. - `no-referrer-when-downgrade` has nothing to do with protocol-version downgrades; it is an HTTPS-to-HTTP navigation and nothing else.
- Is there a case where a permissive policy still sends only an origin?Yes. If the serialization of the referrer value would exceed 4096 characters, the browser falls back to the origin whatever the policy says. A page with a very long URL therefore cannot rely on the full value arriving, which matters if anything downstream was built on reading it.
- What does an empty `Referrer-Policy` value mean?It is valid and means no policy is stated, so the fallback applies: an inherited policy where one exists, otherwise the default. It is not an off switch, and it is not equivalent to `no-referrer`.
- Which tokens still send something to a plain HTTP destination?`origin`, `origin-when-cross-origin` and `unsafe-url`. Every token with the `strict-` prefix, plus `no-referrer-when-downgrade` and `no-referrer`, send nothing on a request from a securely served page to a plain HTTP destination.
saying these in an interview costs you the question
- Thinks strict-origin means the two origins must match.
- Says same-origin sends the origin to other origins.
- Assumes the default policy is no-referrer.
- Believes origin-only keeps the path and drops the query.
- Reads no-referrer-when-downgrade as a protocol-version downgrade.