HTTP Security Header Checker

Instantly check which HTTP security headers your site uses. Detects missing CSP, HSTS, X-Frame-Options, and information leaks.

What are HTTP security headers?

Every time a browser requests a page, the server responds with HTTP headers before the actual HTML arrives. Most of these headers are mundane. Content type, cache duration, encoding. But a handful of them act as security directives that fundamentally change how the browser treats your content.

Content-Security-Policy tells the browser exactly which scripts, styles, and resources are allowed to load. See the full specification at MDN. Without it, any injected <script> tag runs with full privileges. Strict-Transport-Security forces HTTPS and prevents SSL-stripping attacks. X-Frame-Options blocks clickjacking by refusing to render your page inside an iframe on a malicious domain.

The problem? These headers are opt-in. Servers don't send them by default. The OWASP Secure Headers Project documents best practices for each one. If your Nginx config, Apache .htaccess, or Express middleware doesn't explicitly set them, they simply don't exist in the response. And the browser falls back to its most permissive behavior. That gap is exactly what attackers exploit.

Our checker sends a real HTTP request to your URL, parses every response header, and flags what's missing. Read our complete guide to HTTP security headers for an in-depth walkthrough.

Headers we check

The tool evaluates seven security-critical headers and flags information-leaking headers that expose your server stack.

HeaderPurposeSeverity if missing
Content-Security-PolicyControls which resources the browser may load. Primary defense against XSS and data injection.Critical
Strict-Transport-SecurityForces HTTPS-only connections per RFC 6797. Prevents SSL stripping and cookie hijacking over HTTP.Critical
X-Frame-OptionsPrevents your page from being embedded in iframes. Blocks clickjacking attacks.High
X-Content-Type-OptionsStops browsers from MIME-sniffing responses away from the declared content type.High
Referrer-PolicyControls how much referrer information the browser sends with requests. Prevents URL-based data leaks.Medium
Permissions-PolicyRestricts which browser features (camera, microphone, geolocation, payment) your page can use. See the W3C Permissions Policy spec.Medium
Cross-Origin-Opener-PolicyIsolates your browsing context from cross-origin popups. Prevents Spectre-class side-channel attacks.Medium

Need to build a CSP from scratch? Try our visual CSP generator with platform presets for Next.js, WordPress, and React.

How to fix missing security headers

The exact syntax depends on your web server or framework. Below are copy-paste examples that add all seven headers. Adjust the CSP directive values to match your actual resource origins. The examples use a strict baseline.

Nginx

server {
    # Prevent XSS. Restrict resource origins
    add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';" always;

    # Force HTTPS for 1 year, include subdomains
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;

    # Block framing (legacy fallback for CSP frame-ancestors)
    add_header X-Frame-Options "SAMEORIGIN" always;

    # Prevent MIME-type sniffing
    add_header X-Content-Type-Options "nosniff" always;

    # Limit referrer data to same-origin
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # Disable unnecessary browser features
    add_header Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()" always;

    # Isolate browsing context
    add_header Cross-Origin-Opener-Policy "same-origin" always;

    # Hide server version
    server_tokens off;
}

Apache (.htaccess)

<IfModule mod_headers.c>
    Header set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';"
    Header set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
    Header set X-Frame-Options "SAMEORIGIN"
    Header set X-Content-Type-Options "nosniff"
    Header set Referrer-Policy "strict-origin-when-cross-origin"
    Header set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=()"
    Header set Cross-Origin-Opener-Policy "same-origin"

    # Remove server info headers
    Header unset Server
    Header unset X-Powered-By
</IfModule>

Express / Node.js (helmet)

import helmet from "helmet";

app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        defaultSrc: ["'self'"],
        scriptSrc: ["'self'"],
        styleSrc: ["'self'", "'unsafe-inline'"],
        imgSrc: ["'self'", "data:"],
        fontSrc: ["'self'"],
        connectSrc: ["'self'"],
        frameAncestors: ["'self'"],
      },
    },
    strictTransportSecurity: {
      maxAge: 31536000,
      includeSubDomains: true,
      preload: true,
    },
    frameguard: { action: "sameorigin" },
    referrerPolicy: { policy: "strict-origin-when-cross-origin" },
    crossOriginOpenerPolicy: { policy: "same-origin" },
    // helmet strips X-Powered-By automatically
  })
);

Next.js / Vercel (next.config.js)

// next.config.js
const securityHeaders = [
  { key: "Content-Security-Policy", value: "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'self';" },
  { key: "Strict-Transport-Security", value: "max-age=31536000; includeSubDomains; preload" },
  { key: "X-Frame-Options", value: "SAMEORIGIN" },
  { key: "X-Content-Type-Options", value: "nosniff" },
  { key: "Referrer-Policy", value: "strict-origin-when-cross-origin" },
  { key: "Permissions-Policy", value: "camera=(), microphone=(), geolocation=(), payment=()" },
  { key: "Cross-Origin-Opener-Policy", value: "same-origin" },
];

module.exports = {
  async headers() {
    return [{ source: "/(.*)", headers: securityHeaders }];
  },
};

Security header grading

The tool assigns a letter grade from A to F based on a weighted scoring system. Not all headers are equal. CSP and HSTS carry significantly more weight because they protect against the broadest and most damaging attack categories (XSS and SSL stripping, respectively).

A
90 to 100 points

All critical headers present. Minor improvements possible (e.g., adding preload to HSTS).

B
75 to 89 points

Most headers present. Typically missing one medium-severity header like Permissions-Policy or COOP.

C
60 to 74 points

Partial coverage. Usually missing HSTS or has a weak CSP that relies on unsafe-inline.

D
40 to 59 points

Significant gaps. Likely missing CSP entirely, or missing multiple important headers.

F
0 to 39 points

Minimal or no security headers. The site relies entirely on browser defaults.

Information-leaking headers (Server, X-Powered-By, X-AspNet-Version) incur score penalties even when all security headers are present. Removing them can push a B+ into an A.

Common header mistakes

Setting headers incorrectly can be worse than not setting them at all. It gives a false sense of security. These are the mistakes we see most often.

CSP with 'unsafe-inline' and 'unsafe-eval'

Adding these keywords to script-src defeats the entire purpose of CSP. If inline scripts are allowed, an XSS payload runs just fine. Use nonces or hashes instead.

HSTS max-age too short

Setting max-age=86400 (one day) leaves a 24-hour window after each visit where SSL stripping works. Use at least 31536000 (one year). The HSTS preload list requires this minimum.

Missing 'always' flag in Nginx

Without the 'always' parameter, Nginx only adds headers on 2xx and 3xx responses. Error pages (4xx, 5xx) are served without security headers. Exactly the pages an attacker might trigger.

Setting X-Frame-Options but not frame-ancestors

X-Frame-Options is deprecated in favor of CSP frame-ancestors. Modern browsers ignore X-Frame-Options when CSP is present, so you need frame-ancestors in your CSP directive.

CDN stripping custom headers

Some CDNs and reverse proxies strip non-standard headers or override security headers with their own defaults. Always verify headers at the edge, not just at origin. Use this tool after deploying.

Referrer-Policy set to 'no-referrer'

While maximum privacy, this breaks analytics, CSRF tokens that check the Referer header, and OAuth redirects. 'strict-origin-when-cross-origin' is the pragmatic choice for most sites.

Frequently asked questions

What are HTTP security headers?+
HTTP security headers are directives sent by a web server in the HTTP response that tell the browser how to behave when handling your site's content. They control framing, script execution, HTTPS enforcement, MIME type handling, and more. Without them, browsers fall back to permissive defaults that leave users exposed to cross-site scripting (XSS), clickjacking, and data injection attacks.
Which security headers does this tool check?+
The checker scans for seven critical headers: Content-Security-Policy (CSP), Strict-Transport-Security (HSTS), X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, and Cross-Origin-Opener-Policy (COOP). It also detects information-leaking headers like Server and X-Powered-By.
How is the A-F security grade calculated?+
Each header carries a weight based on its security impact. CSP and HSTS are weighted highest because they prevent the broadest attack classes. The tool sums the weights of present headers, penalizes information leaks, and maps the total to a letter grade: A (90-100), B (75-89), C (60-74), D (40-59), and F (below 40).
Is Content-Security-Policy really necessary?+
Yes. CSP is the single most effective browser-side defense against XSS. It restricts which scripts, styles, images, and other resources can load on your page. Without CSP, an attacker who finds any injection point can execute arbitrary JavaScript in your users' browsers, steal session cookies, and exfiltrate data.
What does Strict-Transport-Security (HSTS) do?+
HSTS tells browsers to only connect to your domain over HTTPS, even if the user types http:// or clicks an HTTP link. This prevents SSL stripping attacks where a man-in-the-middle downgrades the connection. The max-age directive sets how long (in seconds) the browser remembers this instruction. A value of 31536000 (one year) with includeSubDomains is recommended.
Should I remove the Server and X-Powered-By headers?+
Yes. These headers reveal your web server software and version (e.g., 'nginx/1.24.0' or 'Express'). While removing them is not a security fix by itself, it raises the bar for attackers who use version-specific exploits. In Nginx, add 'server_tokens off;'. In Express, use helmet() which strips X-Powered-By by default.
How do I add security headers to my site?+
The method depends on your stack. For Nginx, add add_header directives in your server block. For Apache, use Header set in .htaccess or httpd.conf. For Express/Node.js, use the helmet middleware. For Next.js on Vercel, configure the headers() function in next.config.js. Our tool provides copy-paste examples for each platform.
What is the difference between X-Frame-Options and CSP frame-ancestors?+
Both prevent clickjacking, but CSP frame-ancestors is the modern replacement. X-Frame-Options only supports DENY and SAMEORIGIN, while frame-ancestors accepts specific origins (e.g., frame-ancestors 'self' https://trusted.com). Browsers that support CSP ignore X-Frame-Options when frame-ancestors is present. Set both for backward compatibility.
Does this tool store my scan results?+
No. The header check runs in real-time and results are not stored on our servers. Each scan makes a fresh HTTP request to your URL and analyzes the response headers on the fly. For a complete security audit that includes SSL/TLS, port scanning, OWASP checks, and AI-generated reports, try our full scan at ismycodesafe.com.
How often should I check my security headers?+
Check after every deployment that changes your server configuration, reverse proxy setup, or CDN settings. Headers can silently disappear when you migrate hosting providers, update Nginx configs, or switch from a traditional server to a serverless platform. A monthly audit is a reasonable baseline for production sites.

Related tools

Want a full security audit?

Security headers are just one layer. Our full website security scan also checks SSL/TLS configuration, open ports, exposed sensitive files, DNS records, technology stack vulnerabilities, and more. Enter your URL on the homepage to get a full AI-generated security report.

Run a full security scan

Learn more about cross-site scripting (XSS) and how security headers prevent it.

Need the full picture?

Run a complete security audit with 150+ checks, OWASP Top 10, and CVE lookup.

Run Full Scan