HTTP

Header

Referer Header

Learn how the Referer header tells servers which page led to the current request. Understand its use in analytics, security, and privacy implications.

5 min read beginner Try in Playground

TL;DR: Tells servers which page the user came from before making the current request. Use for analytics and security checks, but don’t rely on it alone as it can be missing or spoofed.

What is Referer?

The Referer header tells the server which page the user came from before making the current request. It’s like leaving breadcrumbs—it shows the path users take through websites. This information is valuable for analytics, security, and user experience.

Note: The header name “Referer” is intentionally misspelled (should be “Referrer”) due to a historical typo in the HTTP specification.

How Referer Works

User clicks link on page A:

<!-- On https://blog.example.com/post-1 -->
<a href="https://shop.example.com/products">Visit Shop</a>
```http

**Browser sends request with Referer:**

```http
GET /products HTTP/1.1
Host: shop.example.com
Referer: https://blog.example.com/post-1
Accept: text/html

Server can track the referral:

// Server logs: User came from blog post to shop
console.log('Referral from:', req.headers.referer)
```http

## Referer Format

### Complete URL

```http
Referer: https://example.com/page
Referer: https://search.google.com/search?q=http+tutorial
Referer: https://social.media.com/post/123

No Referer

# Header is omitted when:
# - Direct URL entry
# - Bookmark access
# - Privacy settings block it
```text

## When Browsers Send Referer

### Always Sent For:

- Link clicks between pages
- Form submissions
- Image/resource requests
- AJAX requests (same-origin)

### Sometimes Sent For:

- HTTPS to HTTP requests (blocked by default)
- Cross-origin requests (depends on policy)
- JavaScript redirects

### Never Sent For:

- Direct URL entry in address bar
- Bookmarks
- When blocked by privacy settings

## Real-World Examples

### Blog to E-commerce

```http
GET /product/laptop HTTP/1.1
Host: shop.example.com
Referer: https://blog.example.com/best-laptops-2026

User clicked product link in blog post.

Search Engine Traffic

GET /tutorials/http HTTP/1.1
Host: mysite.com
Referer: https://www.google.com/search?q=http+tutorial
```text

User found site through Google search.

### Social Media Referral

```http
GET /article/web-development HTTP/1.1
Host: news.example.com
Referer: https://twitter.com/

User clicked link shared on Twitter.

Internal Navigation

GET /checkout HTTP/1.1
Host: shop.example.com
Referer: https://shop.example.com/cart
```javascript

User proceeded from cart to checkout.

## Server-Side Usage

### Analytics and Tracking

```javascript
app.use((req, res, next) => {
  const referer = req.headers.referer

  if (referer) {
    // Log referral source
    analytics.track('page_view', {
      page: req.path,
      referer: referer,
      user: req.user?.id
    })

    // Track external referrals
    if (!referer.includes(req.headers.host)) {
      analytics.track('external_referral', {
        source: new URL(referer).hostname,
        target: req.path
      })
    }
  }

  next()
})

Security Validation

app.post('/api/sensitive-action', (req, res) => {
  const referer = req.headers.referer
  const allowedReferers = ['https://myapp.com', 'https://www.myapp.com', 'https://admin.myapp.com']

  // Basic CSRF protection
  if (!referer || !allowedReferers.some((allowed) => referer.startsWith(allowed))) {
    return res.status(403).json({ error: 'Invalid referer' })
  }

  // Process request
  processAction(req.body)
})
```javascript

### Content Personalization

```javascript
app.get('/welcome', (req, res) => {
  const referer = req.headers.referer
  let welcomeMessage = 'Welcome to our site!'

  if (referer) {
    const refererHost = new URL(referer).hostname

    if (refererHost.includes('google.com')) {
      welcomeMessage = "Welcome from Google! Find what you're looking for."
    } else if (refererHost.includes('facebook.com')) {
      welcomeMessage = 'Welcome from Facebook! Thanks for clicking our link.'
    } else if (refererHost === req.headers.host) {
      welcomeMessage = 'Welcome back! Continue exploring our content.'
    }
  }

  res.render('welcome', { message: welcomeMessage })
})

Privacy and Security

Referer Policy Control

<!-- Control referer behavior -->
<meta name="referrer" content="strict-origin-when-cross-origin" />

<!-- Link-specific control -->
<a href="https://external.com" rel="noreferrer">No Referer Link</a>
<a href="https://external.com" rel="noopener noreferrer">Secure External Link</a>
```text

### JavaScript Referer Policy

```javascript
// Set referer policy for fetch requests
fetch('https://api.example.com/data', {
  referrerPolicy: 'strict-origin-when-cross-origin'
})

Server Response Headers

// Control referer policy for all links on page
app.use((req, res, next) => {
  res.set('Referrer-Policy', 'strict-origin-when-cross-origin')
  next()
})
```text

## Common Referer Policies

### strict-origin-when-cross-origin (Default)

```text
Same-origin: Full URL
Cross-origin HTTPSHTTPS: Origin only
Cross-origin HTTPSHTTP: No referer
```text

### no-referrer

```text
All requests: No referer header
```text

### origin

```text
All requests: Origin only (no path)
```text

### unsafe-url

```text
All requests: Full URL (including HTTPSHTTP)
```javascript

## Analytics Use Cases

### Traffic Source Analysis

```javascript
function categorizeReferer(referer) {
  if (!referer) return 'direct'

  const hostname = new URL(referer).hostname

  // Search engines
  if (hostname.includes('google.')) return 'google'
  if (hostname.includes('bing.')) return 'bing'
  if (hostname.includes('yahoo.')) return 'yahoo'

  // Social media
  if (hostname.includes('facebook.')) return 'facebook'
  if (hostname.includes('twitter.')) return 'twitter'
  if (hostname.includes('linkedin.')) return 'linkedin'

  // Internal
  if (hostname === process.env.SITE_DOMAIN) return 'internal'

  return 'other'
}

app.use((req, res, next) => {
  const source = categorizeReferer(req.headers.referer)
  req.trafficSource = source
  next()
})

Conversion Tracking

app.post('/purchase', (req, res) => {
  const referer = req.headers.referer

  // Track which pages lead to purchases
  analytics.track('purchase', {
    amount: req.body.amount,
    referer_page: referer,
    conversion_source: categorizeReferer(referer)
  })

  processPurchase(req.body)
})
```text

## Security Considerations

### CSRF Protection Limitations

```javascript
// ❌ Weak: Referer can be spoofed or missing
app.post('/api/transfer', (req, res) => {
  if (!req.headers.referer?.includes('mybank.com')) {
    return res.status(403).send('Forbidden')
  }
  // Process transfer
})

// ✅ Strong: Use CSRF tokens
app.post('/api/transfer', (req, res) => {
  if (!validateCSRFToken(req.body.csrfToken, req.session)) {
    return res.status(403).send('Forbidden')
  }
  // Process transfer
})

Privacy Leakage

// Be careful with sensitive URLs in referer
app.get('/public-page', (req, res) => {
  const referer = req.headers.referer

  // Don't log sensitive referer URLs
  if (referer && !referer.includes('/private') && !referer.includes('/admin')) {
    analytics.track('page_view', { referer })
  }
})
```text

## Testing Referer Headers

### Using curl

```bash
# Simulate referer
curl -H "Referer: https://google.com/search?q=test" \
     https://example.com/page

# No referer (direct access)
curl https://example.com/page

JavaScript Testing

// Check current referer
console.log('Came from:', document.referrer)

// Make request with custom referer policy
fetch('/api/data', {
  referrerPolicy: 'origin'
})
```javascript

### Browser DevTools

1. Open Network tab
2. Navigate between pages
3. Look for Referer header in requests
4. Notice when it's present vs. missing

## Best Practices

### Validate Referer Safely

```javascript
function isValidReferer(referer, allowedDomains) {
  if (!referer) return false

  try {
    const url = new URL(referer)
    return allowedDomains.includes(url.hostname)
  } catch {
    return false
  }
}

Handle Missing Referers

app.get('/landing', (req, res) => {
  const referer = req.headers.referer

  // Don't assume referer is always present
  const source = referer ? categorizeReferer(referer) : 'direct'

  res.render('landing', {
    source,
    showWelcomeMessage: source !== 'direct'
  })
})
```javascript

### Respect Privacy

```javascript
// Don't log full URLs with sensitive data
function sanitizeReferer(referer) {
  if (!referer) return null

  try {
    const url = new URL(referer)
    // Remove query parameters that might contain sensitive data
    return `${url.protocol}//${url.hostname}${url.pathname}`
  } catch {
    return null
  }
}
  • Origin - Request origin for CORS
  • User-Agent - Client identification
  • Host - Target server domain
  • Cookie - Session tracking alternative

Frequently Asked Questions

What is the Referer header?

Referer contains the URL of the page that linked to the current request. Servers use it for analytics, logging, and security checks. Note the historical misspelling.

Why is Referer spelled wrong?

The misspelling "Referer" was in the original HTTP specification and kept for compatibility. The correct spelling "Referrer" is used in newer headers like Referrer-Policy.

When is Referer not sent?

Referer is not sent when navigating from HTTPS to HTTP, when Referrer-Policy restricts it, from bookmarks or typed URLs, or when rel=noreferrer is used on links.

Is Referer reliable for security?

No, Referer can be spoofed by non-browser clients and may be stripped by privacy settings. Use it for analytics but not as a sole security measure.

Keep Learning