HTTP Headers Every Developer Should Know (2026)
Headers are the hidden conversation between client and server. Understanding them makes you better at debugging, performance, and security.
Request Headers (Client → Server)
GET /api/users HTTP/1.1
Host: example.com
Accept: application/json
Authorization: Bearer eyJhbGci...
Content-Type: application/json
User-Agent: Mozilla/5.0
X-Request-ID: req_abc123
// The headers you'll use most:
// Host — Which domain you're requesting (required in HTTP/1.1)
Host: api.example.com
// Used for virtual hosting (one IP, many domains)
// Accept — What response formats you want
Accept: application/json // Want JSON
Accept: text/html // Want HTML
Accept: */* // Anything is fine
Accept: text/html,application/xhtml+xml;q=0.9,*/*;q=0.8 // With priorities
// Authorization — Credentials
Authorization: Bearer <token> // OAuth2/JWT tokens
Authorization: Basic <base64> // Username:password encoded
Authorization: ApiKey <key> // Custom API key pattern
// Content-Type — What you're sending (for POST/PUT/PATCH)
Content-Type: application/json // JSON payload
Content-Type: application/x-www-form-urlencoded // Form data
Content-Type: multipart/form-data // File uploads
Content-Type: text/plain // Raw text
// User-Agent — Who's making the request
User-Agent: MyClient/1.0 // Identify your client
// Servers use this to: block bots, serve different content, analytics
// Custom headers (X- prefix convention)
X-Request-ID: uuid // Trace requests across services
X-Forwarded-For: 1.2.3.4 // Original client IP (set by proxy)
X-Real-IP: 1.2.3.4 // Original client IP (nginx convention)
X-Correlation-ID: abc123 // Link related requests together
Idempotency-Key: pay_12345 // Prevent duplicate payments
Response Headers (Server → Client)
// Status line + headers:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 1234
Cache-Control: max-age=3600
Date: Sat, 31 May 2026 12:33:00 GMT
ETag: "abc123"
X-RateLimit-Remaining: 95
X-Request-ID: req_abc123
// Content-Type — What you're getting back
Content-Type: application/json; charset=utf-8
Content-Type: text/html; charset=utf-8
Content-Type: image/png
Content-Type: application/octet-stream // Binary download
Content-Type: application/pdf
// ⚠️ Always set charset for text types!
// Content-Length — Size of body in bytes
Content-Length: 12345
// Important for: progress bars, connection keep-alive, detecting truncation
// Content-Encoding — Compression
Content-Encoding: gzip // Body is gzip-compressed
Content-Encoding: br // Brotli compressed (better ratio!)
// Saves 60-80% bandwidth on text responses
// Cache-Control — How long to cache
Cache-Control: no-cache // Revalidate every time
Cache-Control: no-store // Don't cache at all (sensitive data!)
Cache-Control: private // Only browser can cache (not CDNs)
Cache-Control: public // Anyone can cache (CDNs included)
Cache-Control: max-age=3600 // Cache for 1 hour
Cache-Control: max-age=86400, immutable // Cache forever (hashed assets)
Cache-Control: s-maxage=300, must-revalidate // CDN caches 5min, then revalidate
// ETag & If-None-Match — Conditional requests
ETag: "v1-abc123" // Version identifier of resource
// Client sends: If-None-Match: "v1-abc123" on next request
// Server responds: 304 Not Modified if unchanged (saves bandwidth!)
// Location — Redirect target
Location: https://example.com/new-url
// Sent with: 301 (permanent), 302 (temporary), 303 (see other), 307/308
// Set-Cookie — Set cookies on client
Set-Cookie: session_id=abc123; Path=/; HttpOnly; Secure; SameSite=Lax; Max-Age=86400
Set-Cookie: theme=dark; Path=/; Max-Age=31536000
// HttpOnly = JS can't read (prevents XSS token theft)
// Secure = Only sent over HTTPS
// SameSite = CSRF protection (Strict/Lax/None)
// CORS headers (cross-origin requests)
Access-Control-Allow-Origin: * // Or specific origin
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400 // Cache preflight results
Access-Control-Allow-Credentials: true // Allow cookies with cross-origin
Access-Control-Expose-Headers: X-Request-ID, X-RateLimit-Remaining
// Rate limiting headers (send these on EVERY response!)
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 73
X-RateLimit-Reset: 1717184000 // Unix timestamp when limit resets
Retry-After: 60 // On 429 responses
// Security headers
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload // HTTPS only!
X-Content-Type-Options: nosniff // Don't sniff MIME type
X-Frame-Options: DENY // Prevent clickjacking
X-XSS-Protection: 1; mode=block // Basic XSS filter
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'
Referrer-Policy: strict-origin-when-cross-origin // Control referrer header
Permissions-Policy: camera=(), microphone=() # Block camera/mic access
Debugging Headers
// When things go wrong, check these FIRST:
// 1. Is it a caching issue?
// Check response headers:
// Cache-Control: max-age=86400 → Browser won't re-request for 24h!
// Fix: Ctrl+Shift+R (hard reload) or add cache-busting query param
// 2. Is it a CORS issue?
// Browser console shows: "Access-Control-Allow-Origin"
// Check: Does your API return Access-Control-Allow-Origin?
// Check: Is the request preflighted (OPTIONS before actual request)?
// Complex requests (custom headers, non-GET/POST) trigger preflight
// 3. Is it a redirect loop?
// Check: Location header pointing back to itself?
// Check: HTTP vs HTTPS mixed content?
// 4. Is the response actually what you expect?
// Check: Content-Type matches what you're parsing
// Common gotcha: API returns HTML error page when you expect JSON
// 5. Practical debugging with curl:
curl -v https://api.example.com/data
# Shows ALL headers (request and response) — invaluable!
curl -I https://api.example.com/data
# Shows response headers only (HEAD request equivalent)
curl -D - https://api.example.com/data > /dev/null
# Save headers to stdout, discard body
// 6. Browser DevTools Network tab:
// Right-click any request → Copy as cURL
// See exact headers being sent/received
// Filter by: XHR/Fetch (API calls), Doc (page loads), etc.
Performance Headers
// These headers directly impact your app's perceived speed:
// Keep-Alive (connection reuse)
Connection: keep-alive
Keep-Alive: timeout=5, max=100
// Avoids TCP handshake overhead for repeated requests
// Accept-Encoding (compression negotiation)
Accept-Encoding: gzip, deflate, br
// Always include br (brotli) — 15-25% better than gzip
// Your server should compress responses automatically
// Accept-Language
Accept-Language: en-US,en;q=0.9
// Server uses this for i18n content negotiation
// Early Hints (103 status) — send headers before body is ready
HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload, </script.js>; rel=preload
// Browser starts loading resources while server generates HTML!
// Server-Timing (measure backend performance)
Server-Timing: db=45, render=23, total=68
// Visible in Chrome DevTools → Timing → Server Timing
// Format: metric=value or metric="desc";dur=value
Header Security Checklist
Every API response should include:
□ Content-Type (correct, with charset for text)
□ X-Request-ID (for tracing/debugging)
□ X-RateLimit-* headers (if rate limited)
□ Strict-Transport-Security (HTTPS sites)
□ X-Content-Type-Options: nosniff
□ X-Frame-Options (or CSP frame-ancestors)
□ Cache-Control (appropriate for data sensitivity)
□ CORS headers (only for browser clients)
Never expose in headers:
❌ Server version details (Server: nginx/1.24.0 → use generic)
❌ Internal IPs or architecture info
❌ Stack traces or file paths in error responses
❌ API keys, tokens, passwords
❌ Session IDs in URLs (referrer leakage!)
Which header has caused you the most debugging pain?
Follow @armorbreak for more practical developer guides.
Top comments (0)