Blog · SEO

Security Headers: What Each One Does and How to Set Them Up

A handful of HTTP response headers protect your visitors from cross-site scripting, clickjacking and downgrade attacks. What each one does, safe values to start with, how our free security headers checker tests your site and how to fix every problem it reports, on nginx, Apache and Cloudflare.

Searvia · 10/24/2026 · 11 min read

In short: Security headers are instructions your server sends with every page, telling browsers to always use HTTPS, run scripts only from sources you approve, refuse to let other sites frame your pages, never guess file types and keep full URLs out of the Referer header. Start with HTTPS everywhere and a valid certificate, then add Strict-Transport-Security, X-Content-Type-Options: nosniff, Referrer-Policy: strict-origin-when-cross-origin and frame-ancestors or X-Frame-Options. Roll out Content-Security-Policy in report-only mode first. All of them are set in the server or CDN configuration.

Security headers are cheap insurance. Most take one line of server configuration, cost nothing in performance and close off whole classes of attacks: an injected script that steals sessions, an invisible frame that tricks people into clicking, a coffee-shop network that downgrades a visitor to plain HTTP. They are also among the first things security scanners, enterprise customers and security questionnaires check.

This guide explains each header and the connection basics around them, gives safe starting values, shows how our free security headers checker tests your site, and walks through a fix for every problem it reports.

The basics first: HTTPS, certificate and mixed content

Headers sit on top of an encrypted connection; without one, they don't help. Three basics come first:

The headers, one by one

HeaderProtects againstSafe starting value
Strict-Transport-SecurityDowngrade to HTTP, cookie theft on open networksmax-age=31536000; includeSubDomains (after testing)
Content-Security-PolicyCross-site scripting (XSS), injected content, clickjacking via frame-ancestorsStart with Content-Security-Policy-Report-Only
X-Frame-Options or CSP frame-ancestorsClickjackingSAMEORIGIN or frame-ancestors 'self'
X-Content-Type-OptionsMIME sniffing: files run as scripts or stylesnosniff
Referrer-PolicyLeaking full URLs to other sitesstrict-origin-when-cross-origin
Permissions-PolicyEmbedded scripts using camera, microphone, locationcamera=(), microphone=(), geolocation=()

Strict-Transport-Security (HSTS)

HSTS tells the browser to use HTTPS for your host for a set number of seconds, even when someone types http:// or clicks an old link. MDN notes three things to know:

The HSTS preload list hard-codes your domain into browsers. It requires a valid certificate, an HTTP-to-HTTPS redirect on the same host, all subdomains on HTTPS, and a header with max-age of at least 31536000, includeSubDomains and preload. It also warns that "inclusion in the preload list cannot easily be undone": removal takes months to reach users. Preload only when you are sure.

Content-Security-Policy (CSP)

CSP is the strongest of the headers and the hardest to deploy. It lists where scripts, styles, images and other resources may load from, and the browser refuses everything else. MDN calls it mainly "a defense against cross-site scripting (XSS) attacks."

The recommended modern form is a strict CSP based on nonces or hashes rather than long domain allowlists:

Content-Security-Policy: script-src 'nonce-{RANDOM}'; object-src 'none'; base-uri 'none'

The nonce must be random and different on every response. MDN warns that 'unsafe-inline' "defeats much of the purpose of having a CSP."

Because a strict policy can break analytics tags, chat widgets and inline scripts, deploy it in two steps: send Content-Security-Policy-Report-Only with a reporting endpoint, fix what the reports show, then switch to the enforcing header. CSP is also where upgrade-insecure-requests lives (a mixed-content safety net, not a replacement for HSTS) and where frame-ancestors controls framing.

X-Frame-Options and frame-ancestors

Clickjacking loads your page in an invisible frame on another site and tricks people into clicking your buttons. Two ways to stop it:

Neither works from a <meta> tag. MDN states that X-Frame-Options in a meta element "has no effect" and that frame-ancestors "is not supported in the <meta> element." Note also that frame-ancestors doesn't fall back to default-src: a policy of default-src 'none' still allows anyone to frame the page.

X-Content-Type-Options

nosniff tells browsers to trust your Content-Type header. With it, a response requested as a script or stylesheet is blocked if its MIME type doesn't match, which stops an uploaded file disguised as an image from running as a script. It only has one valid value:

X-Content-Type-Options: nosniff

Make sure your server sends correct content types, especially for JavaScript and CSS, before you add it.

Referrer-Policy

When a visitor clicks a link to another site, the browser sends a Referer header. Modern browsers already default to strict-origin-when-cross-origin, which sends only the origin (https://example.com/) cross-site and nothing when going from HTTPS to HTTP (MDN). OWASP still recommends setting it explicitly "rather than relying on browser defaults." Avoid unsafe-url, which sends full URLs, including any tokens in them, everywhere.

Permissions-Policy, and the headers to drop

Permissions-Policy switches off browser features you don't use, so an embedded script can't ask for the camera or location. MDN marks it as experimental with limited browser support, so treat it as an extra layer. Our free checker doesn't test it; the full security scan does.

Two headers to remove rather than add: OWASP says not to set X-XSS-Protection (or set it to 0), because the old filters it controlled could create vulnerabilities, and calls Expect-CT deprecated. It also recommends removing X-Powered-By and giving Server a non-informative value.

How the Searvia security headers checker works

The free security headers checker runs the same engine as our website SEO checker and puts five checks first. It makes ordinary requests that any visitor could make; nothing is attacked or probed.

CheckHow it testsPassWarningFailPriority
HTTPSLoads the page over HTTPS, then requests http:// without following redirectsHTTPS works and HTTP redirects to an https:// address (if HTTP doesn't answer at all, you get a note instead)HTTPS doesn't work, or HTTP doesn't redirectHigh
TLS certificateReads the certificate of the final hostValid, matches the host, 14+ days leftUnder 14 days leftExpired or doesn't cover the hostHigh
HSTSReads max-age from the page's response15,552,000 seconds (about 6 months) or moreMissing or shorterLow
Mixed contentFinds http:// URLs in scripts, iframes, stylesheets, images, video, audio and sources on an HTTPS pageNoneOnly images or mediaScripts, iframes or stylesheetsMedium
Security headersLooks for three key response headers and shows Referrer-PolicyAll three presentAny missingLow

The three it counts are Content-Security-Policy, X-Frame-Options (or a CSP header containing frame-ancestors) and X-Content-Type-Options. Referrer-Policy is listed too, but a missing one is not counted against you: browsers already default to strict-origin-when-cross-origin, and the table says so. The result table shows each one's value, with long policies shortened.

Some limits to keep in mind:

How to read the results

Work top to bottom by priority. A failing HTTPS or certificate check is urgent: visitors see browser warnings or travel unencrypted. Active mixed content (scripts, iframes, stylesheets) is next, because browsers block those files and the page may break. HSTS and the security headers are low priority in the score, but they are also the quickest to fix, so batch them in one configuration change.

How to fix every problem the checker reports

"The site does not work over HTTPS." / "HTTP does not redirect to HTTPS."

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

On Cloudflare, turn on "Always Use HTTPS" under SSL/TLS › Edge Certificates.

"The certificate expired N days ago." / "The certificate does not cover this domain."

A warning with fewer than 14 days left usually means automatic renewal is not working; investigate rather than renewing by hand each time.

"HSTS is not set." / "HSTS is on but shorter than 6 months."

Roll it out in stages so a forgotten HTTP-only subdomain doesn't get locked out:

add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

"N files load over plain HTTP."

"N key security headers are missing."

Add the missing ones in one change. For nginx:

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 Content-Security-Policy-Report-Only "default-src 'self'; frame-ancestors 'self'; report-to csp" always;

For Apache:

Header always set X-Frame-Options "SAMEORIGIN"
Header always set X-Content-Type-Options "nosniff"
Header always set Referrer-Policy "strict-origin-when-cross-origin"

On Cloudflare, add response headers with a Transform Rule. On Netlify, use a _headers file; on Vercel, the headers setting in vercel.json. In nginx, remember that add_header in a location block replaces the headers set at server level, so repeat them or use an include file.

For CSP, the report-only line above is a starting point, not a finished policy. Point report-to at a reporting endpoint you control, review violations for a week or two, adjust the policy, then rename the header to Content-Security-Policy. Once enforced, the CSP check passes.

How to check headers yourself

The checker shows what the checked page sends, but other pages, files and error responses can differ. Two quick ways to look:

A common surprise is headers that appear on normal pages but not on errors or redirects. In nginx, add_header only applies to successful and redirect responses unless you add the always parameter, which is why every example above includes it. Another is a CDN or host that adds or strips headers, so check the response the public sees, not just your server configuration file.

Remember that each header protects a different thing. A perfect CSP does nothing for an expired certificate, and HSTS does nothing against an injected script. The goal is the whole set, added in a sensible order.

Worked example (hypothetical)

The following is a hypothetical example, not real data. Halden Legal, an invented law firm, receives a security questionnaire from a corporate client asking about its website headers. The security headers checker reports:

The fixes take one afternoon. The two image URLs are changed to HTTPS. After confirming that the client portal subdomain works over HTTPS, HSTS goes to max-age=31536000; includeSubDomains in two steps over a week. X-Frame-Options: SAMEORIGIN and Referrer-Policy: strict-origin-when-cross-origin are added at the server. A report-only CSP runs for ten days and reveals an inline script from the booking widget, which is moved to a file and allowed by its origin before the policy is enforced. The final run passes every check, and the firm answers the questionnaire with a link to the shared report.

A one-hour checklist

How Searvia keeps watching your site's security

The free security headers checker checks your home page, or any page you enter, in about 20 seconds, without sign-up, and the same report covers 33 more checks on search appearance, crawling, speed, mobile and email authentication.

A free Searvia account adds a weekly security scan: passive checks of encryption, browser protections, cookie flags, software versions and email spoofing protection, with the request and response that prove each finding. It grades your CSP (for example, 'unsafe-inline' without nonces or hashes), checks Permissions-Policy, and after you verify ownership also looks for exposed .env and .git files, public backups, debug pages and unsafe CORS. Write the remediation plan with AI turns the findings into configuration you can paste (5 credits). On paid plans from Starter, uptime monitoring also checks your TLS certificate daily and alerts you before it expires.

Frequently Asked Questions

What are security headers?
Security headers are HTTP response headers that tell the browser how to handle your page more safely: always use HTTPS (Strict-Transport-Security), only run scripts from approved sources (Content-Security-Policy), don't allow framing by other sites (X-Frame-Options or frame-ancestors), don't guess file types (X-Content-Type-Options) and limit what is sent in the Referer header (Referrer-Policy). They are set on the server or CDN, not in your page content.
Do security headers affect SEO?
Not as individual ranking factors. Google's page experience guidance asks whether pages are served securely, so HTTPS matters, and broken HTTPS or mixed content harms visitors and trust. Headers like Content-Security-Policy and X-Frame-Options protect users from attacks; their value is security, not rankings.
What is a good HSTS max-age?
One year (max-age=31536000) is a common choice and the minimum for the HSTS preload list, which also requires includeSubDomains and preload. Start lower, for example a few minutes, then a week, then a month, while you confirm that every subdomain works over HTTPS, because browsers will refuse plain HTTP for the whole period. Our checker passes values of about six months or more.
Should I use X-Frame-Options or frame-ancestors?
Both are fine; frame-ancestors in Content-Security-Policy is the more flexible modern option and X-Frame-Options is the older fallback. Use frame-ancestors 'self' or X-Frame-Options: SAMEORIGIN if you never need your pages embedded elsewhere. Neither works in a meta tag; they must be sent as HTTP headers.
Is X-XSS-Protection still needed?
No. OWASP recommends not setting it or explicitly turning it off with X-XSS-Protection: 0, because the old browser XSS filters it controlled could introduce vulnerabilities. Use a Content-Security-Policy that blocks inline scripts instead.

Sources

  1. HTTP Security Response Headers Cheat Sheet – OWASP
  2. Strict-Transport-Security – MDN Web Docs
  3. HSTS Preload List Submission – hstspreload.org
  4. Content Security Policy (CSP) – MDN Web Docs
  5. CSP: frame-ancestors – MDN Web Docs
  6. X-Frame-Options – MDN Web Docs
  7. X-Content-Type-Options – MDN Web Docs
  8. Referrer-Policy – MDN Web Docs
  9. Permissions-Policy – MDN Web Docs
  10. Mixed content – MDN Web Docs
  11. Understanding page experience in Google Search results – Google Search Central
  12. Module ngx_http_headers_module – nginx documentation
  13. A secure web is here to stay – Chromium Blog

Keep Reading