← Back to Blog

HTTP Headers Explained: Complete Developer Reference

HTTP headers are the invisible control plane of the web. They negotiate content types, authenticate requests, enforce security policies, control caching, enable CORS, and carry metadata that shapes every interaction between browsers and servers. This is the reference every web developer should bookmark.

What Are HTTP Headers?

HTTP headers are key-value pairs sent at the beginning of every HTTP request and response, before the body. They are separated from the body by a blank line and look like:

GET /api/users/42 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Accept: application/json
Accept-Encoding: gzip, br
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)

Headers are case-insensitive in HTTP/1.1 (though convention is to use title-case like Content-Type). In HTTP/2 and HTTP/3, headers are sent in HPACK/QPACK compressed binary format, but they still represent the same key-value semantics.

Essential Request Headers

Host

Required in every HTTP/1.1 request. Specifies the domain name and optional port of the server. Critical for virtual hosting (one IP serving multiple domains).

Host: api.example.com
Host: api.example.com:8080

Authorization

Carries credentials for authenticating the request. The most common schemes:

# Bearer token (JWT, OAuth 2.0)
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

# Basic authentication (base64 of username:password - ONLY over HTTPS)
Authorization: Basic dXNlcjpwYXNzd29yZA==

# API key (less common, often custom)
Authorization: ApiKey sk_live_abc123...

Content-Type

Describes the format of the request body. Required for POST and PUT requests with a body.

Content-Type: application/json
Content-Type: application/x-www-form-urlencoded
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Type: text/plain; charset=UTF-8

Accept

Tells the server what content types the client can handle. The server should respond with one of these types (content negotiation).

Accept: application/json
Accept: text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8
# q= values are quality factors (preference weights, 0-1)

Accept-Encoding

Lists compression algorithms the client supports. Modern browsers send br (brotli) and gzip. Servers that compress responses can reduce payload size by 60-80%.

Accept-Encoding: gzip, deflate, br, zstd

Cookie

Sends previously stored cookies to the server. Cookies are set by Set-Cookie response headers and automatically included by the browser on subsequent requests to the same domain.

Cookie: session_id=abc123; preferences=dark_mode; _ga=GA1.1.123456789

User-Agent

Identifies the client software making the request. Used for analytics, bot detection, and serving device-appropriate content. Can be spoofed, so never use it for security decisions.

User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36

Origin and Referer

Origin is sent on cross origin requests (including CORS preflight). It contains just the scheme+host+port with no path. Referer (note: misspelled in the HTTP spec) contains the full URL of the page that made the request.

Origin: https://app.example.com
Referer: https://app.example.com/dashboard

Essential Response Headers

Content-Type

Tells the browser what type of content is in the response body. If missing or wrong, the browser may misinterpret the content - a significant security risk (MIME sniffing attacks).

Content-Type: application/json; charset=utf-8
Content-Type: text/html; charset=utf-8
Content-Type: image/webp

Set-Cookie

Creates a cookie in the browser. The attributes that matter most for security:

Set-Cookie: session_id=abc123; HttpOnly; Secure; SameSite=Lax; Path=/; Max-Age=3600

# HttpOnly - JavaScript cannot access this cookie (blocks XSS cookie theft)
# Secure   - Cookie only sent over HTTPS
# SameSite=Lax - Cookie sent on same-site navigations but not cross-site requests
# SameSite=Strict - Only sent on same-site requests (most restrictive)
# Max-Age  - Lifetime in seconds (preferred over Expires)
# Domain   - If set, includes subdomains; omit for host-only restriction

Location

Used in 3xx redirects to specify where the browser should go next. Also returned in 201 Created responses to indicate the URL of the newly created resource.

HTTP/1.1 301 Moved Permanently
Location: https://www.example.com/new-path

HTTP/1.1 201 Created
Location: https://api.example.com/users/42

Security Response Headers

Security headers are the fastest way to close entire classes of web vulnerabilities. They should be sent on every response from your application.

# Force HTTPS for 1 year, include subdomains, allow browser preload list
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload

# Restrict what resources can load - prevents XSS, data injection
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-abc123'; img-src 'self' https:

# Block MIME type sniffing
X-Content-Type-Options: nosniff

# Prevent clickjacking by disallowing iframe embedding
X-Frame-Options: DENY

# Control Referer header sent on navigation
Referrer-Policy: strict-origin-when-cross-origin

# Restrict browser features your site doesn't use
Permissions-Policy: camera=(), microphone=(), geolocation=()

# Enable browser XSS filter (legacy; CSP is the modern replacement)
X-XSS-Protection: 1; mode=block

Content-Security-Policy in depth

CSP is the most powerful security header and the most complex. It whitelists which sources can provide scripts, styles, images, fonts, and other resources. A violation causes the browser to block the resource and optionally send a report to your report-uri.

# Production CSP example for a React SPA with a CDN
Content-Security-Policy:
  default-src 'self';
  script-src 'self' https://cdn.example.com;
  style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;
  font-src 'self' https://fonts.gstatic.com;
  img-src 'self' data: https:;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  report-uri https://csp.example.com/report

Look Up HTTP Status Codes Instantly

Comprehensive reference for every HTTP status code: 1xx informational, 2xx success, 3xx redirect, 4xx client error, and 5xx server error.

Open HTTP Status Codes →

Caching Headers

# Cache forever (use content-hashed filenames)
Cache-Control: public, max-age=31536000, immutable

# Revalidate every time
Cache-Control: no-cache
ETag: "abc123def"

# Never cache (sensitive data)
Cache-Control: private, no-store

# CDN caches for 1 hour, browser for 0 seconds (s-maxage overrides for CDNs)
Cache-Control: public, s-maxage=3600, max-age=0, stale-while-revalidate=86400

# Last-Modified for conditional requests (alternative to ETag)
Last-Modified: Thu, 26 Mar 2026 12:00:00 GMT

CORS Headers

Cross-Origin Resource Sharing (CORS) allows servers to explicitly permit cross origin requests from browsers. Without CORS headers, browsers block cross origin responses by default (the Same-Origin Policy).

# Allow all origins (public API, read-only)
Access-Control-Allow-Origin: *

# Allow a specific origin (when credentials are involved)
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Credentials: true

# Preflight response (OPTIONS request)
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-Request-ID
Access-Control-Max-Age: 86400  # Cache preflight result for 24 hours

You cannot use Access-Control-Allow-Origin: * together with Access-Control-Allow-Credentials: true. When credentials (cookies, auth headers) are involved, you must specify the exact origin, not a wildcard.

Step-by-Step: Setting Security Headers in Popular Servers

Nginx

server {
    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-Frame-Options "DENY" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Content-Security-Policy "default-src 'self'" always;
    add_header Permissions-Policy "camera=(), microphone=()" always;
}

Apache

<IfModule mod_headers.c>
    Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
    Header always set X-Content-Type-Options "nosniff"
    Header always set X-Frame-Options "DENY"
    Header always set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>

Express.js (Node.js)

// Install: npm install helmet
const helmet = require('helmet');
app.use(helmet()); // Sets all security headers with sensible defaults

// Or manually:
app.use((req, res, next) => {
  res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
  res.setHeader('X-Content-Type-Options', 'nosniff');
  res.setHeader('X-Frame-Options', 'DENY');
  res.setHeader('Referrer-Policy', 'strict-origin-when-cross-origin');
  next();
});

Frequently Asked Questions

What is the difference between Origin and Referer headers?

Origin contains only the scheme, host, and port: https://app.example.com. It never includes the path. It is sent on cross origin requests, CORS preflight requests, and form submissions. Referer contains the full URL of the page that initiated the request, including the path and query string: https://app.example.com/dashboard?tab=settings. It is sent on same origin and cross origin navigations. The Referer header can leak sensitive information in query parameters, which is why the Referrer-Policy header exists to control it.

Why does HSTS matter and what is preloading?

Strict-Transport-Security (HSTS) tells browsers to only access your site over HTTPS for the specified duration. Without it, the very first HTTP request to your site (before the redirect to HTTPS) is vulnerable to man in the middle attacks. HSTS preloading goes further: browsers ship with a hardcoded list of domains that must always use HTTPS, even for the first request ever. To be included in the preload list, your site must have HSTS with max-age of at least 31536000 (1 year), includeSubDomains, and preload, then submit to hstspreload.org. This is a one-way commitment - removal takes months to propagate.

Can I use multiple Set-Cookie headers in one response?

Yes. Unlike most headers where the server should send only one instance, Set-Cookie can appear multiple times in a single response - once per cookie you want to set. Do not try to combine multiple cookies in one Set-Cookie header; each cookie must be its own header line. Most web frameworks handle this transparently when you call their cookie-setting API.

What happens if Content-Type is missing from a response?

Browsers will MIME-sniff the response body to guess the content type. This is a security vulnerability: an attacker who can control response content could cause a browser to execute JavaScript by uploading a file that looks like a script. The X-Content-Type-Options: nosniff header disables MIME sniffing, forcing the browser to respect the declared Content-Type. Always set Content-Type explicitly and add X-Content-Type-Options: nosniff to every response.

What is the Forwarded header vs X-Forwarded-For?

X-Forwarded-For is a de facto standard header added by proxies and load balancers to carry the original client IP address. Format: X-Forwarded-For: client_ip, proxy1_ip, proxy2_ip. The Forwarded header is the RFC 7239 standardized replacement with a more structured format: Forwarded: for=192.168.1.1; proto=https; by=10.0.0.1. Both can be spoofed by clients, so never trust them directly for security decisions unless you control the entire proxy chain and strip them at your trusted load balancer.

The Bottom Line

HTTP headers are not optional boilerplate - they are the control plane of web security, performance, and compatibility. Setting the right security headers closes entire categories of vulnerabilities: HSTS prevents downgrade attacks, CSP prevents XSS, X-Frame-Options prevents clickjacking, and X-Content-Type-Options prevents MIME sniffing. Caching headers control your page load performance. CORS headers enable safe cross origin communication. Invest the time to audit and configure your headers correctly; the security return is enormous relative to the effort.

Use our free tool here → HTTP Status Codes Reference to look up every HTTP status code alongside the headers that typically accompany each response class.

UK
Written by Usman Khan
DevOps Engineer | MSc Cybersecurity | CEH | AWS Solutions Architect

Usman has 10+ years of experience securing enterprise infrastructure, managing high-traffic servers, and building zero-knowledge security tools. Read more about the author.