![Maud Nalpas](https://web.dev/images/authors/maudnalpas.jpg) Maud Nalpas [GitHub](https://github.com/maudnals) [LinkedIn](https://www.linkedin.com/in/maudnalpas) [Bluesky](https://bsky.app/profile/maudnals.bsky.social)

<br />

This page outlines some best practices for setting your Referrer-Policy and
using the referrer in incoming requests.

## Summary

- Unexpected cross-origin information leakage damages web users' privacy. A protective referrer policy can help.
- Consider setting a referrer policy of `strict-origin-when-cross-origin`. It preserves most of the referrer's usefulness, while mitigating the risk of leaking data cross-origins.
- Don't use referrers for Cross-Site Request Forgery (CSRF) protection. Use [CSRF tokens](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#token-based-mitigation) instead, and other headers as an extra layer of security.

> [!NOTE]
> **Note** :
>
> - If you're unsure of the difference between "site" and "origin", see [Understanding "same-site" and "same-origin"](https://web.dev/articles/same-site-same-origin).
> - The `Referer` header is missing an R due to a misspelling in the original spec. The `Referrer-Policy` header and `referrer` in JavaScript and the DOM are spelled correctly.

## Referer and Referrer-Policy 101

HTTP requests can include an optional [`Referer` header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Referer),
which indicates the origin or web page URL the request was made from. The
[`Referrer-Policy` header](https://developer.mozilla.org/docs/Web/HTTP/Headers/Referrer-Policy)
defines what data is made available in the `Referer` header.

In the following example, the `Referer` header includes the complete URL of the
page on `site-one` that the request was made from.
![HTTP request including a Referer header.](https://web.dev/static/articles/referrer-best-practices/image/http-request-including-r-9ebf692a22831.jpg) An HTTP request with a Referer header.

The `Referer` header might be present in different types of requests:

- Navigation requests, when a user clicks a link.
- Subresource requests, when a browser requests images, iframes, scripts, and other resources that a page needs.

For navigations and iframes, you can also access this data with JavaScript using
`document.referrer`.

You can learn a lot from `Referer` values. For example, an analytics service
might use them to determine that 50% of the visitors on `site-two.example` came
from `social-network.example`. But when the full URL, including the path and
query string, is sent in the `Referer` **across origins**, it can endanger user
privacy and create security risks:
![URLs with paths, mapped to different privacy and security risks.](https://web.dev/static/articles/referrer-best-practices/image/urls-paths-mapped-diff-5b35e579c46d7.jpg) Using the full URL can impact user privacy and security.

URLs #1 to #5 contain private information, and sometimes sensitive or
identifying information. Leaking these silently across origins can compromise
web users' privacy.

URL #6 is a [capability URL](https://www.w3.org/TR/capability-urls/). If anyone
other than the intended user receives this, a malicious actor can take control
of this user's account.

**To restrict what referrer data is made available for requests from your site,
you can set a referrer policy.**

## What policies are available and how do they differ?

You can select one of eight policies. Depending on the policy, the data
available from the `Referer` header (and `document.referrer`) can be:

- No data (no `Referer` header is present)
- Only the [origin](https://web.dev/articles/same-site-same-origin#origin)
- The full URL: origin, path, and query string

![Data that can
be contained in the Referer header and document.referrer.](https://web.dev/static/articles/referrer-best-practices/image/data-can-contained-the-209ad524f7ae8.jpg) Examples of Referer data.

Some policies are designed to behave differently depending on the **context**:
cross-origin or same-origin request, whether the request destination is as
secure as the origin, or both. This is useful to limit the amount of information
shared across origins or to less secure origins, while maintaining the richness
of the referrer within your own site.

The following table shows how referrer policies restrict the URL data available
from the Referer header and `document.referrer`:

| Policy scope | Policy name | Referer: No data | Referer: Origin only | Referer: Full URL |
|---|---|---|---|---|
| Doesn't consider the request context | `no-referrer` | check |   |   |
| Doesn't consider the request context | `origin` |   | check |   |
| Doesn't consider the request context | `unsafe-url` |   |   | check |
| Security-focused | `strict-origin` | Request from HTTPS to HTTP | Request from HTTPS to HTTPS or HTTP to HTTP |   |
| Security-focused | `no-referrer-when-downgrade` | Request from HTTPS to HTTP |   | Request from HTTPS to HTTPS or HTTP to HTTP |
| Privacy-focused | `origin-when-cross-origin` |   | Cross-origin request | Same-origin request |
| Privacy-focused | `same-origin` | Cross-origin request |   | Same-origin request |
| Privacy and security-focused | `strict-origin-when-cross-origin` | Request from HTTPS to HTTP | Cross-origin request from HTTPS to HTTPS or HTTP to HTTP | Same-origin request |

MDN provides a [full list of policies and behavior
examples](https://developer.mozilla.org/docs/Web/HTTP/Headers/Referrer-Policy#Directives).

Here are some things to be aware of when setting a referrer policy:

- All policies that take the scheme (HTTPS versus HTTP) into account (`strict-origin`, `no-referrer-when-downgrade`, and `strict-origin-when-cross-origin`) treat requests from one HTTP origin to another HTTP origin the same way as requests from an HTTPS origin to another HTTPS origin, even though HTTP is less secure. That's because for these policies, what matters is whether a security **downgrade** takes place; that is, if the request can expose data from an encrypted origin to an unencrypted one, as in HTTPS → HTTP requests. An HTTP → HTTP request is completely unencrypted, so there's no downgrade.
- If a request is **same-origin**, this means that the scheme (HTTPS or HTTP) is the same, so there's no security downgrade.

## Default referrer policies in browsers

*As of October 2021*

**If no referrer policy is set, the browser uses its default policy.**

| Browser | Default `Referrer-Policy` / Behavior |
|---|---|
| Chrome | The default is `strict-origin-when-cross-origin`. |
| Firefox | The default is `strict-origin-when-cross-origin`. Starting from [version 93](https://blog.mozilla.org/security/2021/10/05/firefox-93-features-an-improved-smartblock-and-new-referrer-tracking-protections/), for Strict Tracking Protection and Private Browsing users, the less restrictive referrer policies `no-referrer-when-downgrade`, `origin-when-cross-origin`, and `unsafe-url` are ignored for cross-site requests, meaning the referrer is always trimmed for cross-site requests, regardless of the website's policy. |
| Edge | The default is `strict-origin-when-cross-origin`. |
| Safari | The default is similar to `strict-origin-when-cross-origin`, with some specific differences. See [Preventing Tracking Prevention Tracking](https://webkit.org/blog/9661/preventing-tracking-prevention-tracking/) for details. |

## Best practices for setting referrer policy

> [!TIP]
> **Objective** : Explicitly set a privacy-enhancing policy, such as `strict-origin-when-cross-origin`(or stricter).

There are different ways to set referrer policies for your site:

- As an HTTP header
- Within your [HTML](https://developer.mozilla.org/docs/Web/HTTP/Headers/Referrer-Policy#Integration_with_HTML)
- From JavaScript on a [per-request basis](https://javascript.info/fetch-api#referrer-referrerpolicy)

You can set different policies for different pages, requests, or elements.

The HTTP header and the meta element are both page-level. The priority order for
determining an element's effective policy is as follows:

1. Element-level policy
2. Page-level policy
3. Browser default

**Example:**

`index.html`:

    <meta name="referrer" content="strict-origin-when-cross-origin" />
    <img src="..." referrerpolicy="no-referrer-when-downgrade" />

The image is requested with a `no-referrer-when-downgrade` policy, and all other
subresource requests from this page follow the `strict-origin-when-cross-origin`
policy.

## How to see the referrer policy?

[securityheaders.com](https://securityheaders.com/) is handy to determine which
policy a specific site or page is using.

You can also use the developer tools in Chrome, Edge, or Firefox to see the
referrer policy used for a specific request. At the time of this writing, Safari
doesn't show the `Referrer-Policy` header, but does show the `Referer` that was
sent.
![A screenshot of the Network panel of Chrome DevTools, showing Referer and Referrer-Policy.](https://web.dev/static/articles/referrer-best-practices/image/a-screenshot-the-network-7f0db2eae4fd4.jpg) Chrome DevTools' **Network** panel with a request selected.

## Which policy should you set for your website?

We strongly recommend explicitly setting a privacy-enhancing policy such as
`strict-origin-when-cross-origin` (or stricter).

### Why "explicitly"?

If you don't set a referrer policy, the browser's default policy will be used---in fact, websites often
defer to the browser's default. But this is not ideal, because:

- Different browsers have different default policies, so if you rely on browser defaults, your site won't behave predictably across browsers.
- Browsers are adopting stricter defaults such as `strict-origin-when-cross-origin` and mechanisms such as [referrer trimming](https://github.com/privacycg/proposals/issues/13) for cross-origin requests. Explicitly opting into a privacy-enhancing policy before browser defaults change gives you control and helps you run tests as you see fit.

### Why `strict-origin-when-cross-origin` (or stricter)?

You need a policy that is secure, privacy-enhancing, and useful. What "useful"
means depends on what you want from the referrer:

- **Secure** : if your website uses HTTPS ([if not, make it a
  priority](https://web.dev/why-https-matters)), you don't want your website's URLs to leak in non-HTTPS requests. Since anyone on the network can see these, leaks would expose your users to person-in-the-middle-attacks. The policies `no-referrer-when-downgrade`, `strict-origin-when-cross-origin`, `no-referrer`, and `strict-origin` solve this problem.
- **Privacy-enhancing** : for a cross-origin request, `no-referrer-when-downgrade` shares the full URL, which can cause privacy issues. `strict-origin-when-cross-origin` and `strict-origin` only share the origin, and `no-referrer` shares nothing at all. This leaves you with `strict-origin-when-cross-origin`, `strict-origin`, and `no-referrer` as privacy-enhancing options.
- **Useful** : `no-referrer` and `strict-origin` never share the full URL, even for same-origin requests. If you need the full URL, `strict-origin-when-cross-origin` is a better option.

All of this means that **`strict-origin-when-cross-origin`** is generally a
sensible choice.

**Example: Setting a `strict-origin-when-cross-origin` policy**

`index.html`:

    <meta name="referrer" content="strict-origin-when-cross-origin" />

Or server-side, for example in Express:

    const helmet = require('helmet');
    app.use(helmet.referrerPolicy({policy: 'strict-origin-when-cross-origin'}));

### What if `strict-origin-when-cross-origin` (or stricter) doesn't accommodate all your use cases?

In this case, take a **progressive approach** : set a protective policy like
`strict-origin-when-cross-origin` for your website and, if you need to, a more
permissive policy for specific requests or HTML elements.

### Example: element-level policy

`index.html`:

    <head>
      <!-- document-level policy: strict-origin-when-cross-origin -->
      <meta name="referrer" content="strict-origin-when-cross-origin" />
      <head>
        <body>
          <!-- policy on this <a> element: no-referrer-when-downgrade -->
          <a src="..." href="..." referrerpolicy="no-referrer-when-downgrade"></a>
          <body></body>
        </body>
      </head>
    </head>

Safari/WebKit might cap `document.referrer` or the `Referer` header for
[cross-site](https://web.dev/articles/same-site-same-origin#same-site-cross-site) requests.
See [details](https://webkit.org/blog/10218/full-third-party-cookie-blocking-and-more/).

### Example: request-level policy

`script.js`:

    fetch(url, {referrerPolicy: 'no-referrer-when-downgrade'});

### What else should you consider?

Your policy should depend on your website and use cases, as determined by you,
your team, and your company. If some URLs contain identifying or sensitive data,
set a protective policy.

> [!WARNING]
> **Warning:** Data that might not look sensitive to you can be sensitive for your users, or can just be not data they want or expect to silently leak cross-origin.

## Best practices for incoming requests

Here are some guidelines for what to do if your site uses the referrer URL of
incoming requests.

### Protect users' data

The `Referer` can contain private, personal, or identifying data, so make sure
you treat it as such.

### Incoming referrers can change {referer-can-change}

Using the referrer from incoming cross-origin requests has a few limitations:

- If you have no control over the request emitter's implementation, you can't make assumptions about the `Referer` header (and `document.referrer`) you receive. The request emitter might decide to switch to a `no-referrer` policy at any time , or more generally to a stricter policy than what they used before. This means you receive less data from the `Referer` than before.
- Browsers increasingly use the Referrer-Policy `strict-origin-when-cross-origin` by default. This means that you might now receive only the origin, instead of a full referrer URL, in incoming cross-origin requests, if the sender site has no policy set.
- Browsers might change the way they manage `Referer`. For example, some browser developers might decide to always trim referrers to origins in cross-origin subresource requests, to protect user privacy.
- The `Referer` header (and `document.referrer`) might contain more data than you need. For example, it might have a full URL when you only want to know if the request is cross-origin.

### Alternatives to `Referer`

You might need to consider alternatives if:

- An essential feature of your site uses the referrer URL of incoming cross-origin requests.
- Your site is no longer receiving the part of the referrer URL it needs in a cross-origin request. This happens when the request emitter changes their policy or when they have no policy set and the browser default's policy changed (like in [Chrome 85](https://developers.google.com/web/updates/2020/07/referrer-policy-new-chrome-default)).

To define alternatives, first analyze what part of the referrer you're using.

#### If you only need the origin

- If you're using the referrer in a script that has top-level access to the page, `window.location.origin` is an alternative.
- If available, headers like [`Origin`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Origin) and [`Sec-Fetch-Site`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Sec-Fetch-Site) give you the `Origin` or describe whether the request is cross-origin, which might be exactly what you need.

#### If you need other elements of the URL (path, query parameters...)

- Request parameters might address your use case, which saves you the work of parsing the referrer.
- If you're using the referrer in a script that has top-level access to the page, `window.location.pathname` might work as an alternative. Extract only the path section of the URL and pass it on as an argument, so any potentially sensitive information in the URL parameters isn't passed on.

#### If you can't use these alternatives:

- Check whether you can change your systems to expect the request emitter (for example, `site-one.example`) to explicitly set the information you need in some kind of configuration.
  - Pro: more explicit, more privacy-preserving for `site-one.example` users, more future-proof.
  - Con: potentially more work from your side or for your system's users.
- Check whether the site that emits the requests might agree to set a per-element or per-request Referrer-Policy of `no-referrer-when-downgrade`.
  - Con: potentially less privacy-preserving for `site-one.example` users, potentially not supported in all browsers.

### Cross-site request forgery (CSRF) protection

A request emitter can always decide not to send the referrer by setting a
`no-referrer` policy, and a malicious actor could even spoof the referrer.

Use [CSRF tokens](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html#token-based-mitigation)
as your primary protection. For extra protection, use
[SameSite](https://web.dev/articles/samesite-cookie-recipes#unsafe_requests_across_sites), and
instead of `Referer`, use headers such as
[`Origin`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Origin)
(available on POST and CORS requests) and
[`Sec-Fetch-Site`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Sec-Fetch-Site)
if it's available.

### Log and debug

Make sure to protect users' personal or sensitive data that might be in the
`Referer`.

If you're only using the origin, check whether you can use the
[`Origin`](https://developer.mozilla.org/docs/Web/HTTP/Headers/Origin) header as
an alternative. This might give you the information that you need for debugging
purposes in a simpler way and without needing to parse the referrer.

### Payments

Payment providers might rely on the `Referer` header of incoming requests for
security checks.

For example:

- The user clicks a **Buy** button on `online-shop.example/cart/checkout`.
- `online-shop.example` redirects to `payment-provider.example` to manage the transaction.
- `payment-provider.example` checks the `Referer` of this request against a list of allowed `Referer` values set up by the merchants. If it doesn't match any entry in the list, `payment-provider.example` rejects the request. If it does match, the user can proceed to the transaction.

#### Best practices for payment flow security checks

As a payment provider, you can use the `Referer` as a basic check against some
attacks. However, the `Referer` header by itself isn't a reliable basis for
a check. The requesting site, whether they're a legitimate merchant or not, can set a
`no-referrer` policy that makes the `Referer` information unavailable to the
payment provider.

Looking at the `Referer` might help payment providers catch naive attackers who
didn't set a `no-referrer` policy. If you use the `Referer` as a first check:

- Don't expect the `Referer` to always be present. If it's present, check it against only the minimum data it can include, which is the origin.
  - When setting the list of allowed `Referer` values, make sure to include only the origin and no path.
  - For example, the allowed `Referer` values for `online-shop.example` should be `online-shop.example`, not `online-shop.example/cart/checkout`. By expecting either no `Referer` at all or a `Referer` value that is only the requesting site's origin, you prevent errors that might come from making assumptions about the merchant's `Referrer-Policy`.
- If the `Referer` is absent, or if it's present and your basic `Referer` origin check is successful, you can move onto another, more reliable verification method.

To more reliably verify payments, let the requester
**hash the request parameters** together with a unique key.
Payment providers can then **calculate the same hash on your side**
and only accept the request if it matches your calculation.

**What happens to the `Referer` when an HTTP merchant site with no referrer
policy redirects to an HTTPS payment provider?**

No `Referer` is visible in the request to the HTTPS payment provider, because
[most browsers](https://web.dev/articles/referrer-best-practices#default) use `strict-origin-when-cross-origin` or
`no-referrer-when-downgrade` by default when a website has no policy set.
[Chrome's change to a new default policy](https://developers.google.com/web/updates/2020/07/referrer-policy-new-chrome-default)
won't change this behaviour.

> [!NOTE]
> **Note:** If your website uses HTTP, [migrate to HTTPS](https://web.dev/articles/why-https-matters).

## Conclusion

A protective referrer policy is a great way to give your users more privacy.

To learn more about different techniques to protect your users, see our
[Safe and secure](https://web.dev/explore/secure) collection

## Resources

- [Understanding "same-site" and "same-origin"](https://web.dev/articles/same-site-same-origin)
- [A new security header: Referrer Policy
  (2017)](https://scotthelme.co.uk/a-new-security-header-referrer-policy/)
- [Referrer-Policy on
  MDN](https://developer.mozilla.org/docs/Web/HTTP/Headers/Referrer-Policy)
- [Referer header: privacy and security concerns on
  MDN](https://developer.mozilla.org/docs/Web/Security/Referer_header:_privacy_and_security_concerns)
- [Chrome change: Blink intent to
  implement](https://groups.google.com/a/chromium.org/d/msg/blink-dev/aBtuQUga1Tk/n4BLwof4DgAJ)
- [Chrome change: Blink intent to
  ship](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/lqFuqwZDDR8)
- [Chrome change: status entry](https://www.chromestatus.com/feature/6251880185331712)
- [Chrome change: 85 beta
  blogpost](https://blog.chromium.org/2020/07/chrome-85-upload-streaming-human.html)
- [Referrer trimming GitHub thread: what different browsers
  do](https://github.com/privacycg/proposals/issues/13)
- [Referrer-Policy Spec](https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-delivery)

*With many thanks for contributions and feedback to all reviewers - especially Kaustubha Govind,
David Van Cleve, Mike West, Sam Dutton, Rowan Merewood, Jxck, and Kayce Basques.*