Security Headers / response analyzer
Analyse HTTP security headers
Get a graded assessment of any HTTP response: what is missing, what an attacker gains
from each gap, which headers are leaking your software versions and internal
infrastructure, and the exact configuration line to fix it. Two ways in —
paste a response from Burp, curl or DevTools, or
enter a URL and have the headers retrieved for you. Paste mode makes
no request at all, so it reaches internal and staging hosts that public scanners
cannot, and the headers never leave this tab. URL mode works against any public host
and can follow the redirect chain to the final document.
Response headers
step 1http:// or https:// only
Use {url} where the target should be substituted.
Without it, ?url= is appended. Your endpoint may return either a
raw HTTP response or a JSON header map. Source below.
How URL mode works, and what it costs. A browser cannot read another origin's response headers — that is the same-origin policy, not a limitation of this tool — so the request is made by a service on your behalf and the headers are handed back.
The default public API sees every URL you submit, and the target sees that service's IP rather than yours. Switch to your own endpoint to keep the URLs private. Internal and staging hosts cannot be reached this way at all — use paste mode for those, which makes no network request whatsoever.
Only test hosts you are authorized to assess.
Run your own endpoint — Cloudflare Worker source
Free tier covers 100,000 requests a day. Deploy at
workers.cloudflare.com,
paste this in, and put the resulting
*.workers.dev URL in the field above. Then no third party sees
what you are testing.
export default {
async fetch(request) {
const CORS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, OPTIONS',
'Content-Type': 'text/plain; charset=utf-8'
};
if (request.method === 'OPTIONS') return new Response(null, { headers: CORS });
const target = new URL(request.url).searchParams.get('url');
if (!target) return new Response('error: missing url parameter', { status: 400, headers: CORS });
let u;
try { u = new URL(target); } catch { return new Response('error: invalid url', { status: 400, headers: CORS }); }
if (u.protocol !== 'http:' && u.protocol !== 'https:') {
return new Response('error: only http and https', { status: 400, headers: CORS });
}
// Refuse private and link-local space so this cannot be used to reach
// internal services or a cloud metadata endpoint.
if (/^(localhost|127\.|10\.|192\.168\.|169\.254\.|::1|\[?::1\]?)/i.test(u.hostname) ||
/^172\.(1[6-9]|2\d|3[01])\./.test(u.hostname)) {
return new Response('error: private address refused', { status: 403, headers: CORS });
}
let res;
try {
res = await fetch(u.href, { method: 'GET', redirect: 'manual' });
} catch (e) {
return new Response('error: ' + e.message, { status: 502, headers: CORS });
}
// Emit a raw HTTP response so the analyzer parses it like a pasted one.
let out = `HTTP/1.1 ${res.status} ${res.statusText}\n`;
for (const [k, v] of res.headers) out += `${k}: ${v}\n`;
return new Response(out, { headers: CORS });
}
};
redirect: 'manual' matters — the analyzer
follows the chain itself so it can show you each hop and score the final
document. The private-address check matters too: without it the endpoint is
an SSRF proxy pointed at your own infrastructure.
Run one of these, then switch to Paste response
Accepts Burp Suite (Repeater or Proxy
response, request block included — it is skipped automatically),
curl -I, curl -i, curl -v (the
< prefixes are stripped), raw HTTP responses, ZAP and Fiddler
output, and DevTools › Network › Copy response headers. HTTP/2
pseudo-headers, obsolete line folding, response bodies and
curl -L redirect chains are all handled.
How to capture the headers
Test the authenticated response too. Headers frequently differ between the marketing homepage and the application behind login, and the authenticated response is the one that matters.
Paste response headers above, then press Analyze.
Findings
Generated configuration
all fixes, one blockEvery fix for the findings above, combined into one copy-paste block for your platform.
Reference
Common questions, answered directly.
Which HTTP security headers should every site set?
At minimum, seven: Strict-Transport-Security,
Content-Security-Policy, X-Frame-Options: deny,
X-Content-Type-Options: nosniff, Referrer-Policy: no-referrer,
a Permissions-Policy that switches off unused features, and
Cross-Origin-Opener-Policy: same-origin. Then remove every header that
discloses software or versions.
Strict-Transport-Security: max-age=63072000; includeSubDomains Content-Security-Policy: default-src 'self'; form-action 'self'; base-uri 'none'; object-src 'none'; frame-ancestors 'none' X-Frame-Options: deny X-Content-Type-Options: nosniff Referrer-Policy: no-referrer Cross-Origin-Opener-Policy: same-origin Cross-Origin-Resource-Policy: same-origin X-Permitted-Cross-Domain-Policies: none Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=(), usb=(), interest-cohort=()
Values per the OWASP Secure Headers Project.
Is X-XSS-Protection still needed?
No. The browser feature it controlled no longer exists anywhere. Chrome removed the XSS Auditor in 2019, Edge dropped it when it moved to Chromium, and Firefox never implemented it. The filter was also itself abusable, as a way to selectively disable legitimate scripts on a page.
OWASP lists it as deprecated and recommends removal. If a compliance scanner
insists the header be present, X-XSS-Protection: 0 is the only
defensible value — and this analyzer will not penalise that.
What HSTS max-age does preload require?
At least 31536000 seconds (one year), plus
includeSubDomains and preload. Anything under
15552000 (six months) is ineligible.
Do not add preload until every subdomain can serve HTTPS.
The hstspreload.org team
explicitly asks that tools not enable it by default, because removal is slow and
painful — operators regularly preload themselves into an outage.
Why does a CSP need base-uri?
Because without it, an attacker who can inject markup adds
<base href="https://attacker.example/"> and every
relative script URL on the page now resolves to their origin. Your
script-src 'self' still passes, since the script appears same-origin
to the policy — but the bytes come from the attacker.
base-uri 'none' closes it. It is the most commonly missed directive
in otherwise well-built policies, which is why this analyzer flags it specifically.
Can I check headers on an internal or staging site?
Yes — that is the main reason this tool is paste-based.
Public scanners like securityheaders.com and Mozilla Observatory must reach the
host themselves, so they are useless for
staging.internal.corp, anything behind a VPN, or a host that only
answers with the right Host header.
Run curl -I from wherever you have access and paste the output.
Everything is analysed locally; no request is made and nothing is uploaded.
How is the grade calculated?
Start at 100. Deduct per finding by severity — 25 for a critical absence,
15 high, 8 medium, 3 low; a header that is present but weak costs about 60% of the
absent penalty; information-disclosure headers cost 2 each up to a cap of 14;
deprecated headers 4 each; cookie flag failures 5 each up to 15. Bonuses of 5 apply
only once the score is already 90 or above, for preload-eligible HSTS and for a CSP
with no unsafe-* that also sets base-uri.
Grade boundaries follow the published Mozilla HTTP Observatory scale so a grade here is comparable with one from there. Every deduction is itemised in the sidebar — no hidden arithmetic.
Which headers leak information, and why does it matter?
This analyzer checks all 86 headers on the OWASP information-disclosure list, grouped into five classes: software and version disclosure, internal infrastructure, tracing and correlation identifiers, source and path disclosure, and monitoring agents.
Most public checkers flag only Server and X-Powered-By.
In practice the interesting ones survive into production far more often:
X-Envoy-Original-Dst-Host hands over internal addressing,
X-CalculatedBETarget names the Exchange backend,
X-Kong-Upstream-Latency confirms the gateway,
SourceMap points at unminified source, and the Datadog and B3 trace
headers expose correlation identifiers.
None of these is exploitable alone. Together they remove the reconnaissance phase — an attacker learns the exact stack, version and topology without sending a single unusual request.