What Are HTTP Headers?
HTTP headers are key-value pairs sent between a client (typically a web browser) and a server during HTTP requests and responses. They provide essential metadata about the request or response, including content type, caching instructions, security policies, and server information.
Think of HTTP headers as the envelope and postage information on a letter. While the body of the HTTP message contains the actual content (the letter itself), headers provide crucial context about how to handle that content.
Request vs Response Headers
Request Headers are sent from the client to the server and include information like:
User-Agent- Browser and operating system informationAccept- Content types the client can understandCookie- Authentication and session dataReferer- The URL of the previous page
Response Headers are sent from the server back to the client and include:
Content-Type- The type of content being returnedCache-Control- Caching instructionsSet-Cookie- Cookies to store on the clientSecurity Headers- Various security policies
Why Headers Matter
Properly configured HTTP headers can protect against common web vulnerabilities, improve performance through caching, enhance SEO, and provide a better user experience. Missing or misconfigured headers are among the top security issues found in web application security audits.
Essential Security Headers
Security headers are specialized HTTP response headers that tell browsers how to behave when handling your site's content. They're your first line of defense against many common web attacks.
Content-Security-Policy (CSP)
The Content-Security-Policy header prevents Cross-Site Scripting (XSS) attacks by specifying which sources of content are allowed to load on your page.
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; img-src 'self' data: https:; style-src 'self' 'unsafe-inline';
How it works: CSP creates an allow-list of trusted content sources. Even if an attacker injects malicious code, the browser won't execute it unless it comes from an allowed source.
Common directives:
default-src- Fallback for all resource typesscript-src- Where JavaScript can be loaded fromstyle-src- Where CSS can be loaded fromimg-src- Where images can be loaded fromconnect-src- Where AJAX/WebSocket connections can goframe-ancestors- Who can embed your site in an iframe
CSP Implementation Warning
Implementing CSP on an existing site can break functionality if not done carefully. Start with Content-Security-Policy-Report-Only header to monitor violations without blocking content, then migrate to enforcement once issues are resolved.
Strict-Transport-Security (HSTS)
HSTS forces browsers to only connect to your site over HTTPS, preventing man-in-the-middle attacks and SSL stripping. For complete HTTPS security, also ensure your SSL certificates are properly configured.
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
Key parameters:
max-age- How long (in seconds) to remember to only use HTTPS (31536000 = 1 year)includeSubDomains- Apply to all subdomainspreload- Allow inclusion in browser preload lists
HSTS Preload: Submit your domain to hstspreload.org to be hardcoded into browsers, providing protection on the very first visit.
X-Frame-Options
Protects against clickjacking attacks by controlling whether your site can be embedded in iframes.
X-Frame-Options: DENY
Options:
DENY- Never allow framing (most secure)SAMEORIGIN- Only allow framing by pages on the same domainALLOW-FROM uri- Deprecated, use CSP frame-ancestors instead
Modern Alternative
While X-Frame-Options is still widely supported, the modern approach is using CSP's frame-ancestors directive, which provides more granular control: Content-Security-Policy: frame-ancestors 'self' https://trusted.com
X-Content-Type-Options
Prevents MIME type sniffing, which can lead to security vulnerabilities.
X-Content-Type-Options: nosniff
This simple header tells browsers to trust the Content-Type header and not try to guess the content type. Without it, a browser might execute a file declared as text/plain as JavaScript if it looks like JavaScript.
Referrer-Policy
Controls how much referrer information is included with requests.
Referrer-Policy: strict-origin-when-cross-origin
Common policies:
no-referrer- Never send referrer informationstrict-origin- Send only origin, only for HTTPS→HTTPSstrict-origin-when-cross-origin- Full URL for same-origin, origin only for cross-origin (recommended)unsafe-url- Always send full URL (not recommended for security)
Permissions-Policy
Controls which browser features and APIs can be used on your site.
Permissions-Policy: geolocation=(), microphone=(), camera=()
This allows you to disable potentially invasive features that your site doesn't use, reducing attack surface.
X-XSS-Protection
Legacy header that enabled the browser's XSS filter. Now largely deprecated in favor of CSP.
X-XSS-Protection: 0
Deprecated Header
Modern browsers have removed XSS auditors due to bypass techniques and false positives. The recommended value is 0 to disable it, relying instead on Content-Security-Policy for XSS protection.
How to Analyze Response Headers
Understanding how to inspect and analyze HTTP headers is crucial for debugging, security audits, and optimization.
Using Browser Developer Tools
The easiest way to view headers:
- Open Developer Tools (F12 or Ctrl+Shift+I)
- Go to the Network tab
- Reload the page
- Click on any request
- View the Headers section
Using Command Line Tools
For automation and scripting, command-line tools are invaluable:
# View headers with curl
curl -I https://example.com
# View headers with verbose output
curl -v https://example.com
# View specific header
curl -I https://example.com | grep -i "content-security-policy"
Using HTTP Tiger's Header Checker
The most comprehensive way to analyze headers is using a dedicated tool that checks for security best practices:
How to Use the Tool
- Visit httptiger.com/header-checker.html
- Enter your website URL
- Click "Check Headers" to analyze the response
- Review the security score and recommendations
- Get specific implementation guidance for missing headers
Common Header Misconfigurations
Even experienced developers make these mistakes. Here's what to avoid:
1. Missing Security Headers Entirely
The Problem: Many sites ship with default server configurations that include minimal security headers.
The Fix: Implement at minimum: CSP, HSTS, X-Content-Type-Options, and X-Frame-Options.
2. Overly Permissive CSP
❌ Bad: Content-Security-Policy: default-src *; script-src * 'unsafe-inline' 'unsafe-eval'
This CSP allows everything and provides zero protection.
✓ Good: Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com
3. Short HSTS max-age
❌ Bad: Strict-Transport-Security: max-age=86400
A 1-day max-age means users are only protected for 24 hours between visits.
✓ Good: Strict-Transport-Security: max-age=31536000; includeSubDomains
4. Exposing Server Information
❌ Bad: Server: Apache/2.4.41 (Ubuntu) OpenSSL/1.1.1f
This tells attackers exactly what server version you're running, making targeted attacks easier.
✓ Good: Server: Apache (or remove the header entirely)
5. Weak Cache-Control for Sensitive Data
❌ Bad: Cache-Control: public, max-age=31536000 (on a user dashboard page)
This could cache sensitive user data in browsers or proxies for a year.
✓ Good: Cache-Control: no-store, no-cache, must-revalidate, private
6. Incorrect Content-Type
Serving JavaScript files as text/plain or JSON as text/html can cause security issues and functional problems.
Implementation Guide
How to implement security headers depends on your web server or hosting platform.
Apache (.htaccess)
# Enable mod_headers
# HSTS
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
# CSP
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.example.com; img-src 'self' data: https:; style-src 'self' 'unsafe-inline';"
# X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"
# X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"
# Referrer-Policy
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Permissions-Policy
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
Nginx
# In your server block
server {
# HSTS
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# CSP
add_header Content-Security-Policy "default-src 'self'; script-src 'self' https://cdn.example.com;" always;
# X-Frame-Options
add_header X-Frame-Options "SAMEORIGIN" always;
# X-Content-Type-Options
add_header X-Content-Type-Options "nosniff" always;
# Referrer-Policy
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
Node.js/Express
const helmet = require('helmet');
const app = express();
// Use helmet middleware for security headers
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'", "https://cdn.example.com"],
styleSrc: ["'self'", "'unsafe-inline'"],
imgSrc: ["'self'", "data:", "https:"]
}
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));
CloudFront (AWS)
Use Lambda@Edge or CloudFront Functions to add headers:
// Lambda@Edge (origin response)
exports.handler = (event, context, callback) => {
const response = event.Records[0].cf.response;
const headers = response.headers;
headers['strict-transport-security'] = [{
key: 'Strict-Transport-Security',
value: 'max-age=31536000; includeSubDomains; preload'
}];
headers['x-content-type-options'] = [{
key: 'X-Content-Type-Options',
value: 'nosniff'
}];
callback(null, response);
};
Testing Your Headers
After implementing security headers, thorough testing is essential to ensure they're working correctly and not breaking functionality.
Automated Testing Tools
- HTTP Tiger Header Checker - httptiger.com/header-checker.html - Comprehensive header analysis with security scoring
- SecurityHeaders.com - Quick security header scan with letter grades
- Mozilla Observatory - Detailed security analysis including headers and TLS configuration
Testing CSP
CSP is particularly tricky to get right. Use these strategies:
- Start with Report-Only mode:
Content-Security-Policy-Report-Only: default-src 'self'; report-uri /csp-violation-report - Monitor violation reports to identify legitimate resources being blocked
- Adjust policy based on reports
- Switch to enforcement mode once confident
Testing HSTS
HSTS testing checklist:
- Verify header is present on all HTTPS pages
- Test that HTTP redirects to HTTPS work
- Check that max-age is sufficiently long (minimum 1 year)
- Ensure no mixed content warnings appear
- Test subdomain coverage if using includeSubDomains
Security Header Checklist
A properly configured site should have:
- Content-Security-Policy (restrictive policy)
- Strict-Transport-Security (1 year minimum)
- X-Content-Type-Options: nosniff
- X-Frame-Options or CSP frame-ancestors
- Referrer-Policy (strict-origin-when-cross-origin)
- Permissions-Policy (disabling unused features)
Conclusion
HTTP headers are a powerful tool for enhancing your website's security, performance, and functionality. While they may seem technical, implementing proper headers is one of the highest-impact, lowest-effort security improvements you can make.
Start with the essential security headers (CSP, HSTS, X-Content-Type-Options, X-Frame-Options), test thoroughly, and gradually refine your configuration. Regular audits using automated tools will help you maintain a strong security posture over time.
Check Your HTTP Headers Now
Use HTTP Tiger's free header checker to analyze your website's headers and get specific recommendations.
Analyze Headers →