Remediation guide

How to Set a Referrer-Policy Header (and Which Value to Use)

Every time a visitor on your site clicks a link, loads an image, or triggers a JavaScript fetch, their browser sends the full URL of the current page in a Referer request header — to the destination server, without asking. If that URL contains a private path, a search query, a reset token, or a user ID, it just leaked. A Referrer-Policy header lets you control exactly what gets sent. This guide explains all eight policy values, tells you which one to pick, and gives exact deployment snippets for every major hosting platform.

What the Referer header actually exposes

The Referer header (misspelled in the original HTTP specification — one ‘r’ — and never corrected) is automatically attached by the browser to every outgoing request. Without a Referrer-Policy header, or with the old browser default no-referrer-when-downgrade, the full URL of the current page is sent to:

  • Every external link the user clicks
  • Every third-party image, font, script, or stylesheet your page loads
  • Analytics endpoints, ad networks, and social share widgets
  • Any fetch() or XMLHttpRequest call to an external domain

This is a problem when your URLs carry meaningful data. Common real-world examples:

URL patternWhat leaks to third parties
/reset-password?token=abc123xyz The password-reset token, which may be valid for minutes or hours
/users/8421/settings An internal user ID, which an attacker could use for enumeration
/search?q=confidential+acquisition+plan The full search query — visible to your search analytics CDN
/admin/reports/Q2-revenue The fact that an admin panel exists and its URL structure
/checkout?cart_id=...&promo=STAFF50 Internal promotion codes and cart identifiers

If your site loads a Google Font, a Stripe.js file, an analytics pixel, or any third-party resource from a CDN, those servers receive a Referer header on every page load. The hosting companies for those services may log those headers. Setting a Referrer-Policy is a one-line fix that stops this.

All eight policy values explained

The Referrer-Policy header accepts one of eight values. “Origin” means just the scheme + domain + port (e.g. https://yoursite.com) with no path. “Full URL” means the complete URL including path and query string.

ValueSame-origin sendsCross-origin HTTPS sendsCross-origin HTTP sendsRisk
no-referrer Nothing Nothing Nothing Safest
no-referrer-when-downgrade Full URL Full URL Nothing Leaks paths cross-origin
origin Origin only Origin only Origin only Safe
origin-when-cross-origin Full URL Origin only Origin only Safe
same-origin Full URL Nothing Nothing Safe
strict-origin Origin only Origin only Nothing Safe
strict-origin-when-cross-origin Full URL Origin only Nothing Recommended
unsafe-url Full URL Full URL Full URL Always leaks paths

The two values you should avoid:

  • no-referrer-when-downgrade — was the old browser default. Sends the full URL cross-origin to any HTTPS destination, which covers the vast majority of third-party resources. Legacy — do not set explicitly.
  • unsafe-url — sends the full URL everywhere, including HTTP destinations. Maximally leaky. Only exists for backward-compatibility.

Which value to use

For almost every website, the right answer is strict-origin-when-cross-origin:

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

Here is what it does and why each part is correct:

  • Same-origin requests get the full URL. When your own pages link to each other or load your own resources, the full path is sent. This means your own server-side analytics and logs still see page-level referral data within your site.
  • Cross-origin HTTPS requests get only the origin. When you link to an external site or load a third-party resource over HTTPS, the destination sees https://yoursite.com — not the path. Third-party analytics providers can identify that the visitor came from your site; they cannot see which page or what the query string contained.
  • Cross-origin HTTP requests get nothing. If the destination is HTTP (an insecure, unencrypted connection), no referrer is sent at all. This prevents leaking your HTTPS URLs into an unencrypted channel where they can be intercepted.
This is already the browser default since 2021–2022. Chrome 85 (August 2020), Firefox 87 (March 2021), and Safari 14.5 (April 2021) all changed their default to strict-origin-when-cross-origin. But “the browser default” is not the same as an explicit header: older browsers, crawlers, and some enterprise proxies still use the old default. Setting the header explicitly costs two minutes and guarantees consistent behaviour everywhere. Security scanners, including HardenCheck, flag missing headers even when the effective behaviour is correct — because explicit is auditable and implicit is not.

When you might choose something stricter:

  • same-origin — if your site never needs external parties to know your origin at all and you don’t care about third-party referral attribution. Sends nothing cross-origin.
  • no-referrer — the most private option. Sends nothing, even same-origin. Breaks server-side referral tracking entirely. Appropriate for applications where URL paths are sensitive even to your own analytics.

Deploy it on your platform

nginx

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

Apache (.htaccess)

<IfModule mod_headers.c>
  Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>

Vercel (vercel.json)

{
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "Referrer-Policy",
          "value": "strict-origin-when-cross-origin"
        }
      ]
    }
  ]
}

Next.js (next.config.js)

const securityHeaders = [
  {
    key: 'Referrer-Policy',
    value: 'strict-origin-when-cross-origin'
  }
];

module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: securityHeaders,
      },
    ];
  },
};

Netlify (_headers file)

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

Cloudflare Pages (_headers file)

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

Express.js

app.use((req, res, next) => {
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
  next();
});

If you use the Helmet middleware, it sets Referrer-Policy: no-referrer by default. To use the recommended value instead:

app.use(helmet({
  referrerPolicy: { policy: 'strict-origin-when-cross-origin' }
}));
Combining multiple headers in one configuration block? You can set all five recommended headers — Referrer-Policy, Content-Security-Policy, Strict-Transport-Security, X-Content-Type-Options, and X-Frame-Options — in the same platform configuration block. Stack them together rather than maintaining separate configuration sections for each header.

Per-page and per-element overrides

The Referrer-Policy HTTP header sets the default for your entire site. You can override it at two more granular levels:

Per page — HTML meta tag

Add a <meta> tag in the <head> of any page. This overrides the HTTP header for that page only:

<meta name="referrer" content="no-referrer">

Useful for pages with particularly sensitive URL structure — admin panels, password reset flows, private reports — where you want even stricter behaviour than the site default.

Per element — referrerpolicy attribute

Individual links, images, iframes, scripts, and form elements accept a referrerpolicy attribute that overrides the page-level policy for that request only:

<!-- No referrer sent when a visitor clicks this external link -->
<a href="https://example.com/partner" referrerpolicy="no-referrer">Partner site</a>

<!-- Only origin sent when loading this external image -->
<img src="https://cdn.example.com/photo.jpg" referrerpolicy="origin">

<!-- No referrer for this iframe embed -->
<iframe src="https://embed.example.com/widget" referrerpolicy="no-referrer"></iframe>

The per-element attribute is additive: you can set a default policy that covers 99% of your site and add stricter policies on specific sensitive elements without changing the site-wide header.

Verify with HardenCheck

Once you’ve deployed your Referrer-Policy header, paste your raw response headers into HardenCheck. It checks whether the header is present, whether the value is a recognised policy, and whether it meets the recommended baseline of strict-origin-when-cross-origin or stricter. You can test different policy values by editing the paste directly and watching the grade update in real time, without touching your server.

Grade my headers with HardenCheck →

Frequently asked questions

What is the difference between Referer and Referrer-Policy?

Referer (note: misspelled in the original HTTP spec — one ‘r’) is the request header that browsers automatically attach to outgoing requests, containing the URL of the page that initiated the request. Referrer-Policy (spelled correctly) is the response header you set on your server to control what value the browser puts in that Referer header. The policy is yours to set; the Referer header is what the browser sends as a result.

Does strict-origin-when-cross-origin break my analytics?

No. strict-origin-when-cross-origin sends the full URL for same-origin requests (page to page within your own site) and sends only the origin for cross-origin requests. Your analytics tool collects the full page URL from the JavaScript data layer — it does not rely on the Referer header for page-level tracking. The Referer header is used by analytics to identify the referring domain (which campaign or external site sent the visitor), and strict-origin-when-cross-origin still sends the origin for that purpose.

Do I need to set Referrer-Policy if browsers already default to strict-origin-when-cross-origin?

Yes, for two reasons. First, older browsers and some enterprise proxies still use the old default (no-referrer-when-downgrade), which sends the full URL cross-origin. Setting the header explicitly ensures consistent behaviour across all clients. Second, security scanners — including HardenCheck — flag the absence of an explicit Referrer-Policy as a finding even when the effective behaviour happens to be correct. Explicit is auditable; implicit is not.

Can I set Referrer-Policy per page instead of for the whole site?

Yes. Add <meta name="referrer" content="no-referrer"> in the <head> of any page to override the HTTP header for that page only. You can also override at the element level using the referrerpolicy attribute on individual <a>, <img>, <link>, and <form> tags. This lets you set a relaxed site-wide default while applying a stricter policy on specific sensitive pages or links.

What does the Referer header actually expose in practice?

Without a Referrer-Policy, the browser sends the full URL of the current page to every external link click, every third-party image or script your page loads, and every external API call your JavaScript makes. If your URLs contain a user ID (/users/12345/settings), a session token (/reset?token=abc123), a search query, or a private path (/admin/reports/Q2), all of that is transmitted to every external domain your page references.

What happens if I set no-referrer?

The browser sends an empty Referer header on all requests — same-origin and cross-origin. Third parties receive nothing. Your own server-side analytics that rely on the Referer header for traffic-source attribution will stop seeing referral data entirely. For most sites, strict-origin-when-cross-origin is the right balance: same-origin requests still carry the full URL, while cross-origin requests are limited to just the origin.

Does Referrer-Policy affect API requests made by JavaScript?

Yes. The policy governs the Referer header on all requests the browser makes, including fetch() and XMLHttpRequest calls. If your JavaScript fetches a third-party API and you have no Referrer-Policy set, the current page’s full URL is sent in the Referer header of that API request. With strict-origin-when-cross-origin, only your site’s origin is sent to cross-origin APIs. Same-origin API calls still receive the full URL, which is expected and generally fine.

Also in the Copper Bay Labs ship-safety suite

Referrer-Policy is one of five security headers HardenCheck checks — here are guides for the others: