Every web developer has had this moment: you check your app's response headers, see a wall of Content-Type and Cache-Control, and wonder — is this actually secure? Which headers am I missing? What does Permissions-Policy do again?
I built HTTP Header Analyzer to answer those questions instantly. Paste any set of HTTP response headers and get a security score, missing header warnings, cache analysis, and recommended values — all in the browser, zero dependencies, zero server.
What it does
Paste headers in Key: Value format (one per line) and click Analyze Headers. The tool:
- Scores security headers from 0–100 with a letter grade (A+ → F)
- Flags missing critical headers with recommended values
- Categorizes all headers — Security / Cache / Content / Other
- Evaluates each header value — good, warn, or bad — with a plain-English explanation
- Supports sample presets for Nginx, Express, Apache, and a "Minimal (insecure)" set
The security scoring model
Six headers are required; three more earn bonus points:
| Header | Points |
|---|---|
| Content-Security-Policy | 20 |
| Strict-Transport-Security | 15 |
| X-Frame-Options | 10 |
| X-Content-Type-Options | 10 |
| Referrer-Policy | 10 |
| Permissions-Policy | 10 |
| Cross-Origin-Embedder-Policy | +5 bonus |
| Cross-Origin-Opener-Policy | +5 bonus |
| Cross-Origin-Resource-Policy | +5 bonus |
A "warn" rating (e.g. HSTS with max-age under a year, or CSP with unsafe-inline) earns half points. The score caps at 100.
A+ ≥ 90 A ≥ 80 B ≥ 70 C ≥ 60 D ≥ 40 F < 40
Nuanced per-header evaluation
Rather than just checking "present or absent," the tool evaluates the value:
HSTS
Strict-Transport-Security: max-age=86400
→ warn: max-age should be at least 31536000 (1 year)
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
→ good: Good configuration.
CSP
Content-Security-Policy: default-src 'self'; script-src 'unsafe-inline'
→ warn: Contains unsafe-inline. Consider removing for stronger XSS protection.
Content-Security-Policy: default-src 'self'; object-src 'none'
→ good: Policy present without unsafe directives.
Set-Cookie
Set-Cookie: session=abc123; path=/
→ bad: Missing HttpOnly; Missing Secure; Missing SameSite.
Set-Cookie: session=abc123; HttpOnly; Secure; SameSite=Strict
→ good: All security attributes present.
Server / X-Powered-By — version disclosure is flagged:
Server: nginx/1.24.0
→ warn: Version disclosed. Consider removing version number.
Server: nginx
→ good: No version disclosed.
Cache-Control — directives are decoded into plain English:
Cache-Control: public, max-age=31536000, immutable
→ public | max-age=31536000 | immutable: resource will not change
Sample presets
Three real-world samples are one click away:
Nginx — full security headers, Brotli, ETag, HSTS with preload
Express — X-Powered-By leak, weak HSTS, CORS origin, signed cookie
Apache — version disclosure, no security headers, basic cache
Minimal (insecure) — the bad old days: PHPSESSID without HttpOnly, PHP version disclosed
Load "Minimal (insecure)" and you get an F-grade report with every critical header flagged as missing. Load "Nginx" and you score 75 with specific advice on adding COEP/COOP/CORP to push toward A+.
Implementation
Zero dependencies. Pure HTML + CSS + vanilla JavaScript in a single file.
The parser handles:
- HTTP status lines (skipped correctly)
- Multiple
Set-Cookieheaders (collected as an array) - Values containing colons (
Location: https://example.com:443/path) - Case-insensitive header name matching
function parseHeaders(raw) {
const headers = {};
for (const line of raw.split("\n")) {
const trimmed = line.trim();
if (!trimmed || /^HTTP\/\d/i.test(trimmed)) continue;
const idx = trimmed.indexOf(":");
if (idx === -1) continue;
const key = trimmed.slice(0, idx).trim().toLowerCase();
const value = trimmed.slice(idx + 1).trim();
if (key === "set-cookie") {
if (!headers[key]) headers[key] = [];
headers[key].push({ name: trimmed.slice(0, idx).trim(), value });
} else {
headers[key] = { name: trimmed.slice(0, idx).trim(), value };
}
}
return headers;
}
Scoring:
function computeScore(parsedHeaders) {
let score = 0;
for (const key of REQUIRED_SECURITY_HEADERS) {
const hdr = parsedHeaders[key];
if (!hdr) continue;
const ev = HEADER_DB[key].evaluate(hdr.value);
if (ev.rating === "good") score += HEADER_DB[key].points;
else if (ev.rating === "warn") score += Math.floor(HEADER_DB[key].points * 0.5);
}
// bonus for COEP/COOP/CORP
return Math.min(100, score + bonusScore);
}
147 tests, no framework
Tests run in Node.js with just the built-in assert module.
$ node test/test.js
Results: 147 passed, 0 failed
Total: 147 tests
Test coverage includes:
- Parser edge cases (status line skipping, colon-in-value, multiple Set-Cookie)
- Each header's evaluation logic across all rating outcomes
- Score computation (correct points, half-points for warn, bonus capping at 100)
- Grade thresholds (A+ / A / B / C / D / F)
- Utility functions (formatSeconds, formatBytes)
- Integration scenarios (nginx sample, minimal insecure, full perfect score)
Try it
Live tool: https://devnestio.pages.dev/http-header-analyzer/
All tools: https://devnestio.pages.dev/
The tool is part of devnestio — a collection of browser-only developer utilities with no login, no tracking, and no server round-trips.
Built with vanilla JS. 147 tests. Zero dependencies.
Top comments (0)