What Referrer-Policy puts in Referer: the full URL, the origin, or nothing

Referrer-Policy decides what goes in Referer when a page loads an image or follows a link. The eight values, what is always stripped, where the policy is set, redirects and the Origin header.

DevelopmentWebSecurityPrivacy

Say a password reset page lives at https://example.com/account/reset?token=8f3a. If that page has one link to an outside help site, or one image from another domain, the browser may put the page’s address in the Referer header of that request, token and all. The W3C Referrer Policy spec opens with cases like this one: an HTTPS application with a session identifier in its URLs, and “capability URLs”, where the URL itself grants access.

Referrer-Policy is the rule for what goes into that header. Every policy ends up sending one of three things: the full URL (with some parts removed), only the origin, or no header at all.

What every policy strips

No policy sends the URL exactly as it is. The “strip url” algorithm in section 8.4 of Referrer Policy removes:

  • the fragment (everything after #)
  • the username and password (user:pass in https://user:pass@host/)

RFC 9110 section 10.1.3 asks for the same thing: a user agent MUST NOT include the fragment and userinfo components when it generates a Referer value. The same algorithm also returns no referrer at all if the URL’s scheme is a local scheme.

The origin-only policies go further and drop the path and the query, leaving scheme, host and port. The browser appends a / so the result is a valid URL, which is why an origin referrer looks like https://example.com/.

The “full URL” keeps the path and the query string. In the example above, https://example.com/account/reset?token=8f3a goes out unchanged; only a fragment would have been removed.

The eight values

Take a document at https://example.com/page?q=1 making requests to three places. Each policy gives the following, straight from the “Determine request’s Referrer” algorithm in section 8.3 of Referrer Policy and the examples in section 3.

Policy Same origin https://example.com/other Cross-origin https://not.example.com/ HTTPS to HTTP http://not.example.com/
no-referrer none none none
no-referrer-when-downgrade full URL full URL none
same-origin full URL none none
origin origin origin origin
strict-origin origin origin none
origin-when-cross-origin full URL origin origin
strict-origin-when-cross-origin full URL origin none
unsafe-url full URL full URL full URL

The strict- prefix is about the last column. The spec’s condition is a request from a TLS-protected document to a URL that is not “potentially trustworthy”, and in the spec’s examples an http:// address is that case. The strict- policies and no-referrer-when-downgrade send nothing there. A document that was served over plain HTTP in the first place doesn’t meet the condition, so strict-origin on such a page sends the origin anywhere.

A few details are easy to miss:

  • Same origin means the request’s origin compared with the origin of the URL the request is currently going to. A note under origin-when-cross-origin says that even a scheme upgrade, such as http://example.com/ to https://example.com/, counts as a cross-origin request.
  • Section 10.1 says origin, origin-when-cross-origin and unsafe-url can leak the origin or URL of a secure site over insecure transport. For unsafe-url the spec adds that the policy’s name doesn’t lie.
  • strict-origin sends only the origin even for same-origin requests. If you want to know which page within your own site a visitor came from, it isn’t the right choice.

Where the policy is set

Section 4 of Referrer Policy lists five ways a request gets its policy:

  1. the Referrer-Policy response header
  2. <meta name="referrer" content="...">
  3. a referrerpolicy attribute on a, area, img, iframe or link
  4. rel="noreferrer" on a, area or link
  5. inheritance (an srcdoc iframe, or a context created from a blob URL)

The header name doesn’t copy the old misspelling: the policy header is Referrer-Policy, the request header is Referer.

fetch() lets you set it per request. The Request constructor in the Fetch Standard uses the referrerPolicy option as the request’s policy, and referrer: "" sets the request’s referrer to no-referrer.

// Send only the origin with this request
await fetch("https://api.partner.example/v1/items", {
  referrerPolicy: "strict-origin",
});

// Send no Referer with this request
await fetch("https://cdn.partner.example/pixel.gif", { referrer: "" });

When neither an element attribute nor a fetch() option sets anything, the request’s policy is the empty string. The current Fetch Standard’s main fetch algorithm then fills it in from the request’s policy container. Section 6 of Referrer Policy explains that the HTML Standard records a policy on the document from its response and uses it as the baseline for requests that document makes. So a request with no policy of its own gets the document’s.

Several values in one header

Section 8.1 reads the tokens of the Referrer-Policy header from left to right and overwrites the policy each time it recognises one. Unknown tokens are skipped, so the last recognised value wins. Section 11.1 presents this as the way to roll out new values: put a value older browsers understand first and the newer one after it.

Referrer-Policy: no-referrer, strict-origin-when-cross-origin

A browser that knows the second value uses it; one that doesn’t stays with the first. The spec points out that this does not apply to the referrerpolicy attribute. For the attribute, it suggests setting the value from script and reading it back to see whether it’s supported.

A redirect response can change the policy

Before following a redirect, the Fetch Standard’s HTTP-redirect fetch calls “Set request’s referrer policy on redirect” from Referrer Policy. That algorithm parses the redirect response’s Referrer-Policy header the same way as section 8.1 and replaces the request’s policy only when the result is a recognised, non-empty value. If the header is missing or holds only unknown tokens, the policy stays as it was.

What matters is what the new policy is applied to. Main fetch works out the request’s referrer before the first request goes out and stores the result on the request. When the redirect is followed, main fetch runs again on the same request: a referrer that is already no-referrer is skipped, and a URL is reduced again under the new policy, starting from the value stored on the first hop.

So a redirect can change how much of what remains gets sent, but it can’t bring back what was already removed:

  • A request sent under no-referrer has no-referrer as its referrer from the start. A redirect response with Referrer-Policy: unsafe-url still doesn’t produce a Referer.
  • If only the origin survived the first hop, the path and query are already gone. A looser policy later on can send at most that origin.
  • If the full URL survived the first hop, for example a same-origin request under strict-origin-when-cross-origin, and the redirect response sets unsafe-url while redirecting to another origin, that full URL goes to the other origin. Section 10.2 says the spec does not forbid switching to a less strict policy.

It also works the other way: if your own server returns the redirect, for a short link or a login hop, a strict policy on that response cuts down what the next request carries. Redirect status codes themselves are covered in the post on HTTP redirects.

It changes the Origin header too

Referrer-Policy affects more than Referer. “Append a request Origin header” in section 3.2 of the Fetch Standard checks the request in this order:

  1. If the request’s response tainting is cors, or its mode is websocket or webtransport, the origin is added as is and the policy plays no part. Main fetch sets response tainting to cors for a cross-origin request in cors mode, such as a cross-origin fetch().
  2. Otherwise, a GET or HEAD request gets no Origin from this algorithm.
  3. Otherwise, a request whose mode is cors also gets its origin unchanged, without the policy. A same-origin fetch() POST lands here: fetch() defaults to cors mode, and a same-origin request keeps basic response tainting.
  4. Any other request, such as one in navigate or no-cors mode, has Origin set to null depending on the policy:
    • no-referrer: always null
    • no-referrer-when-downgrade, strict-origin, strict-origin-when-cross-origin: null when going from an HTTPS origin to a non-HTTPS URL
    • same-origin: null for a different origin

If your server checks Origin as part of its CSRF defence and you set no-referrer for the whole site, a request that is neither GET nor HEAD and is already in navigate mode reaches the policy switch in step 4, and under no-referrer that branch sets Origin to null. A same-origin fetch() POST under the same policy still carries the real origin. The note under this algorithm says the referrer policy is taken into account for every fetch where the fetcher did not explicitly opt into sharing its origin, for example through the CORS protocol. CORS and the Origin header are covered in the post on CORS preflight.

Where the default comes from

If nothing sets a policy, the browser default applies, and the document that defines that default has changed.

  • The W3C document at https://www.w3.org/TR/referrer-policy/ is a Candidate Recommendation dated 26 January 2017. That version treats an empty policy as no-referrer-when-downgrade.
  • The Fetch Standard dated 6 October 2026 fills an empty policy from the HTML Standard’s policy container, and its Referrer Policy reference points to https://w3c.github.io/webappsec-referrer-policy/.

So the default Fetch follows today is decided by the HTML Standard and the version Fetch points to, not by the 2017 document. That is why this post doesn’t present the 2017 default as what browsers do now. In practice you can sidestep the question: don’t rely on the default, and state the policy in a response header. motitory.com sends Referrer-Policy: strict-origin-when-cross-origin on every static response from public/_headers.

How to choose a value:

  • Pages whose URLs carry tokens or personal identifiers: no-referrer or same-origin. If you need analytics within your own site, same-origin.
  • Ordinary pages: strict-origin-when-cross-origin is a reasonable choice. Same-origin requests get the full URL, other origins get the origin, plain HTTP gets nothing.
  • unsafe-url, origin and origin-when-cross-origin can put information from an HTTPS page into HTTP requests. Use them only for a clear reason.

What the policy doesn’t do

  • Referrer-Policy is a promise by the sender. Section 9.1 of Referrer Policy allows user agents to give users an option to suppress the referrer, and the Fetch Standard repeats this in a note. RFC 9110 says some intermediaries remove Referer indiscriminately. Servers should handle requests with a missing or reduced Referer, and must not rely on it for access control; RFC 9110 also says not all requests contain it.
  • Section 1.2 notes that capability URLs can leak in other ways, and controlling the referrer is not enough to stop all of them. Section 17.9 of RFC 9110 recommends keeping sensitive data out of URIs in the first place: use POST for the form, transform the data before building the URI, or redirect to a different, server-generated URI.

Sources

Links and content checked on 18 October 2026. The Fetch Standard is a living document; the points above follow the version retrieved that day.

Back to the blog