Last updated
Security Response Headers
The HTTP Header Generator creates properly formatted security headers. Here is a complete set of security headers for a production web application:
# Complete security header set
# Prevent XSS attacks by restricting resource sources
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'
# Enforce HTTPS for 1 year, include subdomains
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
# Prevent clickjacking
X-Frame-Options: DENY
# Prevent MIME type sniffing
X-Content-Type-Options: nosniff
# Control referrer information
Referrer-Policy: strict-origin-when-cross-origin
# Restrict browser features
Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()
Cache Control Headers
Cache headers control how browsers and CDNs cache responses. Different resources need different caching strategies:
# Static assets (images, fonts, JS, CSS) — aggressive caching
Cache-Control: public, max-age=31536000, immutable
# 1 year cache, immutable tells browser not to revalidate
# HTML pages — short cache with revalidation
Cache-Control: public, max-age=3600, must-revalidate
# 1 hour cache, must revalidate when stale
# API responses — no caching
Cache-Control: no-store
# Never cache sensitive API data
# Dynamic pages — cache but revalidate
Cache-Control: public, max-age=0, must-revalidate
ETag: "abc123def456"
Last-Modified: Mon, 15 Jan 2024 10:30:00 GMT
# CDN-specific: cache at CDN but not browser
Cache-Control: public, s-maxage=86400, max-age=0
# CDN caches for 24 hours, browser always revalidates
# Vary header — cache different versions per Accept-Encoding
Vary: Accept-Encoding, Accept-Language
CORS Headers for APIs
Cross-Origin Resource Sharing headers control which origins can access your API:
# Public API — allow all origins (read-only data)
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, HEAD, OPTIONS
Access-Control-Allow-Headers: Content-Type, Accept
Access-Control-Max-Age: 86400
# Restricted API — specific origin only
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization, X-API-Key
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 3600
# Preflight response (OPTIONS request)
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://app.example.com
Access-Control-Allow-Methods: POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400
Content-Length: 0
Authentication Headers
Different authentication schemes use different header formats:
# Basic authentication (base64 encoded username:password)
Authorization: Basic dXNlcm5hbWU6cGFzc3dvcmQ=
# Bearer token (JWT or OAuth 2.0)
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U
# API key in header
X-API-Key: sk_live_abcdefghijklmnopqrstuvwxyz123456
# API key as query parameter (less secure)
GET /api/data?api_key=sk_live_abcdefghijklmnopqrstuvwxyz123456
# WWW-Authenticate (server challenge)
WWW-Authenticate: Bearer realm="api", error="invalid_token", error_description="Token expired"
# Digest authentication
Authorization: Digest username="admin", realm="example.com", nonce="abc123", uri="/api/data", response="def456"
Content Negotiation Headers
Content negotiation headers allow clients and servers to agree on format and encoding:
# Client request headers
Accept: application/json, text/html;q=0.9, */*;q=0.8
Accept-Language: en-US,en;q=0.9,fr;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Charset: utf-8, iso-8859-1;q=0.5
# Server response headers
Content-Type: application/json; charset=utf-8
Content-Language: en-US
Content-Encoding: gzip
Content-Length: 1234
# Common Content-Type values
Content-Type: text/html; charset=utf-8
Content-Type: application/json
Content-Type: application/xml
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Type: application/x-www-form-urlencoded
Content-Type: text/plain; charset=utf-8
Content-Type: image/jpeg
Content-Type: application/octet-stream
Server Configuration Examples
Implementing security headers in Apache and Nginx:
# Apache .htaccess
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options "DENY"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Content-Security-Policy "default-src 'self'"
Header always set Permissions-Policy "camera=(), microphone=()"
</IfModule>
# Nginx configuration
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'" always;
# Express.js (Node.js) using helmet
const helmet = require('helmet');
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
}
},
hsts: { maxAge: 31536000, includeSubDomains: true, preload: true }
}));