🛡️ Security HTTP Response Header Generator
Generate HSTS, Content-Security-Policy, X-Frame-Options, Referrer-Policy and Permissions-Policy response headers, with preload gated behind a warning.
OWASP Recommended Security Header Toggles
Generated HTTP Response Headers
What Security HTTP Response Header Generator Does
This tool builds a block of HTTP response security headers — Strict-Transport-Security (HSTS), X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Content-Security-Policy (CSP) and a fixed Permissions-Policy line — that you paste into your web server or application config. Untick a box and that line disappears from the output entirely rather than being blanked out, so what you copy is only what you asked for. The one exception is Permissions-Policy: it has no toggle and is appended to every configuration, checked or not.
The HSTS preload checkbox is deliberately hard to reach: it stays disabled until HSTS itself is switched on, and checking it does not add a second header — it appends the word `preload` to the same Strict-Transport-Security line. That friction is intentional. Preloading a domain means Chrome, Firefox and Safari ship a hardcoded list that forces HTTPS before the browser ever makes a request, so a misconfigured subdomain that still serves plain HTTP becomes unreachable in every preloaded browser until you go through a removal process that plays out over browser release cycles, not a config redeploy.
The output is one generic block, not a config file. Nginx, Apache, Cloudflare and a Next.js `headers()` array each apply these lines through different syntax, and two of those platforms have a specific failure mode worth knowing before you paste anything in: Nginx's `add_header` directive silently skips 4xx and 5xx responses unless you add the word `always`, and it stops inheriting a parent block's headers the moment you add even one `add_header` inside a child `location` block.
The Content-Security-Policy line is fixed, not a builder — you get one policy string, not independent control over script-src, style-src, img-src and connect-src. This batch tightened it: script-src no longer carries 'unsafe-inline', and object-src 'none' plus base-uri 'self' were added. style-src still carries 'unsafe-inline', which is worth knowing before you assume the whole policy blocks inline content.
How to Use Security HTTP Response Header Generator
- Toggle desired security protections (HSTS, CSP, X-Frame-Options, Referrer Policy)
- Review generated HTTP headers
- Copy and paste into your web server configuration (Nginx, Apache, Cloudflare Workers)
Formula Used by Security HTTP Response Header Generator
HSTS max-age in human time
days = max-age ÷ 86,400 | years = days ÷ 365
- max-age
- Seconds the browser should remember to force HTTPS for this host, from the Strict-Transport-Security header
- 86,400
- Seconds in one day (24 × 60 × 60)
Worked example
This tool hardcodes max-age=31536000 whenever HSTS is checked, on or off preload.
- 31,536,000 ÷ 86,400 = 365 days
- 365 ÷ 365 = 1 year
Result: Exactly 365 days. That is also the exact minimum the HSTS preload list will accept — the tool's fixed value clears the bar with no margin, so lowering it yourself before submitting to preload would disqualify the domain.
How many header lines a given configuration produces
N = HSTS + X-Frame-Options + X-Content-Type-Options + Referrer-Policy + CSP + 1
- HSTS, X-Content-Type-Options, CSP
- 1 if the checkbox is ticked, 0 if not
- X-Frame-Options
- 1 unless the dropdown is set to "None" (an empty string), which produces 0
- Referrer-Policy
- Always 1 — the dropdown has no blank option, so this line is never omitted
- + 1
- The Permissions-Policy line, which has no toggle and is always appended
Worked example
Factory defaults: HSTS on, X-Frame-Options DENY, X-Content-Type-Options on, Referrer-Policy strict-origin-when-cross-origin, CSP on.
- N = 1 + 1 + 1 + 1 + 1 + 1
Result: N = 6 lines. Unticking every optional header and setting X-Frame-Options to "None" leaves N = 0 + 0 + 0 + 1 + 0 + 1 = 2 lines — Referrer-Policy and Permissions-Policy are the two lines this tool cannot produce an empty output for.
Every Control in This Tool
What each toggle does to the output, read directly from the component.
| Control | Default | Effect |
|---|---|---|
| HSTS checkbox | Checked | Adds Strict-Transport-Security: max-age=31536000; includeSubDomains |
| HSTS preload checkbox | Unchecked, disabled until HSTS is on | Appends "; preload" to the same HSTS line — not a separate header |
| X-Frame-Options dropdown | DENY | DENY, SAMEORIGIN, or "None" which omits the line entirely |
| X-Content-Type-Options checkbox | Checked | Adds X-Content-Type-Options: nosniff, or omits the line |
| Referrer-Policy dropdown | strict-origin-when-cross-origin | Also offers no-referrer or same-origin; never produces an empty line |
| Content-Security-Policy checkbox | Checked | Adds the fixed 6-directive policy string, or omits the line |
| Permissions-Policy | Always on, no toggle | Always adds camera=(), microphone=(), geolocation=() regardless of other settings |
The Six CSP Directives This Tool Sets
The exact policy string emitted when the CSP checkbox is on. It is fixed — there is no per-directive editor.
| Directive | Value | Restricts |
|---|---|---|
| default-src | 'self' | Fallback source list for any fetch directive not set explicitly |
| img-src | 'self' data: https: | Images from your own origin, inline data: URIs, and any HTTPS host |
| script-src | 'self' | JavaScript and WebAssembly sources — no 'unsafe-inline', tightened this batch |
| style-src | 'self' 'unsafe-inline' | CSS sources — still allows inline <style> tags and style attributes; not tightened this batch |
| object-src | 'none' | Sources for <object> and <embed> — blocks plugin content outright |
| base-uri | 'self' | URLs usable in a document's <base> element — blocks base-tag hijacking |
Source: MDN — Content-Security-Policy
Nginx add_header: Which Responses Get the Header Without "always"
Paste this block into an Nginx location block and it applies to these response codes by default — no others.
| Response class | Codes included without "always" | What silently loses the header |
|---|---|---|
| Success | 200, 201, 204, 206 | Nothing — this is the case every test happens against |
| Redirect | 301, 302, 303, 304, 307, 308 | Nothing — redirects are covered |
| Client error | None (e.g. 400, 401, 403, 404) | A custom 404 page ships with no CSP, no HSTS, no X-Frame-Options |
| Server error | None (e.g. 500, 502, 503) | An error page from a crashed backend ships unprotected too |
Does This Tool's HSTS Line Alone Meet the Preload List's Bar?
What hstspreload.org actually requires to accept a submission, checked against what this tool produces on its own.
| Requirement | What this tool produces | Met by the header alone? |
|---|---|---|
| max-age of at least 31,536,000 seconds | Exactly 31,536,000 — the floor, not above it | Yes |
| includeSubDomains present | Always included whenever HSTS is checked | Yes |
| preload directive present in the header | Only if the preload checkbox is also checked | Only if you check it |
| Valid TLS certificate; HTTP redirects to HTTPS | Not something a response header can do | No — server config, done separately |
| Every subdomain reachable over HTTPS | Not something any header can verify | No — you must confirm this yourself first |
Source: hstspreload.org
How to Read Your Result
HSTS preload is a one-way door, not a checkbox
Turning the preload checkbox off in this tool and redeploying does not remove your domain from browsers that already preloaded it. Per hstspreload.org, removing the preload directive from your live header only makes you "eligible for the removal form" — actual removal from users' browsers then depends on a Chrome release reaching them, which the site states takes months, with no guarantee for other browsers at all. Decide before you check this box, not after.
A header that works on your homepage can vanish on your error page
Nginx's add_header directive only attaches to responses with status 200, 201, 204, 206, 301, 302, 303, 304, 307 or 308 by default. A 404 or a 500 response is not in that list, so a site that only tested its homepage can genuinely have zero security headers on every error page. Adding the word `always` to each add_header line — add_header X-Content-Type-Options nosniff always; — is the fix, and it needs to be on every line, not just one.
One add_header in a location block can cancel headers set above it
Nginx inherits add_header directives from a parent server or http block only if the current location block has zero add_header directives of its own. Add a single add_header inside a location — for a one-off CORS header on an API route, say — and every header this tool generated at the server level for that route disappears unless you copy all of them into the same location block too.
This policy still allows inline styles, not inline scripts
script-src 'self' with no 'unsafe-inline' means an injected <script>alert(1)</script> is blocked by this policy. style-src 'self' 'unsafe-inline' means an injected style attribute or <style> block is not. That gap is deliberate in many real deployments — CSS-based data exfiltration exists but is far narrower than script injection — but it means this policy is not "fully locked down" just because CSP is checked. Closing it requires replacing 'unsafe-inline' in style-src with a per-request nonce matched to every inline style tag, the same mechanism CSP uses for scripts.
Confirm the headers actually shipped
This tool only produces text to paste; it does not check that your server sent it. After deploying, run curl -I https://yourdomain.com from a terminal and read the response headers back, or open the Network tab in browser DevTools and inspect any request's response headers. A header missing from that output after you've added it to your config almost always means either a caching layer (CDN, reverse proxy) is stripping it, or it landed in the wrong server block and was never inherited.
Limitations & Accuracy Notes
- Output is one generic header block. It does not produce Nginx, Apache, Cloudflare _headers, or Next.js headers() syntax — you translate the block into your platform's config format by hand.
- No CORS headers of any kind. Cross-origin resource sharing is a separate concern from these response headers and this tool does not generate Access-Control-* headers.
- No security presets. Every checkbox is independent; there is no single "Recommended" or "Strict" button that sets several at once.
- The Content-Security-Policy is one fixed string. There is no per-directive editor for script-src, style-src, img-src or connect-src, and style-src still permits 'unsafe-inline'.
- Permissions-Policy is hardcoded to camera=(), microphone=(), geolocation=() and has no toggle — it cannot be turned off, narrowed, or expanded to other features like payment or fullscreen.
- No Cross-Origin-Opener-Policy, Cross-Origin-Embedder-Policy, or Cross-Origin-Resource-Policy headers are offered.
- The tool cannot verify that headers actually reach a live response — a CDN, proxy, or misplaced server block can silently drop what you paste in, and only inspecting the real response (curl -I or DevTools) will catch that.
Frequently Asked Questions
Why are security HTTP headers important?
What is a Content Security Policy (CSP)?
Which security headers matter most?
Is X-Frame-Options still needed?
Why is my Content-Security-Policy breaking the site?
Does unsafe-inline defeat the purpose of CSP?
Where do these headers go?
Is my configuration sent anywhere?
References & Further Reading
- MDN — Strict-Transport-Security — Confirms max-age semantics and the 31,536,000-second minimum required for preload
- MDN — Content-Security-Policy — Directive-by-directive reference, including base-uri, object-src and the nonce mechanism
- hstspreload.org — Official submission requirements and the months-long removal process, maintained by the Chromium team
- nginx.org — Module ngx_http_headers_module — Official documentation for add_header, the always parameter, and per-block inheritance rules
- OWASP — HTTP Headers Cheat Sheet — Confirms CSP frame-ancestors supersedes X-Frame-Options and that Permissions-Policy replaced Feature-Policy