HTTP

Header

Referrer-Policy Header

Learn how Referrer-Policy controls how much referrer information is sent with requests. Protect user privacy while maintaining analytics functionality.

6 min read intermediate Try in Playground

TL;DR: Controls how much referrer information is sent with requests to protect user privacy. Use strict-origin-when-cross-origin for balanced privacy and functionality.

What is Referrer-Policy?

The Referrer-Policy header controls how much referrer information (the URL of the previous page) is included in the Referer header when navigating from your site or loading resources. It’s a privacy and security feature that lets you decide what information to share about where users came from.

Think of it like deciding how much information to share when you refer someone to another place - you can share the full address, just the street name, or nothing at all.

How Referrer-Policy Works

Without policy (default behavior):

GET https://example.com/page HTTP/1.1
Host: example.com
```text

User clicks link to `https://external.com/article`:

```http
GET /article HTTP/1.1
Host: external.com
Referer: https://example.com/page?user=123&token=secret

Full URL including sensitive parameters is sent!

With strict policy:

HTTP/1.1 200 OK
Referrer-Policy: no-referrer
Content-Type: text/html

<html>...</html>
```text

User clicks link to external site:

```http
GET /article HTTP/1.1
Host: external.com
(no Referer header)

No referrer information is sent, protecting privacy.

Syntax

Referrer-Policy: <directive>
```text

Multiple policies can be comma-separated (browser uses first supported one):

```http
Referrer-Policy: no-referrer, strict-origin-when-cross-origin

Policy Directives

no-referrer

Never send Referer header.

Referrer-Policy: no-referrer
```text

**Example:**

```http
From: https://example.com/private/page?id=123
To:   https://external.com/article
Referer: (not sent)
```text

### no-referrer-when-downgrade (default)

Send full URL for same-protocol requests. Don't send when downgrading from HTTPS to HTTP.

```http
Referrer-Policy: no-referrer-when-downgrade

Examples:

From: https://example.com/page
To:   https://other.com/article
Referer: https://example.com/page

From: https://example.com/page
To:   http://other.com/article (downgrade)
Referer: (not sent)

origin

Send only the origin (scheme, host, port), not the full URL.

Referrer-Policy: origin
```text

**Example:**

```http
From: https://example.com/path/to/page?query=value
To:   https://other.com/article
Referer: https://example.com/
```text

### origin-when-cross-origin

Send full URL for same-origin requests, only origin for cross-origin.

```http
Referrer-Policy: origin-when-cross-origin

Examples:

From: https://example.com/page1
To:   https://example.com/page2 (same-origin)
Referer: https://example.com/page1

From: https://example.com/page1
To:   https://other.com/page (cross-origin)
Referer: https://example.com/

same-origin

Send full URL for same-origin requests, nothing for cross-origin.

Referrer-Policy: same-origin
```text

**Examples:**

```http
From: https://example.com/page1
To:   https://example.com/page2 (same-origin)
Referer: https://example.com/page1

From: https://example.com/page1
To:   https://other.com/page (cross-origin)
Referer: (not sent)
```text

### strict-origin

Send only origin when protocol is same or upgraded, nothing when downgrading.

```http
Referrer-Policy: strict-origin

Examples:

From: https://example.com/private/page
To:   https://other.com/article
Referer: https://example.com/

From: https://example.com/page
To:   http://other.com/article (downgrade)
Referer: (not sent)

Full URL for same-origin, origin for cross-origin (if not downgrading), nothing when downgrading.

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

**Examples:**

```http
From: https://example.com/page1?user=123
To:   https://example.com/page2 (same-origin)
Referer: https://example.com/page1?user=123

From: https://example.com/page?user=123
To:   https://other.com/article (cross-origin)
Referer: https://example.com/

From: https://example.com/page
To:   http://other.com/article (downgrade)
Referer: (not sent)
```text

### unsafe-url

Always send full URL (least privacy).

```http
Referrer-Policy: unsafe-url

Example:

From: https://example.com/private/page?token=secret
To:   http://other.com/article
Referer: https://example.com/private/page?token=secret

Warning: This can leak sensitive information!

Common Examples

Privacy-Focused Site

HTTP/1.1 200 OK
Referrer-Policy: no-referrer
Content-Type: text/html

<!DOCTYPE html>
<html>
  <!-- No referrer sent for any links -->
</html>
```text

### Balanced Privacy and Analytics

```http
HTTP/1.1 200 OK
Referrer-Policy: strict-origin-when-cross-origin
Content-Type: text/html

Most common and recommended policy.

Same-Origin Only

HTTP/1.1 200 OK
Referrer-Policy: same-origin
Content-Type: text/html
```text

Internal analytics work, external sites get nothing.

### Express.js Configuration

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

Real-World Scenarios

E-commerce Checkout

HTTP/1.1 200 OK
Referrer-Policy: no-referrer
Content-Type: text/html

<!DOCTYPE html>
<html>
  <!-- Protect order details in URL -->
  <a href="https://payment.example.com/pay">
    Complete Payment
  </a>
</html>
```text

Prevents leaking order IDs or cart contents to payment processor.

### Social Media Platform

```javascript
// Node.js/Express
app.use((req, res, next) => {
  // Protect user profiles from being leaked
  if (req.path.startsWith('/user')) {
    res.setHeader('Referrer-Policy', 'same-origin')
  } else {
    res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin')
  }
  next()
})
<!-- Override default policy for specific links -->
<a href="https://analytics.example.com/track" referrerpolicy="no-referrer"> Track Event </a>

<a href="https://trusted-partner.com" referrerpolicy="origin"> Partner Site </a>

<!-- Image with no referrer -->
<img src="https://external.com/pixel.gif" referrerpolicy="no-referrer" />
```text

### API Endpoints

```javascript
// Different policies for different endpoints
app.get('/public/*', (req, res, next) => {
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin')
  next()
})

app.get('/private/*', (req, res, next) => {
  res.setHeader('Referrer-Policy', 'no-referrer')
  next()
})

app.get('/admin/*', (req, res, next) => {
  res.setHeader('Referrer-Policy', 'same-origin')
  next()
})

Meta Tag Alternative

<!-- Can also be set via meta tag -->
<meta name="referrer" content="strict-origin-when-cross-origin" />
```text

**Note:** HTTP header takes precedence over meta tag.

## Best Practices

### 1. Use strict-origin-when-cross-origin as Default

```javascript
// ✅ Balanced privacy and functionality
app.use((req, res, next) => {
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin')
  next()
})

2. Use no-referrer for Sensitive Pages

// ✅ Protect sensitive information
app.get('/account/payment', (req, res) => {
  res.setHeader('Referrer-Policy', 'no-referrer')
  res.render('payment')
})

app.get('/admin/users', (req, res) => {
  res.setHeader('Referrer-Policy', 'no-referrer')
  res.render('admin')
})
```javascript

### 3. Clean URLs Before External Links

```javascript
// ✅ Remove sensitive query parameters
function cleanURL(url) {
  const cleaned = new URL(url)
  // Remove sensitive params
  cleaned.searchParams.delete('token')
  cleaned.searchParams.delete('session')
  cleaned.searchParams.delete('api_key')
  return cleaned.toString()
}

4. Test Referrer Policy Impact

// ✅ Monitor analytics impact
app.use((req, res, next) => {
  const referer = req.headers.referer || req.headers.referrer

  // Log referrer availability for analytics
  if (req.path.startsWith('/api/analytics')) {
    console.log('Referer header present:', !!referer)
  }

  next()
})
```javascript

### 5. Helmet.js (Express)

```javascript
const helmet = require('helmet')

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

Common Patterns

Environment-Based Policy

const isDevelopment = process.env.NODE_ENV === 'development'

const referrerPolicy = isDevelopment
  ? 'unsafe-url' // Full URLs in dev for debugging
  : 'strict-origin-when-cross-origin' // Strict in production

app.use((req, res, next) => {
  res.setHeader('Referrer-Policy', referrerPolicy)
  next()
})
```text

### Content-Type Specific

```javascript
app.use((req, res, next) => {
  // API endpoints: no referrer
  if (req.path.startsWith('/api')) {
    res.setHeader('Referrer-Policy', 'no-referrer')
  }
  // Regular pages: balanced policy
  else {
    res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin')
  }
  next()
})

Fallback Policy

# Multiple policies (first supported one is used)
Referrer-Policy: no-referrer, strict-origin-when-cross-origin
```javascript

## Privacy Implications

### Protecting User Privacy

```javascript
// URLs that may contain sensitive info
const sensitivePatterns = ['/user', '/account', '/payment', '/admin', '/reset-password']

app.use((req, res, next) => {
  const isSensitive = sensitivePatterns.some((pattern) => req.path.includes(pattern))

  if (isSensitive) {
    res.setHeader('Referrer-Policy', 'no-referrer')
  } else {
    res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin')
  }

  next()
})

Query Parameter Leakage

# Bad: Sensitive data in URL
https://example.com/reset-password?token=secret123&email=user@example.com

# If referrer policy is unsafe-url:
User clicks external link → token and email leaked!

# Solution: Use no-referrer or keep tokens in POST body

Analytics Considerations

Impact on Analytics

// strict-origin-when-cross-origin allows:
// - Same-origin: full URL (good for internal analytics)
// - Cross-origin: origin only (protects privacy)

// Track referrer availability
app.get('/analytics/track', (req, res) => {
  const referer = req.headers.referer

  if (referer) {
    // Can track traffic source
    console.log('Traffic from:', referer)
  } else {
    // Referrer blocked by policy
    console.log('No referrer (privacy protected)')
  }

  res.sendStatus(200)
})
```javascript

### UTM Parameters

```javascript
// Use UTM parameters for cross-origin tracking instead of relying on Referer
// ?utm_source=google&utm_medium=cpc&utm_campaign=spring_sale

app.get('/landing', (req, res) => {
  const source = req.query.utm_source
  const medium = req.query.utm_medium

  // Track via query params, not Referer header
  analytics.track({ source, medium })

  res.render('landing')
})

Testing

Check Current Policy

# Using curl
curl -I https://example.com | grep -i referrer-policy

# Output:
# referrer-policy: strict-origin-when-cross-origin
```javascript

### Test Referrer Behavior

```html
<!-- Test page -->
<!DOCTYPE html>
<html>
  <head>
    <meta name="referrer" content="strict-origin-when-cross-origin" />
  </head>
  <body>
    <script>
      // Check what referrer is sent
      fetch('https://httpbin.org/headers')
        .then((r) => r.json())
        .then((data) => {
          console.log('Referer header:', data.headers.Referer || 'not sent')
        })
    </script>
  </body>
</html>

Browser DevTools

1. Open DevTools → Network tab
2. Click link or load resource
3. Check request headers for "Referer"
4. Compare with current page URL

Browser Support

All modern browsers support Referrer-Policy:

  • Chrome 61+
  • Firefox 52+
  • Safari 11.1+
  • Edge 79+

Default policy (if not specified):

  • Modern browsers: strict-origin-when-cross-origin
  • Older browsers: no-referrer-when-downgrade

Frequently Asked Questions

What is Referrer-Policy?

Referrer-Policy controls how much referrer information is sent with requests. It helps protect user privacy by limiting URL information shared with other sites.

What is a good default Referrer-Policy?

strict-origin-when-cross-origin is a good default. It sends full referrer to same-origin, only origin to cross-origin HTTPS, and nothing to HTTP.

What does no-referrer do?

no-referrer never sends the Referer header. Use it for maximum privacy but note it may break analytics and some functionality that depends on referrer.

Why is it Referrer-Policy but Referer header?

The Referer header has a historical misspelling from the HTTP specification. Referrer-Policy uses the correct spelling. Both refer to the same concept.

Keep Learning