HTTP

Header

Cookie Header

Learn how the Cookie header sends stored cookies to servers with each request. Understand cookie transmission, session management, and security considerations.

4 min read beginner Try in Playground

TL;DR: Sends stored cookies from browser to server for session management and user tracking. Contains name=value pairs separated by semicolons for state persistence.

The Cookie header sends previously stored cookies back to the server. It’s like showing your membership card or loyalty points when you visit a store—the server recognizes you and remembers your preferences.

Cookies enable stateful interactions in the stateless HTTP protocol, allowing servers to remember users across requests.

How Cookies Work

1. Server sets cookies:

HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; HttpOnly; Secure
Set-Cookie: theme=dark; Max-Age=86400
```text

**2. Browser stores and sends them back:**

```http
GET /dashboard HTTP/1.1
Host: example.com
Cookie: sessionId=abc123; theme=dark
Cookie: name=value
```text

### Multiple Cookies

```http
Cookie: sessionId=abc123; userId=42; theme=dark; lang=en

With Special Characters

Cookie: message=Hello%20World; data=%7B%22key%22%3A%22value%22%7D
```text

## Common Use Cases

### Session Management

```http
Cookie: JSESSIONID=A1B2C3D4E5F6; PHPSESSID=xyz789

Maintains user login state across requests.

User Preferences

Cookie: theme=dark; language=en-US; timezone=America/New_York
```text

Remembers user settings and customizations.

### Shopping Cart

```http
Cookie: cart=item1,item2,item3; cartTotal=49.99

Tracks items before user logs in.

Analytics and Tracking

Cookie: _ga=GA1.2.123456789; _gid=GA1.2.987654321
```text

Google Analytics tracking cookies.

## Real-World Examples

### E-commerce Site

```http
GET /products HTTP/1.1
Host: shop.example.com
Cookie: sessionId=user123; cart=prod1,prod2; currency=USD; lastVisit=2026-01-17

Social Media Platform

GET /feed HTTP/1.1
Host: social.example.com
Cookie: authToken=jwt123; userId=42; notifications=enabled; darkMode=true
```text

### Banking Application

```http
GET /account HTTP/1.1
Host: bank.example.com
Cookie: secureSession=encrypted123; csrfToken=abc456; lastActivity=1642518000

HttpOnly

Set-Cookie: sessionId=abc123; HttpOnly
```text

Prevents JavaScript access (XSS protection).

### Secure

```http
Set-Cookie: authToken=xyz789; Secure

Only sent over HTTPS connections.

SameSite

Set-Cookie: csrf=token123; SameSite=Strict
```text

Controls cross-site request behavior.

### Expiration

```http
Set-Cookie: remember=true; Max-Age=2592000
Set-Cookie: temp=data; Expires=Wed, 18 Jan 2026 12:00:00 GMT

Security Considerations

Sensitive Data Protection

// ❌ Don't store sensitive data in cookies
document.cookie = 'password=secret123'
document.cookie = 'creditCard=1234567890123456'

// ✅ Store session identifiers only
document.cookie = 'sessionId=abc123; Secure; HttpOnly'
```text

### CSRF Protection

```http
Cookie: csrfToken=random123; sessionId=user456

Include CSRF tokens to prevent cross-site attacks.

Size Limitations

// Cookies are limited to ~4KB per cookie
// Total limit: ~4KB per domain
const largeCookie = 'data=' + 'x'.repeat(4000) // Might be rejected
```text

## Browser Behavior

### Automatic Sending

Browsers automatically include relevant cookies:

```http
GET /api/profile HTTP/1.1
Host: example.com
Cookie: sessionId=abc123; theme=dark
# Browser adds these automatically

Domain and Path Matching

# Cookie set for .example.com applies to:
# - example.com
# - www.example.com
# - api.example.com

# Cookie set for /admin applies to:
# - /admin
# - /admin/users
# - /admin/settings
```text

### Cookie Jar Management

```javascript
// Browsers manage cookie storage automatically
// Cookies persist across browser sessions (unless session-only)
// Expired cookies are automatically removed

Server-Side Handling

Reading Cookies

// Node.js/Express
app.get('/profile', (req, res) => {
  const sessionId = req.cookies.sessionId
  const theme = req.cookies.theme || 'light'

  if (!sessionId) {
    return res.status(401).json({ error: 'Not authenticated' })
  }

  const user = getUserBySession(sessionId)
  res.json({ user, theme })
})
```text

### Setting Cookies

```javascript
// Express.js
res.cookie('sessionId', 'abc123', {
  httpOnly: true,
  secure: true,
  maxAge: 24 * 60 * 60 * 1000 // 24 hours
})
function parseCookies(cookieHeader) {
  const cookies = {}

  if (cookieHeader) {
    cookieHeader.split(';').forEach((cookie) => {
      const [name, value] = cookie.trim().split('=')
      cookies[name] = decodeURIComponent(value)
    })
  }

  return cookies
}
```text

## Best Practices

### Minimize Cookie Size

```javascript
// ❌ Large cookies slow down requests
Cookie: userData = {
  name: 'John',
  email: 'john@example.com',
  preferences: { theme: 'dark', lang: 'en' }
}

// ✅ Store minimal identifiers
Cookie: sessionId = abc123

Use Appropriate Attributes

// For authentication
res.cookie('sessionId', id, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict'
})

// For preferences
res.cookie('theme', 'dark', { maxAge: 30 * 24 * 60 * 60 * 1000 }) // 30 days

// For tracking (if needed)
res.cookie('analytics', id, { secure: true, sameSite: 'lax' })
```javascript

### Handle Missing Cookies

```javascript
app.get('/api/data', (req, res) => {
  const sessionId = req.cookies.sessionId

  if (!sessionId) {
    return res.status(401).json({
      error: 'Authentication required',
      redirectTo: '/login'
    })
  }

  // Continue with authenticated request
})

Testing Cookies

Using curl

# Send cookies manually
curl -H "Cookie: sessionId=abc123; theme=dark" https://example.com/api/profile

# Save cookies from response
curl -c cookies.txt https://example.com/login

# Use saved cookies
curl -b cookies.txt https://example.com/dashboard
```javascript

### Using JavaScript

```javascript
// Read cookies (if not HttpOnly)
const cookies = document.cookie.split(';').reduce((acc, cookie) => {
  const [name, value] = cookie.trim().split('=')
  acc[name] = value
  return acc
}, {})

// Set cookies (client-side)
document.cookie = 'theme=dark; max-age=86400; secure'

Browsers enforce size limits on cookies. The maximum size for a single cookie (name + value + attributes) is approximately 4096 bytes across all major browsers. The total number of cookies per domain is typically limited to 50, and the total size of all cookies for a domain is capped at around 4096 bytes in some browsers. Exceeding these limits causes cookies to be silently dropped, which can cause subtle authentication bugs.

Cookie prefixes are a security mechanism that enforces attribute requirements. A cookie named __Secure-session must have the Secure attribute — browsers reject it otherwise. A cookie named __Host-session must have Secure, must not have a Domain attribute, and must have Path=/. The __Host- prefix is the stronger of the two because it prevents subdomain cookies from overriding it, making it ideal for session cookies on applications that share a domain with other services.

Frequently Asked Questions

What is the Cookie header?

The Cookie header sends stored cookies from the browser to the server. It contains name=value pairs for all cookies that match the request domain and path.

How are multiple cookies sent?

Multiple cookies are sent in one header, separated by semicolons: "Cookie: session=abc; theme=dark; user=123". Each cookie is a name=value pair.

What is the difference between Cookie and Set-Cookie?

Cookie is a request header sent by clients. Set-Cookie is a response header sent by servers to create or update cookies. They work together for state management.

Why are my cookies not being sent?

Check cookie attributes: domain must match, path must match, Secure requires HTTPS, SameSite may block cross-site requests, and HttpOnly cookies are still sent but not accessible to JavaScript.

Keep Learning