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 exposes
- All eight policy values
- Which value to use
- Deploy on your platform
- Per-page and per-element overrides
- Verify with HardenCheck
- FAQ
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()orXMLHttpRequestcall to an external domain
This is a problem when your URLs carry meaningful data. Common real-world examples:
| URL pattern | What 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.
| Value | Same-origin sends | Cross-origin HTTPS sends | Cross-origin HTTP sends | Risk |
|---|---|---|---|---|
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.
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' }
}));
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:
Write a Content-Security-Policy that blocks XSS without breaking your site — with report-only mode, nonces, hashes, and platform snippets.
Fix guide Enable HSTSForce HTTPS at the browser level — so attackers can’t strip the connection even if a visitor types http://.
Fix guide X-Content-Type-OptionsStop MIME-sniffing attacks that turn uploaded files into executable scripts.
Secret scanning LeakCheckPaste code or a config file and see exposed API keys and secrets flagged before they reach the repo.
ADA & privacy ShipSafeCheck your site for WCAG accessibility failures and privacy-risk patterns before they become liabilities.