Most websites are missing critical HTTP security headers. These headers tell browsers how to handle your site’s content — blocking clickjacking, XSS attacks, MIME sniffing, and more. Without them, your site is vulnerable to attacks that are trivially preventable.
The good news: checking takes seconds, and fixing usually means adding a few lines to your server config.
Scan any website for security headers, SEO issues, and more.
Run Free AuditOr via curl: curl -s "https://snap.michaelcli.com/api/audit?url=https://yoursite.com"
When your browser requests a web page, the server sends back HTTP headers along with the content. Security headers are a subset of these that instruct the browser to enable specific protections.
Think of them as seatbelts for your website. They don’t prevent all accidents, but they prevent the easy, embarrassing ones — the attacks that make security researchers shake their heads.
Here’s the problem: most web frameworks don’t set them by default. You have to add them yourself. And because they’re invisible to visitors (no one sees HTTP headers), they get forgotten.
The single most important security header. CSP tells the browser which sources of content (scripts, styles, images) are allowed. Without it, an attacker who injects a script into your page can load anything from anywhere.
Content-Security-Policy: default-src self; script-src self https://cdn.example.com
Impact: Blocks XSS attacks, data injection, clickjacking via inline frames.
Forces browsers to only connect via HTTPS. Without HSTS, a user who types http://yoursite.com makes an unencrypted request before being redirected — a window for man-in-the-middle attacks.
Strict-Transport-Security: max-age=31536000; includeSubDomains
Impact: Prevents SSL stripping attacks, protocol downgrade attacks.
Prevents browsers from MIME-type sniffing. Without it, a browser might interpret a text file as JavaScript and execute it.
X-Content-Type-Options: nosniff
Impact: Blocks MIME confusion attacks.
Controls whether your site can be embedded in an iframe on another domain. Without it, attackers can overlay your site with invisible frames to trick users into clicking things (clickjacking).
X-Frame-Options: DENY
Impact: Prevents clickjacking attacks.
Enables the browser’s built-in XSS filter. While modern browsers have largely moved to CSP, this header still provides defense-in-depth for older browsers.
X-XSS-Protection: 1; mode=block
Controls how much referrer information is sent when users click links on your site. Without it, full URLs (including query parameters with sensitive data) leak to third-party sites.
Referrer-Policy: strict-origin-when-cross-origin
Impact: Prevents leaking sensitive URL paths and parameters.
Controls which browser features (camera, microphone, geolocation) your site can use. Even if your site doesn’t use these features, setting this header prevents injected scripts from accessing them.
Permissions-Policy: camera=(), microphone=(), geolocation=()
You have three options, from easiest to most detailed:
Our website audit checks all 7 security headers plus 18 SEO and technical checks in one scan:
curl -s "https://snap.michaelcli.com/api/audit?url=https://yoursite.com"
Or use the web interface for a visual report with fix instructions.
curl -sI https://yoursite.com | grep -iE "(content-security|strict-transport|x-content-type|x-frame|x-xss|referrer-policy|permissions-policy)"
If a header is missing from the output, your site doesn’t set it.
Open DevTools (F12) → Network tab → reload the page → click the first request → check Response Headers.
server {
add_header X-Frame-Options "DENY" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header Content-Security-Policy "default-src self" always;
}
Header always set X-Frame-Options "DENY" Header always set X-Content-Type-Options "nosniff" Header always set X-XSS-Protection "1; mode=block" Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains" Header always set Referrer-Policy "strict-origin-when-cross-origin" Header always set Permissions-Policy "camera=(), microphone=(), geolocation=()" Header always set Content-Security-Policy "default-src self"
const helmet = require(helmet); app.use(helmet());
The helmet package sets all recommended headers with sensible defaults.
Add a vercel.json or _headers file:
// vercel.json
{
"headers": [{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Strict-Transport-Security", "value": "max-age=31536000" }
]
}]
}
We audited some well-known sites. Here’s how their security headers stack up:
| Site | Security Headers | Missing |
|---|---|---|
| google.com | 6/7 | Permissions-Policy |
| github.com | 7/7 | — |
| wordpress.com | 3/7 | CSP, HSTS, Permissions, Referrer |
| shopify.com | 5/7 | Permissions, CSP |
| medium.com | 4/7 | Permissions, CSP, X-XSS |
Want to check your site? Run the audit and see exactly which headers you’re missing.
Check security headers + 18 SEO checks. Free, instant, no signup.
Run Free AuditSecurity headers are one of the easiest wins in web security. They take 5 minutes to add and protect against entire categories of attacks. There’s no excuse for not having them.
If you’re building a web application, add them to your server config today. If you’re auditing someone else’s site, use the scanner and send them the results.
For automated monitoring, integrate the SnapAPI endpoint into your CI/CD pipeline:
curl -s "https://snap.michaelcli.com/api/audit?url=$DEPLOY_URL" | grep -q "security headers missing" && echo "WARNING: Security headers incomplete"