Skip to main content
Back to blog
April 27, 2026·Updated May 2, 2026|9 min read|Antoine Duno|Web Security

Referrer-Policy Explained: Control Data Leakage from Your Website

The Referer header silently leaks URL fragments, session tokens, and user paths to third parties on every navigation. The Referrer-Policy header gives you precise control over what gets shared — and most sites are using the wrong setting.

Antoine Duno

1,448 words

AD

Antoine Duno

Founder of ZeriFlow · 10 years fullstack engineering · About the author

Key Takeaways

  • The Referer header silently leaks URL fragments, session tokens, and user paths to third parties on every navigation. The Referrer-Policy header gives you precise control over what gets shared — and most sites are using the wrong setting.
  • Includes copy-paste code examples and step-by-step instructions.
  • Free automated scan available to verify your implementation.

Referrer-Policy Explained: Control Data Leakage from Your Website

When a user clicks a link on your website and navigates to another site, or when your page loads external resources (images, scripts, fonts, analytics), the browser sends a Referer header to those external servers. That header contains the URL of the page the request originated from.

Most developers treat this as a minor technicality. It is not. In 2026, the combination of complex URLs, third-party analytics, CDNs, and embedded content means that the Referer header routinely transmits data you did not intend to share — sometimes including session tokens, user-specific identifiers, and sensitive path parameters.

The Referrer-Policy header (note: "Referrer" is spelled correctly in the header name, unlike the historical typo in the Referer request header) is your control mechanism.

What the Referer Header Actually Leaks

Before examining the policy values, it helps to understand concretely what the Referer header exposes.

Token leakage in URLs:

https://app.example.com/reset-password?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

If this page includes a tracking pixel, Google Analytics snippet, or any third-party resource, the full URL — including the password reset token — is sent to that third party in the Referer header.

User ID exposure:

https://app.example.com/users/84729/settings

Loading a Google Font or any external resource from this page sends the user ID to Google or the CDN provider. Depending on your terms of service and privacy policy, this may constitute an undisclosed transfer of personal data.

Search query leakage:

https://app.example.com/search?q=John+Smith+accountant+London

If your search results page loads external resources, the search query is transmitted to those providers.

API endpoint exposure:

https://internal-admin.example.com/api/users/bulk-export?format=csv&scope=all

Internal tool URLs can reveal internal API structure, admin functionality, and operational data.

The third-party scope problem: When you add a Google Analytics script, a Hotjar heatmap, a Stripe payment form, a social sharing button, or an embedded video to your page, each of these loads resources from external servers. Each of those resource requests carries the full Referer URL from the page that loaded them — unless you have set a Referrer-Policy.

All 8 Referrer-Policy Values Explained

The specification defines eight directive values. Understanding each one is necessary to choose correctly.

### 1. no-referrer No Referer header is sent on any request, regardless of origin or protocol.

Use when: Maximum privacy is required — internal tools, admin panels, health or financial applications. Trade-off: Analytics and some legitimate third-party integrations may break or lose useful context.

### 2. no-referrer-when-downgrade Sends the full URL as Referer when navigating to HTTPS, but sends nothing when navigating from HTTPS to HTTP (downgrade).

This was the browser default before 2020. It is not a secure default for most applications — it sends full URLs including tokens and paths to all HTTPS destinations.

Use when: You need legacy compatibility and are certain your URLs contain no sensitive data.

### 3. origin Sends only the origin (scheme + host + port) — never the path or query string.

# Full URL: https://app.example.com/users/84729/settings
# Referer sent: https://app.example.com

Use when: You want analytics providers to know traffic came from your domain but not which specific pages. Some third-party integrations need the origin for attribution.

### 4. origin-when-cross-origin Sends the full URL for same-origin requests (within your own domain) and only the origin for cross-origin requests.

# Same-origin request (within app.example.com):
# Referer sent: https://app.example.com/users/84729/settings

# Cross-origin request (to analytics.thirdparty.com):
# Referer sent: https://app.example.com

Use when: You want internal analytics to see full page paths but external services to see only your domain.

### 5. same-origin Sends the full URL for same-origin requests. Sends nothing for cross-origin requests.

Use when: You only care about same-origin navigation tracking (internal analytics), and you want complete privacy from all external parties.

### 6. strict-origin Sends only the origin for same-protocol requests (HTTPS to HTTPS, HTTP to HTTP). Sends nothing for downgrade (HTTPS to HTTP) requests.

This is similar to origin but adds protection against protocol downgrade.

### 7. strict-origin-when-cross-origin - Same-origin requests: full URL is sent - Cross-origin same-protocol requests (HTTPS to HTTPS): only origin is sent - Protocol downgrade (HTTPS to HTTP): nothing is sent

This is the recommended default for most applications. It provides useful same-origin navigation tracking for your own analytics while protecting path and query data from external parties, and preventing any leakage to non-HTTPS destinations.

### 8. unsafe-url Always sends the full URL regardless of origin or protocol. No privacy protection whatsoever.

Use when: Never in production. This is the least restrictive option and exists primarily for testing.

Policy Behavior Summary

PolicySame-OriginCross-Origin HTTPSCross-Origin HTTP
no-referrer
no-referrer-when-downgradeFull URLFull URL
originOriginOriginOrigin
origin-when-cross-originFull URLOriginOrigin
same-originFull URL
strict-originOriginOrigin
strict-origin-when-cross-originFull URLOrigin
unsafe-urlFull URLFull URLFull URL

Which Policy to Choose

For most web applications in 2026:

`strict-origin-when-cross-origin` — the right default. Your own analytics (if same-origin) still see full page paths. Third-party services only know your domain. No leakage over non-HTTPS channels.

`no-referrer` — for applications handling especially sensitive data: healthcare portals, legal platforms, financial tools, internal admin panels. The slight loss of analytics fidelity is worth the privacy guarantee.

`origin-when-cross-origin` — if you rely on cross-origin analytics that need some URL context but not full paths. Less recommended in 2026 given the privacy implications.

Avoid no-referrer-when-downgrade and unsafe-url in any user-facing production application.

GDPR Implications

Referrer leakage has a direct relationship with GDPR''s data minimization and lawful transfer requirements. When the full URL of a page (which may contain personal data — user IDs, search terms, token fragments) is sent to a third-party analytics or CDN provider:

  1. 1That third party becomes a data recipient under GDPR
  2. 2If they are outside the EU/EEA (e.g., US-based analytics), a lawful transfer mechanism is required
  3. 3The transfer must be documented in your Article 30 Records of Processing Activities
  4. 4Users must be informed in your privacy policy

Setting Referrer-Policy: strict-origin-when-cross-origin or stricter is a direct technical implementation of GDPR''s data minimization principle — you share only what is necessary (the domain, for basic attribution) rather than everything (the full URL with personal data).

Several EU DPA enforcement actions have cited unnecessary data sharing with analytics providers via referrer headers as evidence of inadequate privacy practices.

How to Implement Referrer-Policy

Nginx

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

Apache

apache
Header always set Referrer-Policy "strict-origin-when-cross-origin"

Express.js (with Helmet)

javascript
import helmet from ''helmet'';

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

Next.js (next.config.js)

javascript
module.exports = {
  async headers() {
    return [
      {
        source: ''/(.*)'',
        headers: [
          {
            key: ''Referrer-Policy'',
            value: ''strict-origin-when-cross-origin'',
          },
        ],
      },
    ];
  },
};

HTML Meta Tag (per-page)

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

Use the meta tag when you cannot control server headers — for example, static HTML files or third-party CMS platforms.

You can override the global policy for individual links using the referrerpolicy attribute:

html
<!-- Override to send nothing for a specific sensitive external link -->
<a href="https://external-partner.com/signup" referrerpolicy="no-referrer">
  Register with Partner
</a>

<!-- Override to send full URL for a specific same-origin link (for tracking) -->
<a href="/dashboard/overview" referrerpolicy="unsafe-url">
  Dashboard
</a>

This granularity is useful when you have a general policy of strict-origin-when-cross-origin but specific flows that require different behavior.

Browser Support

Referrer-Policy is supported in all modern browsers as of 2026: - Chrome 56+ (2017) - Firefox 52+ (2017) - Safari 11.1+ (2018) - Edge 79+ (2020)

Browsers that do not support the header fall back to their default behavior, which in modern browsers is strict-origin-when-cross-origin (Chrome 85+, Firefox 87+, Safari 14+). Older browsers may fall back to no-referrer-when-downgrade, which is the reason for setting the header explicitly rather than relying on defaults.

Verification

bash
# Check your current header
curl -I https://yourapp.com | grep -i referrer-policy

# Expected output:
# referrer-policy: strict-origin-when-cross-origin

ZeriFlow checks for Referrer-Policy and 6 other critical security headers as part of its 80+ check scan, with specific recommendations for which directive to use based on your application type. Run a free scan at zeriflow.com.

Ready to check your site?

Run a free security scan in 30 seconds.

Related articles

Keep reading