Set-Cookie header example
Complete guide to implementing secure cookie headers with proper security attributes for protecting user sessions and data.
What is Set-Cookie?
The Set-Cookie header is used to send cookies from the server to the browser. Proper cookie configuration is critical for security and privacy.
Basic Syntax
Set-Cookie: name=value; attribute1; attribute2
Security Attributes
Secure
Only send cookie over HTTPS.
Set-Cookie: sessionid=abc123; Secure
HttpOnly
Prevent JavaScript access (XSS protection).
Set-Cookie: sessionid=abc123; HttpOnly
SameSite
Control cross-site cookie sending.
Set-Cookie: sessionid=abc123; SameSite=Strict
SameSite Options:
Strict- Never send in cross-site requestsLax- Send on top-level navigation (default)None- Always send (requiresSecure)
Path
Limit cookie to specific URL path.
Set-Cookie: sessionid=abc123; Path=/app
Domain
Specify which domains can receive the cookie.
Set-Cookie: sessionid=abc123; Domain=.example.com
Max-Age / Expires
Set cookie expiration.
Set-Cookie: sessionid=abc123; Max-Age=3600
Set-Cookie: token=xyz; Expires=Wed, 21 Oct 2025 07:28:00 GMT
Secure Session Cookie (Best Practice)
Set-Cookie: __Secure-SessionID=abc123; Path=/; Secure; HttpOnly; SameSite=Strict; Max-Age=86400
Explanation:
__Secure-prefix enforcesSecureattributePath=/applies to entire siteSecure- HTTPS onlyHttpOnly- No JavaScript accessSameSite=Strict- No cross-site sendingMax-Age=86400- Expires in 24 hours
Cookie Prefixes
__Secure- Prefix
Requires Secure attribute:
Set-Cookie: __Secure-Token=value; Secure; Path=/
__Host- Prefix
Most restrictive (requires Secure, Path=/, no Domain):
Set-Cookie: __Host-SessionID=value; Secure; HttpOnly; Path=/; SameSite=Strict
Real-World Examples
Authentication Cookie
Header always set Set-Cookie "__Secure-SessionID=abc123; Path=/; Secure; HttpOnly; SameSite=Strict; Max-Age=3600"
Remember Me Cookie (30 days)
Set-Cookie: __Secure-RememberToken=xyz789; Path=/; Secure; HttpOnly; SameSite=Lax; Max-Age=2592000
Shopping Cart (1 week, accessible by JS)
Set-Cookie: CartID=cart456; Path=/; Secure; SameSite=Lax; Max-Age=604800
Tracking Cookie (1 year)
Set-Cookie: _ga=GA1.2.123456789; Path=/; Secure; SameSite=None; Max-Age=31536000
CSRF Token
Set-Cookie: __Host-CSRF-Token=token123; Path=/; Secure; SameSite=Strict; Max-Age=3600
Implementation
Apache (.htaccess)
<IfModule mod_headers.c>
Header always set Set-Cookie "__Secure-SessionID=example; Path=/; Secure; HttpOnly; SameSite=Strict; Max-Age=3600"
</IfModule>
PHP
<?php
setcookie(
'__Secure-SessionID',
session_id(),
[
'expires' => time() + 3600,
'path' => '/',
'domain' => '',
'secure' => true,
'httponly' => true,
'samesite' => 'Strict'
]
);
?>
Node.js (Express)
res.cookie('__Secure-SessionID', 'value', {
maxAge: 3600000,
secure: true,
httpOnly: true,
sameSite: 'strict',
path: '/'
});
Python (Flask)
response.set_cookie(
'__Secure-SessionID',
value='abc123',
max_age=3600,
secure=True,
httponly=True,
samesite='Strict',
path='/'
)
Nginx
add_header Set-Cookie "__Secure-SessionID=abc123; Path=/; Secure; HttpOnly; SameSite=Strict; Max-Age=3600" always;
SameSite Explained
Strict
Never sent on cross-site requests:
Set-Cookie: sessionid=abc; SameSite=Strict
Use for: Session cookies, authentication
Behavior:
- ✅ User clicks link on your site
- ❌ User clicks link from external site
- ❌ Embedded in iframe
Lax (Default)
Sent on top-level navigation:
Set-Cookie: cart=xyz; SameSite=Lax
Use for: Shopping carts, preferences
Behavior:
- ✅ User clicks link from external site
- ✅ User navigates within your site
- ❌ AJAX requests from other sites
- ❌ Images/iframes on other sites
None
Always sent (requires Secure):
Set-Cookie: tracking=123; SameSite=None; Secure
Use for: Cross-site widgets, OAuth, payment gateways
Behavior:
- ✅ All cross-site requests
- ⚠️ Must use HTTPS (Secure attribute required)
Security Best Practices
1. Always Use Secure and HttpOnly for Sensitive Cookies
Set-Cookie: sessionid=value; Secure; HttpOnly; SameSite=Strict
2. Use Secure- orHost- Prefixes
Set-Cookie: __Host-UserID=123; Secure; HttpOnly; Path=/; SameSite=Strict
3. Set Appropriate Expiration
# Session cookie (no Max-Age/Expires)
Set-Cookie: temp=value; Secure; HttpOnly
# Persistent cookie
Set-Cookie: pref=value; Secure; Max-Age=2592000
4. Minimize Cookie Scope
# Limit to specific path
Set-Cookie: admin=value; Path=/admin; Secure; HttpOnly
# Don't use Domain unless necessary
Set-Cookie: data=value; Secure; HttpOnly
5. Clear Cookies on Logout
<?php
// Delete cookie by setting expiration in past
setcookie('SessionID', '', time() - 3600, '/');
?>
Common Patterns
Session Management
Set-Cookie: __Host-SessionID=abc123; Path=/; Secure; HttpOnly; SameSite=Strict; Max-Age=1800
Multi-Factor Authentication
Set-Cookie: __Secure-MFA-Token=xyz; Path=/; Secure; HttpOnly; SameSite=Strict; Max-Age=300
Language Preference
Set-Cookie: language=en; Path=/; Secure; SameSite=Lax; Max-Age=31536000
Dark Mode Preference
Set-Cookie: theme=dark; Path=/; Secure; SameSite=Lax; Max-Age=31536000
GDPR Compliance
Essential Cookies (No Consent Required)
Set-Cookie: __Host-SessionID=value; Secure; HttpOnly; SameSite=Strict
Analytics/Marketing (Requires Consent)
<!-- Only set after user accepts cookies -->
Set-Cookie: _ga=value; Secure; SameSite=None; Max-Age=31536000
Cookie Flags Comparison
| Flag | Purpose | Recommendation |
|---|---|---|
Secure |
HTTPS only | ✅ Always use in production |
HttpOnly |
No JavaScript access | ✅ Use for session cookies |
SameSite=Strict |
No cross-site sending | ✅ Use for authentication |
SameSite=Lax |
Limited cross-site | ✅ Use for general cookies |
SameSite=None |
Always send | ⚠️ Only when necessary |
__Secure- prefix |
Enforce Secure | ✅ Recommended |
__Host- prefix |
Maximum security | ✅ Best for sensitive data |
Testing Cookies
View in Browser DevTools
- Open DevTools (F12)
- Go to Application tab
- Click Cookies in left sidebar
- Inspect cookie attributes
Check Security Attributes
// In browser console
document.cookie // Only shows non-HttpOnly cookies
Test SameSite Behavior
<!-- Test cross-site request -->
<img src="https://yoursite.com/api/test">
Troubleshooting
Cookie Not Being Set
- Check HTTPS for
Securecookies - Verify path matches current URL
- Check domain attribute
- Ensure no conflicting cookies
Cookie Not Sent with Request
- Check SameSite attribute
- Verify cookie hasn't expired
- Check path/domain restrictions
- Ensure Secure flag matches protocol
Third-Party Cookies Blocked
Modern browsers block third-party cookies by default. Use:
Set-Cookie: name=value; SameSite=None; Secure; Partitioned
Additional Resources
- MDN Set-Cookie Documentation
- OWASP Cookie Security
- Test your cookies: SecurityHeaders.com
Related Headers
- Cookie - Client sends cookies to server
- Set-Cookie2 - Deprecated, don't use
- Clear-Site-Data - Clear cookies and storage