Referrer-Policy Values Compared

This guide is part of the Referrer-Policy and Permissions-Policy reference. The Referrer-Policy header takes exactly one of eight tokens, and each token draws a different line between three cases: what the browser puts in the Referer request header for a same-origin navigation, for a cross-origin navigation at the same security level, and for a downgrade from HTTPS to HTTP. Pick the wrong token and you either leak full URLs — paths, query strings, session identifiers, PII — to third parties, or you starve your own referral analytics of the origin it needs. This page compares the eight values side by side and lands on the one correct production default.

Configuration Syntax & Exact Values

The header carries a single token with no parameters, no quoting inside the value, and no comma list:

Referrer-Policy: strict-origin-when-cross-origin

The eight legal tokens, ordered from most restrictive to least, with the exact Referer each sends in the three cases (same-origin / cross-origin same-security / HTTPS→HTTP downgrade):

no-referrer                     -> (none)      / (none)     / (none)
same-origin                     -> full URL    / (none)     / (none)
strict-origin                   -> origin      / origin     / (none)
strict-origin-when-cross-origin -> full URL    / origin     / (none)   <- recommended default
origin                          -> origin      / origin     / origin
origin-when-cross-origin        -> full URL    / origin     / origin
no-referrer-when-downgrade      -> full URL    / full URL   / (none)
unsafe-url                      -> full URL    / full URL   / full URL  <- never use

“origin” means the bare serialized origin with a trailing slash — https://app.example/ — with path and query stripped. “full URL” includes path, query string, but never the fragment (#...); browsers strip the fragment from Referer unconditionally. A token the browser does not recognize (a typo like strict-origin-when-crossorigin) is silently ignored, and the agent falls back to its own default — so the literal spelling is load-bearing.

Two of these tokens are traps. unsafe-url sends the full URL everywhere, including to plaintext HTTP and to any third party — it defeats the entire point of the header. no-referrer-when-downgrade was the historical browser default but leaks full URLs across origins at the same security level; it only protects the downgrade hop. Neither belongs in a modern configuration.

Referrer-Policy value comparison matrix A matrix of the eight Referrer-Policy tokens against what each sends for same-origin, cross-origin, and HTTPS-to-HTTP downgrade requests. Referrer-Policy value same-origin cross-origin downgrade no-referrer none none none same-origin full URL none none strict-origin origin origin none strict-origin-when-cross-origin full URL origin none origin origin origin origin origin-when-cross-origin full URL origin origin no-referrer-when-downgrade full URL full URL none unsafe-url full URL full URL full URL origin = https://app.example/ (path and query stripped) full URL = scheme + host + path + query (fragment always removed) downgrade = an HTTPS page navigating to a plaintext http:// destination
The eight tokens mapped to what leaves the browser in each of the three navigation cases.

Server-Side Configuration

Emit the header at one enforcement layer only — the edge or the origin, never both — to avoid a duplicated Referrer-Policy, which browsers resolve by taking the last value but which trips header audits.

Nginx

add_header Referrer-Policy "strict-origin-when-cross-origin" always;

always sends the header on 4xx/5xx error responses as well as 2xx. On Nginx any add_header inside a location block discards every header inherited from the enclosing server block, so repeat this line in each location that defines its own headers.

Apache

Header always set Referrer-Policy "strict-origin-when-cross-origin"

On Apache always covers internally generated error responses and set overwrites any value emitted upstream instead of appending a second one. Requires mod_headers.

Cloudflare

Use a Transform Rule so the edge overwrites rather than appends. On Cloudflare: Rules → Transform Rules → Modify Response Header → Set header Referrer-Policy to strict-origin-when-cross-origin for All incoming requests. “Set” replaces any origin value; “Add” would create a duplicate.

Node / Express (Helmet)

const helmet = require("helmet");

app.use(
  helmet.referrerPolicy({ policy: "strict-origin-when-cross-origin" })
);

Helmet normalizes casing and guarantees a single header. Register it before your route handlers so it applies to every response. Passing an array to policy emits a comma-separated fallback list — only do that to support agents that lack a specific token.

Django / FastAPI

# Django settings.py (SecurityMiddleware)
SECURE_REFERRER_POLICY = "strict-origin-when-cross-origin"

Django SecurityMiddleware sets the header on every response when SECURE_REFERRER_POLICY is defined; this is already the framework default from Django 3.1 onward, so set it explicitly to pin the value against future changes.

Diagnostic & Verification Steps

Confirm the header is present and spelled correctly with a single request:

curl -sI https://app.example/ | grep -i referrer-policy

Expected output — the exact token, once:

referrer-policy: strict-origin-when-cross-origin

A missing line means the header never left the server; two lines mean two layers are both emitting it. To prove the runtime behaviour rather than just header presence, watch what the browser actually sends. In Chrome or Firefox DevTools open the Network panel, click a cross-origin request, and read the Request Headers: under strict-origin-when-cross-origin a same-origin request shows the full URL in Referer, a cross-origin request shows only https://app.example/, and a request to an http:// destination shows no Referer at all.

Referer emitted under the recommended default Three requests leaving an HTTPS origin under strict-origin-when-cross-origin and the Referer value each carries. HTTPS origin app.example/p?id=9 same-origin Referer: https://app.example/p?id=9 cross-origin HTTPS Referer: https://app.example/ HTTPS → HTTP Referer: (header absent)
Under strict-origin-when-cross-origin the full URL stays internal, only the origin crosses, and nothing survives a downgrade.

To verify a token behaves differently from the default, temporarily set no-referrer and repeat the DevTools check: every Referer — including same-origin — disappears. Restore the recommended value afterward.

Edge Cases, Security Implications & Safe Rollback

Analytics attribution depends on the origin surviving. Referral reports in Google Analytics, Plausible, Matomo, and server-log analyzers are built from the Referer origin, not the path. strict-origin-when-cross-origin, strict-origin, and origin all preserve the cross-origin origin, so referral sources still resolve. The dangerous downgrade is to no-referrer or same-origin, which strip the origin entirely: inbound partners then land in your “direct / none” bucket and outbound partners stop crediting you. Choose restriction that keeps the origin, not restriction that erases it.

A meta tag and per-request attributes can override the header. A <meta name="referrer" content="unsafe-url"> in the document, or a referrerpolicy attribute on an <a>, <img>, <link>, or <script>, overrides the HTTP header for those requests. A single stray unsafe-url attribute can leak full URLs that your server-set policy was designed to strip. Grep templates for referrerpolicy and name="referrer" before trusting the header alone.

Downgrade protection is not a substitute for HSTS. The strict- tokens suppress Referer on an HTTPS→HTTP hop, but they do nothing to stop the insecure request itself. Pair the policy with HSTS so downgraded destinations are upgraded or blocked before the request is even made.

Choosing a Referrer-Policy value A decision tree that selects one of five practical Referrer-Policy tokens based on cross-origin and analytics needs. Send any Referer cross-origin? no same-origin strips everything cross-origin yes (origin) Keep full URL same-origin? yes strict-origin-when-cross-origin recommended default no strict-origin Every branch above keeps downgrade protection; unsafe-url and no-referrer-when-downgrade appear on no branch.
A practical selector that never routes to unsafe-url or no-referrer-when-downgrade.

Rollback is trivial and stateless. The Referer header is computed fresh per request; no value is persisted in the browser the way an HSTS max-age is. To revert, change the token (or remove the line) and purge any edge/CDN cache so stale responses stop carrying the old header. There is no client-side residue to expire.

Conclusion

Deploy the value the same way at every layer: set strict-origin-when-cross-origin in staging first, confirm in DevTools that same-origin requests still carry the full URL, cross-origin requests carry only the origin, and downgraded requests carry nothing — and that referral analytics still resolve inbound sources. Then promote the identical token to production at a single enforcement layer and purge the cache. Because the header holds no client state, rollback is a one-line change with no waiting period.

Frequently Asked Questions

Which Referrer-Policy value should I use in production? strict-origin-when-cross-origin for nearly every site: full URL same-origin, bare origin cross-origin, and nothing on an HTTPS→HTTP downgrade. It preserves internal analytics and inbound referral attribution while keeping paths, query strings, and tokens off third-party servers.

Does strict-origin-when-cross-origin break referral analytics? No. Referral reports key off the Referer origin, and this value still sends the origin cross-origin. The values that break attribution are no-referrer and same-origin, which strip the origin entirely and push traffic into the “direct” bucket.

What is the difference between strict-origin and strict-origin-when-cross-origin? strict-origin sends only the bare origin in every case, including same-origin, so internal pages lose the full referring URL. strict-origin-when-cross-origin keeps the full URL for same-origin navigation and downgrades to just the origin only when the request crosses origins.

Why should I never use unsafe-url? unsafe-url sends the complete URL — path and query — to every destination, including plaintext HTTP and unrelated third parties. It exposes session identifiers and PII embedded in URLs and removes downgrade protection, defeating the header’s entire purpose.

Does the fragment (#section) ever appear in the Referer? No. Browsers strip the URL fragment from Referer under every policy value, including unsafe-url. Only scheme, host, path, and query can be sent, and cross-origin policies strip path and query on top of that.