
Security headers are a set of HTTP response headers that tell the browser how to handle your content securely. Without the right security headers, your website becomes vulnerable to attacks like cross-site scripting (XSS), clickjacking, and MIME type sniffing. The good news: adding them requires no code changes — just a few lines in your .htaccess or Nginx config.
This guide explains the most important security headers, shows you how to check your current grade for free, and walks through adding them to Apache or Nginx hosting.
Key Security Headers Every Website Should Have
| Header | Protects Against | Recommended Value |
|---|---|---|
Strict-Transport-Security |
HTTPS downgrade attacks | max-age=31536000; includeSubDomains |
Content-Security-Policy |
XSS and unauthorized resource loading | Customize per site (e.g., default-src 'self') |
X-Frame-Options |
Clickjacking via iframe embedding | SAMEORIGIN or DENY |
X-Content-Type-Options |
MIME sniffing attacks | nosniff |
Referrer-Policy |
Leaking referrer info to third parties | strict-origin-when-cross-origin |
Permissions-Policy |
Unauthorized access to camera, mic, geolocation | geolocation=(), microphone=(), camera=() |
X-XSS-Protection |
Reflected XSS (legacy browsers) | 1; mode=block |
Check Your Security Headers Instantly (Free)
Before adding headers, run a quick check to see what your site already sends and what's missing. A free online tool that gives detailed, easy-to-understand results:
dnsxray.com — Security Headers Checker
Check HTTP security headers for any website instantly. See which headers are present, which are missing, and get plain-English fix suggestions — no installation required.
Check Security Headers Free →Understanding the Grade System
Security header checkers typically score your site from A+ to F based on which headers are present and how well they're configured:
Most unconfigured sites score D or F. A good target is B+ or higher. For e-commerce, banking, or login-based sites, aim for A+.
Adding Security Headers in .htaccess (Apache / DirectAdmin)
On Apache-based hosting — including AsiaGB's DirectAdmin hosting — add security headers to your root .htaccess file:
# Security Headers — add to .htaccess
<IfModule mod_headers.c>
# Force HTTPS for 1 year
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" "expr=%{HTTPS} == 'on'"
# Prevent clickjacking
Header always set X-Frame-Options "SAMEORIGIN"
# Prevent MIME sniffing
Header always set X-Content-Type-Options "nosniff"
# Referrer policy
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Disable camera/mic/geo
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# Legacy XSS protection
Header always set X-XSS-Protection "1; mode=block"
</IfModule>
Adding Security Headers in Nginx (VPS)
On a VPS running Nginx, add these headers inside the server block of your site configuration:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
add_header X-XSS-Protection "1; mode=block" always;
Testing Security Headers on Staging Before Going Live
Before pushing security headers to a production server, test them on a staging environment first — especially CSP, which is the most likely to break functionality. Here is a reliable testing workflow:
- Check browser DevTools Console: After adding headers, open the Console tab (F12) and look for "Refused to load" or "Blocked by Content Security Policy" messages.
- Start with Report-Only mode: Use
Content-Security-Policy-Report-Onlyto monitor violations without blocking anything. Run it for at least two to four days to catch edge cases. - Test every feature path: Exercise all site functionality — forms, embedded videos, maps, payment widgets, login flows — since each may require different source allowances in CSP.
- Test on mobile: Some mobile browsers interpret CSP directives slightly differently. Test on both iOS Safari and Android Chrome at minimum.
- Verify live with a checker: After deploying to production, re-run dnsxray.com/security-headers to confirm the headers are actually being served correctly.
No staging environment? Use a subdomain (e.g., staging.yourdomain.com) or a local development setup. On Apache with XAMPP or Laragon, place headers in the Virtual Host config rather than .htaccess for easier management.
Security Headers Across Platforms: Apache, Nginx, and Frameworks
The method for setting security headers depends on your hosting stack. Here is a quick reference for the most common environments:
| Platform | Where to Set Headers | Notes |
|---|---|---|
| Apache (shared hosting) | .htaccess at document root |
Requires mod_headers — enabled by default on most hosts including AsiaGB |
| Nginx (VPS) | nginx.conf or site config in sites-enabled/ |
Use add_header ... always; — the always flag ensures headers appear on error pages too |
| Next.js | next.config.js headers array |
Applies at build time; supports regex route matching |
| Laravel | HTTP Middleware class | Register in app/Http/Kernel.php global middleware stack |
| Cloudflare Pages / Netlify | _headers file or platform config |
Apache .htaccess does not apply on these platforms |
| WordPress (plugin) | .htaccess or security plugin | Add headers above # BEGIN WordPress to prevent permalink-save overwriting |
Understanding Content-Security-Policy in Depth
Content-Security-Policy (CSP) is the most powerful — and most complex — security header. It tells the browser exactly which sources are allowed to load scripts, styles, images, fonts, and other resources. A well-crafted CSP makes XSS attacks significantly harder to execute because even if an attacker injects a script tag, the browser will refuse to run it if the source isn't whitelisted.
Core CSP Directives
default-src— Fallback for any directive not explicitly setscript-src— Allowed sources for JavaScript filesstyle-src— Allowed sources for CSS filesimg-src— Allowed sources for imagesconnect-src— Allowed endpoints for Fetch, XHR, and WebSocket connectionsframe-ancestors— Controls which pages can embed your site in an iframe (replaces X-Frame-Options)
Sample CSP for a Site Using Google Analytics and Google Fonts
# Sample CSP — customize for your site
Header always set Content-Security-Policy \
"default-src 'self'; \
script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com; \
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; \
font-src 'self' https://fonts.gstatic.com; \
img-src 'self' data: https://www.google-analytics.com; \
connect-src 'self' https://www.google-analytics.com; \
frame-ancestors 'self';"
Start with Report-Only mode: Use Content-Security-Policy-Report-Only before enforcing. This logs violations to the browser console without blocking anything, letting you refine the policy before it affects real users.
Security Header Impact Comparison
Each security header protects against different attack vectors. Understanding the risk of missing each one helps you prioritize what to implement first:
| Header | Priority | Risk If Missing | Most Vulnerable Sites |
|---|---|---|---|
Strict-Transport-Security |
Critical | HTTPS can be downgraded to HTTP by attackers | Any HTTPS site |
Content-Security-Policy |
Critical | XSS attacks can steal cookies and session tokens | Login-based, e-commerce sites |
X-Frame-Options |
High | Site can be embedded in iframes for clickjacking | Banking, admin dashboards |
X-Content-Type-Options |
Medium | Browser may execute scripts disguised as other file types | Sites that accept file uploads |
Referrer-Policy |
Medium | Private URLs (e.g., tokens in query strings) leak to third parties | Sites using URL-based tokens |
Permissions-Policy |
Medium | Third-party scripts can access camera, microphone, or location | Any site with third-party scripts |
HSTS Preload: Long-Term Commitment You Must Understand
HSTS Preload means registering your domain in a hardcoded list that Chrome, Firefox, Safari, and Edge ship in their source code. The browser enforces HTTPS before making any network request — even on a first visit — because it already knows your site requires it.
Requirements before submitting to the HSTS Preload list at hstspreload.org:
- A valid SSL certificate covering all subdomains
Strict-Transport-Securityheader withmax-ageof at least 31536000 (one year)- The
includeSubDomainsdirective present - The
preloaddirective present - All HTTP requests redirect to HTTPS first
Critical warning: HSTS Preload is extremely difficult to reverse. Browsers take months to ship an updated list that removes your domain. Never submit for preload if any subdomain does not have SSL or still serves HTTP content — users will be unable to access that subdomain for months.
Common Problems After Adding Security Headers
Implementing security headers sometimes breaks functionality. Here are the most common issues and how to fix them:
1. White Screen After Adding CSP
The most common cause is CSP blocking a required script or stylesheet. Open browser DevTools (F12), check the Console tab, and look for "Refused to load..." errors. Each error will include the blocked URL — add that domain to the appropriate CSP directive.
2. External Images or Videos Not Displaying
Verify that img-src and media-src in your CSP include the domains hosting those assets. For example, if you serve images from a CDN, that CDN domain must be explicitly listed.
3. Google Analytics or Tracking Tags Stop Working
Add tracking platform domains to both script-src and connect-src:
script-src 'self' 'unsafe-inline'
https://www.googletagmanager.com
https://connect.facebook.net;
connect-src 'self'
https://www.google-analytics.com
https://www.facebook.com;
4. HSTS Prevents HTTP Access During Development
This is expected behavior — browsers that have seen an HSTS header will refuse HTTP connections for the max-age duration. For local testing, use an Incognito window, or clear HSTS state in Chrome at chrome://net-internals/#hsts.
Debug tip: Use dnsxray.com/security-headers to verify which headers your server is actually sending after making changes to .htaccess or Nginx config. Cached responses can sometimes show stale header data.
Security Headers for WordPress
Add headers to your root .htaccess above the # BEGIN WordPress block (WordPress rewrites below that marker when you save Permalinks). Alternatively, use a plugin:
- WP Rocket — Security headers available under Advanced Rules
- Wordfence — Extended Protection includes header configuration
- Headers Security Advanced & HSTS WP — Dedicated security header management plugin
Step-by-Step: Using dnsxray.com to Check Headers
- Open dnsxray.com/security-headers
- Enter your website URL (e.g.,
https://yourdomain.com) and click Check - View your overall grade plus the status of each individual header
- Missing headers show specific fix instructions
- After adding headers to
.htaccessor Nginx, re-check to confirm the grade improved
Try it now: Open dnsxray.com/security-headers, enter your URL, and get your security header grade in under 30 seconds — completely free, no account required.
Frequently Asked Questions
Content-Security-Policy-Report-Only mode to monitor violations without enforcing them, then refine the policy before switching to enforcement.Strict-Transport-Security response header. Once a browser sees this header, it enforces HTTPS connections for the duration specified in max-age without allowing fallback to HTTP.AsiaGB Hosting Ships with Security Headers Built In
Every hosting plan includes free SSL, HSTS, cPGuard, and Imunify360 malware protection — from 500 THB/year