HTTP

Header

Set-Cookie

Learn how the Set-Cookie header instructs browsers to store cookies with attributes like HttpOnly, Secure, SameSite, and expiration settings.

4 min read intermediate Try in Playground

TL;DR: Creates or updates cookies in the browser with specified attributes. Use HttpOnly, Secure, and SameSite for security, especially for session cookies.

Set-Cookie tells the browser to store a small piece of data (a cookie) that will be sent back with future requests to the same domain. It’s like giving someone a membership card - they show it every time they visit to prove who they are or maintain their preferences.

Cookies are essential for user sessions, preferences, shopping carts, and tracking.

How It Works

1. Server sends cookie in response:

HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure
Content-Type: text/html

<html>Welcome back!</html>
```text

**2. Browser stores the cookie.**

**3. Browser sends cookie with future requests:**

```http
GET /dashboard HTTP/1.1
Host: example.com
Cookie: sessionId=abc123

4. Server recognizes the user and provides personalized content.

Basic Syntax

Set-Cookie: name=value; attribute1; attribute2=value2
```text

### Simple Cookie

```http
Set-Cookie: username=john
Set-Cookie: sessionId=abc123; Path=/; Domain=example.com; Secure; HttpOnly; SameSite=Strict
```text

## Cookie Attributes

### Path

Restricts cookie to specific URL paths:

```http
Set-Cookie: adminToken=xyz789; Path=/admin

Cookie only sent for /admin/* URLs.

Domain

Restricts cookie to specific domain/subdomains:

Set-Cookie: userId=123; Domain=example.com
```text

Cookie sent to `example.com` and `*.example.com`.

### Expires

Sets absolute expiration date:

```http
Set-Cookie: rememberMe=true; Expires=Wed, 15 Jan 2026 12:00:00 GMT

Max-Age

Sets relative expiration in seconds:

Set-Cookie: sessionId=abc123; Max-Age=3600
```text

Cookie expires in 1 hour.

### Secure

Only send over HTTPS:

```http
Set-Cookie: sensitiveData=secret; Secure

HttpOnly

Prevent JavaScript access:

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

Protects against XSS attacks.

### SameSite

Controls cross-site request behavior:

```http
Set-Cookie: csrfToken=xyz; SameSite=Strict

Real-World Examples

User Session

Set-Cookie: sessionId=a1b2c3d4e5f6; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=86400
```text

Secure session cookie that expires in 24 hours.

### User Preferences

```http
Set-Cookie: theme=dark; Path=/; Max-Age=31536000; SameSite=Lax

Theme preference stored for 1 year.

Shopping Cart

Set-Cookie: cartId=cart_789; Path=/; Max-Age=604800; SameSite=Lax
```text

Shopping cart ID stored for 1 week.

### Remember Me

```http
Set-Cookie: rememberToken=longRandomString; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=2592000

Long-term authentication token for 30 days.

CSRF Protection

Set-Cookie: csrfToken=randomToken123; Path=/; SameSite=Strict; Secure
```text

CSRF token that's only sent with same-site requests.

## Multiple Cookies

Send multiple cookies with separate headers:

```http
HTTP/1.1 200 OK
Set-Cookie: sessionId=abc123; HttpOnly; Secure
Set-Cookie: theme=dark; Max-Age=31536000
Set-Cookie: language=en; Path=/; Max-Age=31536000
Content-Type: text/html

Secure Cookies

Always use Secure for sensitive data:

✅ Set-Cookie: sessionId=abc123; Secure; HttpOnly
❌ Set-Cookie: sessionId=abc123
```text

### HttpOnly Protection

Prevent XSS cookie theft:

```http
✅ Set-Cookie: sessionId=abc123; HttpOnly
❌ Set-Cookie: sessionId=abc123  (accessible via JavaScript)

SameSite Protection

Prevent CSRF attacks:

Set-Cookie: sessionId=abc123; SameSite=Strict  # Strictest
Set-Cookie: sessionId=abc123; SameSite=Lax     # Balanced
Set-Cookie: sessionId=abc123; SameSite=None; Secure  # Cross-site (requires Secure)
```text

## Cookie Expiration

### Session Cookies

No expiration - deleted when browser closes:

```http
Set-Cookie: tempData=value

Persistent Cookies

With expiration date:

Set-Cookie: userData=value; Max-Age=86400
```text

### Delete Cookies

Set expiration in the past:

```http
Set-Cookie: oldCookie=; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/

Server Implementation

Express.js

app.get('/login', (req, res) => {
  // Set secure session cookie
  res.cookie('sessionId', 'abc123', {
    httpOnly: true,
    secure: true,
    sameSite: 'strict',
    maxAge: 24 * 60 * 60 * 1000 // 24 hours
  })

  res.json({ message: 'Logged in successfully' })
})

// Delete cookie
app.post('/logout', (req, res) => {
  res.clearCookie('sessionId', {
    httpOnly: true,
    secure: true,
    sameSite: 'strict'
  })

  res.json({ message: 'Logged out' })
})
```javascript

### Python Flask

```python
from flask import make_response

@app.route('/login')
def login():
    response = make_response('Logged in')
    response.set_cookie(
        'sessionId',
        'abc123',
        max_age=86400,
        secure=True,
        httponly=True,
        samesite='Strict'
    )
    return response

Best Practices

1. Always use Secure for sensitive cookies:

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

**2. Use HttpOnly for session cookies:**

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

3. Set appropriate SameSite:

Set-Cookie: sessionId=abc123; SameSite=Strict  # For auth
Set-Cookie: preferences=theme; SameSite=Lax    # For UX
```text

**4. Use reasonable expiration times:**

```text
Session cookies: No expiration (browser session)
Auth tokens: 1-24 hours
Preferences: 30 days to 1 year
Remember me: 30 days maximum
```text

**5. Minimize cookie size:**

```text
Keep cookies under 4KB total per domain
Store large data server-side, use cookie as key
```text

**6. Use descriptive names:**

```http
✅ Set-Cookie: userSessionId=abc123
❌ Set-Cookie: s=abc123

Common Issues

Problem: Cookie not being sent Solution: Check Path, Domain, Secure, and SameSite attributes

Problem: Cookie accessible via JavaScript Solution: Add HttpOnly attribute

Problem: Cookie sent over HTTP Solution: Add Secure attribute and use HTTPS

Problem: CSRF attacks Solution: Use SameSite=Strict or SameSite=Lax

  • Cookie - Request header that sends stored cookies
  • Cache-Control - Affects cookie caching
  • Vary - Cache different responses based on cookies

In Practice

Express.js
// Session cookie (deleted when browser closes)
res.cookie('sessionId', token, {
  httpOnly: true,
  secure: true,
  sameSite: 'lax',
  path: '/'
})

// Persistent cookie (30 days)
res.cookie('rememberMe', userId, {
  httpOnly: true,
  secure: true,
  sameSite: 'strict',
  maxAge: 30 * 24 * 60 * 60 * 1000 // ms
})

// Clear a cookie
res.clearCookie('sessionId', { path: '/' })
Next.js App Router
import { cookies } from 'next/headers'

// Server Action or Route Handler
export async function POST(request: Request) {
  const cookieStore = await cookies()

  // Set session cookie
  cookieStore.set('sessionId', token, {
    httpOnly: true,
    secure: true,
    sameSite: 'lax',
    path: '/'
  })

  // Or via Response headers
  return new Response(null, {
    status: 200,
    headers: {
      'Set-Cookie': 'sessionId=abc123; Path=/; HttpOnly; Secure; SameSite=Lax'
    }
  })
}
Django
from django.http import JsonResponse

def login_view(request):
    response = JsonResponse({'status': 'ok'})

    # Session cookie
    response.set_cookie(
        'sessionId',
        value=token,
        httponly=True,
        secure=True,
        samesite='Lax',
        path='/'
    )

    # Persistent cookie (30 days)
    response.set_cookie(
        'rememberMe',
        value=user_id,
        max_age=30 * 24 * 60 * 60,
        httponly=True,
        secure=True,
        samesite='Strict'
    )
    return response

Frequently Asked Questions

What is Set-Cookie?

Set-Cookie is a response header that creates or updates cookies in the browser. It specifies the cookie name, value, and attributes like expiration, domain, and security settings.

What cookie attributes should I use for security?

Use HttpOnly to prevent JavaScript access, Secure to require HTTPS, SameSite=Strict or Lax to prevent CSRF. For session cookies, combine all three.

How do I set a cookie expiration?

Use Max-Age (seconds) or Expires (date). Max-Age=3600 expires in 1 hour. Without either, the cookie is a session cookie deleted when the browser closes.

Can I set multiple cookies in one response?

Yes, use multiple Set-Cookie headers. Each header sets one cookie. You cannot combine multiple cookies in a single Set-Cookie header.

Keep Learning