What Is the Referrer Header?
When a user clicks a link on your website to navigate to another site, the browser sends a Referer header (yes, it's misspelled — the original HTTP specification had a typo that stuck) with the request. This header contains the URL of the page the user came from.
For example, if a user on https://example.com/dashboard/settings?user=john clicks a link to https://external-site.com, the browser sends:
Referer: https://example.com/dashboard/settings?user=johnThat external site now knows: - The user came from example.com - They were on the dashboard settings page - The URL contains a username parameter
This is the referrer leakage problem.
Why Referrer Leakage Is a Privacy Problem
Referrer leakage exposes sensitive information in several ways:
### URL Parameters
Many applications put sensitive data in URLs:
- Session tokens: ?token=abc123
- User identifiers: ?user_id=42
- Search queries: ?q=medical+symptoms
- API keys: ?key=sk_live_xxx
- Password reset tokens: /reset?token=secret
When these URLs appear in the Referer header, external sites receive data they were never intended to see.
### Internal Structure Exposure
Even without sensitive parameters, referrer URLs reveal:
- Your application's URL structure and routing patterns
- Internal page names (admin panels, internal tools)
- User workflow patterns (which pages they visit in sequence)
- Technology indicators (e.g., /wp-admin/ reveals WordPress)
### Real-World Consequences - Healthcare sites leaking medical search queries to advertisers - Banking sites leaking account numbers in URL parameters - HR platforms leaking employee IDs to third-party analytics - E-commerce sites leaking order details to social media pixels
### Third-Party Scripts It's not just external links. Every third-party resource your page loads (analytics scripts, ad pixels, social media widgets, CDN resources) can read the current page URL. This means dozens of companies may know which pages your users visit.
Referrer-Policy Directives Explained
The Referrer-Policy header lets you control exactly how much referrer information the browser shares. Here are all eight possible values:
### no-referrer
Never send the Referer header. Maximum privacy.
Referer: (not sent)### no-referrer-when-downgrade
Send the full URL for same-protocol requests. Don't send anything when navigating from HTTPS to HTTP. This was the default browser behavior before 2020.
HTTPS → HTTPS: Referer: https://example.com/page?q=test
HTTPS → HTTP: Referer: (not sent)### origin
Send only the origin (scheme + host + port), never the path or query string.
Referer: https://example.com### origin-when-cross-origin
Send the full URL for same-origin requests. Send only the origin for cross-origin requests.
Same-origin: Referer: https://example.com/page?q=test
Cross-origin: Referer: https://example.com### same-origin
Send the full URL for same-origin requests. Don't send anything for cross-origin requests.
Same-origin: Referer: https://example.com/page?q=test
Cross-origin: Referer: (not sent)### strict-origin
Send only the origin for same-protocol requests. Don't send anything on downgrade (HTTPS → HTTP).
HTTPS → HTTPS: Referer: https://example.com
HTTPS → HTTP: Referer: (not sent)### strict-origin-when-cross-origin
The most balanced option and the current browser default. Full URL for same-origin, origin-only for cross-origin (same protocol), nothing on downgrade.
Same-origin: Referer: https://example.com/page?q=test
Cross-origin: Referer: https://example.com
HTTPS → HTTP: Referer: (not sent)### unsafe-url
Always send the full URL, even on downgrades. Never use this — it defeats the purpose of having a policy.
Which Value Should You Use?
For most websites, here's the decision:
| Use Case | Recommended Policy |
|---|---|
| Most websites | strict-origin-when-cross-origin |
| Privacy-focused sites | no-referrer |
| Sites with sensitive URL parameters | same-origin or no-referrer |
| E-commerce / SaaS | strict-origin-when-cross-origin |
| Healthcare / Financial | no-referrer or same-origin |
| Sites that depend on referrer analytics | origin-when-cross-origin |
Our recommendation: Start with strict-origin-when-cross-origin. It's the best balance between privacy and functionality. It prevents URL parameter leakage to external sites while still allowing your analytics to see internal navigation paths.
If you handle particularly sensitive data (health, finance, legal), consider no-referrer or same-origin.
Setting Referrer-Policy
Nginx
server {
listen 443 ssl http2;
server_name example.com;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}Apache
Header always set Referrer-Policy "strict-origin-when-cross-origin"Next.js
In next.config.js:
const nextConfig = {
async headers() {
return [
{
source: '/(.*)',
headers: [
{
key: 'Referrer-Policy',
value: 'strict-origin-when-cross-origin',
},
],
},
];
},
};
module.exports = nextConfig;Express.js
app.use((req, res, next) => {
res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
next();
});Or with the helmet middleware:
const helmet = require('helmet');
app.use(helmet.referrerPolicy({ policy: 'strict-origin-when-cross-origin' }));HTML-Level Referrer Control
Beyond the HTTP header, you can set referrer policy at the HTML level:
Meta Tag (Page-Wide)
<meta name="referrer" content="strict-origin-when-cross-origin">Per-Link Control
<a href="https://external.com" referrerpolicy="no-referrer">External Link</a>Per-Element Control
<img src="https://cdn.example.com/image.jpg" referrerpolicy="no-referrer">
<iframe src="https://widget.example.com" referrerpolicy="no-referrer"></iframe>
<script src="https://analytics.example.com/script.js" referrerpolicy="no-referrer"></script>rel="noreferrer" on Links
<a href="https://external.com" rel="noreferrer">External Link</a>This is equivalent to referrerpolicy="no-referrer" and also implies rel="noopener", which prevents the linked page from accessing window.opener.
Priority order: Per-element attribute > <meta> tag > HTTP header > browser default.
Test Your Implementation
### Browser DevTools
1. Open DevTools (F12) → Network tab
2. Click on any request to an external resource
3. Look at the Request Headers section for Referer
4. Verify it matches your expected policy behavior
Curl Check
curl -s -D - -o /dev/null https://your-site.com | grep -i referrer-policy### Full Scan Run your site through ZeriFlow to verify your Referrer-Policy header is set correctly alongside all other security headers.
Impact on Analytics
Changing your Referrer-Policy will affect analytics data — both yours and others':
### Your Analytics
- no-referrer or same-origin will break referrer tracking for external links pointing to your site. You won't see which sites send you traffic in Google Analytics or similar tools.
- strict-origin-when-cross-origin preserves origin-level referrer data (you'll see https://example.com but not the full path), which is sufficient for most analytics needs.
### Others' Analytics - Sites you link to will receive less referrer data, which may affect their analytics - This is generally considered good practice — you're protecting your users' privacy
### UTM Parameters Still Work
If you use UTM parameters for campaign tracking (?utm_source=newsletter), they work regardless of Referrer-Policy because they're on the destination URL, not the referrer.
### Recommendation
Use strict-origin-when-cross-origin to maintain useful analytics while protecting user privacy. If you switch to no-referrer, rely on UTM parameters for campaign tracking.
