DEV Community

Alex Chen
Alex Chen

Posted on

HTTP Headers Every Developer Should Know (2026)

HTTP Headers Every Developer Should Know (2026)

Headers are the hidden conversation between your browser and the server. Understanding them makes you a better developer.

The Request-Response Cycle

Browser → [Request Headers] → Server processes → [Response Headers] → Browser renders

Headers are key-value pairs.
They control caching, security, content type, authentication, and more.
Most work automatically — but when things break, headers are usually why.
Enter fullscreen mode Exit fullscreen mode

Request Headers (Client → Server)

Essential Headers

GET /api/users HTTP/1.1
Host: api.example.com          # REQUIRED. Domain of the server
User-Agent: Mozilla/5.0 ...    # Client software info
Accept: application/json       # What response formats I accept
Accept-Language: en-US         # Preferred language
Connection: keep-alive         # Reuse TCP connection
Enter fullscreen mode Exit fullscreen mode

Content Negotiation

# Tell the server what you want back
Accept: application/json        # JSON data
Accept: text/html               # HTML page
Accept: */*                     # Anything (default)
Accept: text/html,application/xhtml+xml;q=0.9,*/*;q=0.8  # With priorities!

# What encoding you accept
Accept-Encoding: gzip, deflate, br   # Compression preference

# What language
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8
Enter fullscreen mode Exit fullscreen mode

Authentication

# Basic Auth (base64 encoded credentials)
Authorization: Basic dXNlcjpwYXNz  # "user:pass" base64-encoded

# Bearer Token (JWT / OAuth2)
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

# API Key (various patterns)
Authorization: ApiKey abc123def456
X-API-Key: abc123def456
Enter fullscreen mode Exit fullscreen mode

Conditional Requests (Caching!)

# "Only give me this if it changed since..."
If-None-Match: "33a64df5514310bf564"  # ETag value from last response
If-Modified-Since: Wed, 21 Oct 2026 07:28:00 GMT  # Last-Modified timestamp

# Server responds:
# → 200 OK + full data (if changed)
# → 304 Not Modified, no body (if NOT changed) ← SAVES BANDWIDTH!
Enter fullscreen mode Exit fullscreen mode

CORS Preflight

# Browser sends this before cross-origin requests:
OPTIONS /api/data HTTP/1.1
Origin: https://myapp.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type, Authorization

# Server must respond with matching permissions:
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://myapp.com
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400           # Cache preflight for 24h
Enter fullscreen mode Exit fullscreen mode

Response Headers (Server → Client)

Status Codes & Basics

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 1234
Date: Tue, 26 May 2026 00:33:00 GMT
Server: nginx/1.24.0              # Hide or customize this in production!
Enter fullscreen mode Exit fullscreen mode

Common status codes you should know:

Code Meaning When to Use
200 OK Successful GET/PUT/PATCH
201 Created Successful POST (include Location header)
204 No Content Successful DELETE
301 Moved Permanently Permanent redirect
304 Not Modified Cached data still valid
400 Bad Request Invalid input
401 Unauthorized Not authenticated
403 Forbidden Authenticated but no permission
404 Not Found Resource doesn't exist
405 Method Not Allowed Wrong HTTP method for this endpoint
409 Conflict Resource state conflict (duplicate)
413 Payload Too Large Body exceeds size limit
415 Unsupported Media Type Wrong Content-Type
422 Unprocessable Entity Valid format but business rule failed
429 Too Many Requests Rate limited
500 Internal Server Error Something broke on server
502 Bad Gateway Upstream server error
503 Service Unavailable Server overloaded/maintenance

Caching Headers (Critical for Performance!)

# Version 1: Expiration-based
Cache-Control: public, max-age=3600      # Cache for 1 hour (CDN + browser)
Cache-Control: private, max-age=300     # Only browser cache (5 min), not CDN
Cache-Control: no-cache                  # Must revalidate with server each time
Cache-control: no-store                  # Never cache (API responses, auth pages)
Cache-Control: immutable, max-age=31536000 # Never revalidate (hashed assets)

# Version 2: Validation tags (used WITH no-cache)
ETag: "33a64df5514310bf564"             # Unique content hash/ID
Last-Modified: Wed, 21 Oct 2026 07:28:00 GMT  # Modification timestamp

# Practical examples:

# Static assets (CSS/JS/images) — AGGRESSIVE caching
Cache-Control: public, max-age=31536000, immutable
# Files with hash in name: main.a1b2c3d4.css → never changes

# HTML pages — SHORT cache, always validate
Cache-Control: public, max-age=0, must-revalidate
ETag: "abc123"

# API responses — NO cache by default
Cache-Control: no-store
# Unless it's a rarely-changing public API:
Cache-Control: public, max-age=60, stale-while-revalidate=300
Enter fullscreen mode Exit fullscreen mode

Security Headers

# Prevent clickjacking
X-Frame-Options: SAMEORIGIN
# Or: DENY (no framing at all)

# Prevent MIME sniffing
X-Content-Type-Options: nosniff

# XSS protection (legacy but still useful)
X-XSS-Protection: 1; mode=block

# Control referrer information
Referrer-Policy: strict-origin-when-cross-origin

# Permissions Policy (replaces Feature-Policy)
Permissions-Policy: camera=(), microphone=(), geolocation=()

# THE BIG ONE: Content Security Policy
Content-Security-Policy: 
  default-src 'self';
  script-src 'self' 'unsafe-inline' cdn.example.com;
  style-src 'self' 'unsafe-inline' fonts.googleapis.com;
  font-src 'self' fonts.gstatic.com;
  img-src 'self' data: https:;
  connect-src 'self' api.example.com wss://ws.example.com;
  frame-ancestors 'self';
  base-uri 'self';
  form-action 'self';

# Strict Transport Security (force HTTPS)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# Tells browser: "For the next year, only use HTTPS, never HTTP"
Enter fullscreen mode Exit fullscreen mode

CORS Response Headers

# For cross-origin API access:
Access-Control-Allow-Origin: https://myapp.com    # Specific origin (best!)
Access-Control-Allow-Origin: *                    # Public API (any origin)
Access-Control-Allow-Credentials: true            # Allow cookies/auth headers
Access-Control-Expose-Headers: X-Request-ID, X-RateLimit-Remaining
Access-Control-Max-Age: 86400                      # Preflight cache duration
Enter fullscreen mode Exit fullscreen mode

Rate Limiting Headers

# Tell clients their rate limit status:
X-RateLimit-Limit: 100            # Max requests per window
X-RateLimit-Remaining: 73         # How many left
X-RateLimit-Reset: 1716675800      # Unix timestamp when window resets
Retry-After: 60                   # Seconds until they can try again (for 429s)
Enter fullscreen mode Exit fullscreen mode

Debugging Header Issues

Using curl to Inspect Headers

# See all response headers
curl -I https://example.com/api/users

# See request AND response headers
curl -v https://example.com/api/users

# Custom headers
curl -H "Authorization: Bearer token123" \
  -H "Accept: application/json" \
  https://example.com/api/me

# Follow redirects and see each hop's headers
curl -vL https://example.com/redirect

# Check caching behavior
curl -I -H "If-None-Match: \"some-etag\"" \
  https://example.com/data
# Should return 304 if ETag matches!
Enter fullscreen mode Exit fullscreen mode

Browser DevTools

F12 → Network tab → Click any request → Headers section

Key areas to check:
1. General → Request URL, Method, Status Code
2. Request Headers → What your browser sent
3. Response Headers → What the server sent back
4. Preview/Parsed → Formatted response body

Pro tip: Right-click column headers → Manage Columns → Enable:
→ "Remote Address" (which server IP?)
→ "Time" (how long did it take?)
→ "Initiator" (what triggered this request?)
Enter fullscreen mode Exit fullscreen mode

Common Header Problems & Fixes

Problem: CORS error on frontend
Fix: Check Access-Control-Allow-Origin on server response
Note: Credentials mode requires specific origin, not *

Problem: Assets not updating after deploy
Fix: Check Cache-Control headers, add cache-busting query param or hash filename

Problem: 400 Bad Request on POST
Fix: Check Content-Type header matches what server expects (application/json)

Problem: Downloads showing as text in browser
Fix: Set Content-Disposition: attachment; filename="file.pdf"

Problem: API works in Postman but not browser
Fix: Usually CORS or missing Content-Type header. Check preflight OPTIONS response.

Problem: Images not loading from CDN
Fix: Check referrer policy or hotlink protection headers
Enter fullscreen mode Exit fullscreen mode

Quick Reference Card

Header Direction Purpose
Host Request Target server/domain
User-Agent Request Client identification
Accept Request Response format preference
Authorization Request Authentication credentials
Content-Type Both Format of request/response body
Content-Length Both Size of body in bytes
Cookie Request Send cookies to server
Set-Cookie Response Set cookies on client
Location Response Redirect URL (with 3xx status)
Cache-Control Both Caching directives
ETag Response Content version identifier
Last-Modified Response Last change timestamp
If-None-Match Request Conditional request (ETag)
If-Modified-Since Request Conditional request (timestamp)
X-Forwarded-For Request Original client IP (via proxy)
X-Request-ID Both Trace request through system

Which header has caused you the most debugging pain?

Follow @armorbreak for more practical web dev guides.

Top comments (0)