# Domain

> Learn how the Domain cookie attribute controls which domains can access cookies. Understand subdomain sharing, security implications, and restrictions.

Source: https://howhttpworks.com/cookies/domain
Last reviewed: 2026-10-04

> **TL;DR:** Controls which domains can access a cookie - set `Domain=example.com` to share cookies across subdomains, or omit it to restrict cookies to the exact domain that set them.

## What is the Domain Attribute?

The **Domain** attribute controls which domains can access a cookie. It determines the scope of cookie availability across your domain hierarchy, enabling subdomain sharing while maintaining security boundaries.

Without the Domain attribute, cookies are restricted to the exact domain that set them. With it, you can share cookies across subdomains or restrict them more precisely.

## How It Works

### Default Behavior (No Domain Attribute)

```http
Set-Cookie: sessionId=abc123
```

Cookie is only available to the exact domain that set it:

- ✅ `example.com` can access
- ❌ `api.example.com` cannot access
- ❌ `subdomain.example.com` cannot access

### With Domain Attribute

```http
Set-Cookie: sessionId=abc123; Domain=example.com
```

Cookie is available to the specified domain and all its subdomains:

- ✅ `example.com` can access
- ✅ `api.example.com` can access
- ✅ `subdomain.example.com` can access
- ❌ `otherdomain.com` cannot access

## Security Implications

### Subdomain Cookie Sharing Risks

When you set `Domain=example.com`, **all subdomains** can access the cookie:

```javascript
// Dangerous: Shares sensitive data with all subdomains
document.cookie = 'authToken=secret123; Domain=example.com'

// Safer: Restrict to specific domain
document.cookie = 'authToken=secret123' // No Domain attribute
```

**Risk**: If any subdomain is compromised, attackers can steal cookies from the parent domain.

### Domain Validation

Browsers enforce strict domain validation:

```http
# ❌ Invalid: Cannot set cookie for unrelated domain
Set-Cookie: data=value; Domain=google.com
# (Set from example.com - browser will reject)

# ❌ Invalid: Cannot set for parent domain you don't control
Set-Cookie: data=value; Domain=.com
# (Browser will reject)

# ✅ Valid: Can set for current domain or its subdomains
Set-Cookie: data=value; Domain=example.com
# (Set from example.com or any subdomain)
```

## Browser Behavior

### Leading Dot Handling

Modern browsers treat these identically:

```http
Set-Cookie: data=value; Domain=example.com
Set-Cookie: data=value; Domain=.example.com
```

Both allow access from `example.com` and all subdomains.

### Public Suffix Protection

Browsers prevent setting cookies for public suffixes:

```http
# ❌ Blocked by browser
Set-Cookie: data=value; Domain=.co.uk
Set-Cookie: data=value; Domain=.github.io
```

This prevents malicious sites from setting cookies that affect unrelated domains.

## Code Examples

### Express.js Cookie Management

```javascript
const express = require('express')
const app = express()

// Restrict to exact domain
app.get('/login', (req, res) => {
  res.cookie('sessionId', 'abc123', {
    // No domain - only available to current domain
    httpOnly: true,
    secure: true
  })
})

// Share across subdomains
app.get('/api-login', (req, res) => {
  res.cookie('apiToken', 'xyz789', {
    domain: 'example.com', // Available to all subdomains
    httpOnly: true,
    secure: true
  })
})
```

### Client-Side Domain Checking

```javascript
// Check current domain before setting cookies
function setCrossDomainCookie(name, value) {
  const currentDomain = window.location.hostname

  if (currentDomain.endsWith('.example.com') || currentDomain === 'example.com') {
    document.cookie = `${name}=${value}; Domain=example.com; Secure; SameSite=Strict`
  } else {
    // Fallback to domain-specific cookie
    document.cookie = `${name}=${value}; Secure; SameSite=Strict`
  }
}
```

### Reading Domain-Scoped Cookies

```javascript
// Function to check cookie availability across domains
function checkCookieScope() {
  const cookies = document.cookie.split(';')

  cookies.forEach((cookie) => {
    const [name, value] = cookie.trim().split('=')
    console.log(`Cookie ${name} available on ${window.location.hostname}`)
  })
}

// Test from different subdomains
checkCookieScope() // Run on api.example.com, app.example.com, etc.
```

## Common Mistakes

### Over-Sharing with Subdomains

```javascript
// ❌ Bad: Exposes sensitive data to all subdomains
document.cookie = 'creditCard=1234; Domain=example.com'

// ✅ Good: Keep sensitive data domain-specific
document.cookie = 'creditCard=1234' // No Domain attribute
```

### Incorrect Domain Format

```javascript
// ❌ Wrong: Including protocol or path
document.cookie = 'data=value; Domain=https://example.com'
document.cookie = 'data=value; Domain=example.com/path'

// ✅ Correct: Domain name only
document.cookie = 'data=value; Domain=example.com'
```

### Assuming Domain Inheritance

```javascript
// ❌ Wrong assumption: Parent domain cookies aren't automatically
// available to subdomains without Domain attribute
// Set on example.com without Domain attribute
document.cookie = 'parentData=value'

// This won't be available on api.example.com
```

## Getting Domain right

1. **Default to No Domain**: Only use Domain attribute when subdomain sharing is necessary
2. **Minimize Scope**: Set Domain to the most specific level needed
3. **Audit Subdomains**: Ensure all subdomains in scope are secure
4. **Separate Sensitive Data**: Use domain-specific cookies for authentication tokens
5. **Monitor Cookie Scope**: Regularly review which cookies are shared across subdomains
