Every web developer knows they should set proper security headers like Content-Security-Policy (CSP), HSTS, and X-Frame-Options. But knowing which headers your site is missing, and exactly what values to set them to, is harder than it sounds.
In this tutorial I'll walk through a practical way to check a URL's HTTP security response headers — lightweight, OWASP-aligned on the assessment side, and fast enough to run as part of a pre-deployment sanity check or a CI step.
What Are HTTP Security Headers and Why Do They Matter?
HTTP security headers are directives your server sends alongside every response. They tell the browser how to behave — which scripts to trust, whether the page may be framed, whether to enforce HTTPS, how to handle cross-origin requests.
The OWASP Secure Headers Project tracks the main ones. A misconfigured or missing header is one of the most common (and cheapest to fix) security gaps in production web apps:
- Content-Security-Policy (CSP) — controls which scripts, styles, and fonts can load
- Strict-Transport-Security (HSTS) — forces HTTPS connections
- X-Frame-Options — prevents clickjacking
- X-Content-Type-Options — blocks MIME-sniffing
- Referrer-Policy — controls what referrer data is sent
- Permissions-Policy — restricts browser API access
- Cross-Origin-Opener-Policy (COOP) — isolates your window from cross-origin ones
- Cross-Origin-Resource-Policy (CORP) — restricts resource sharing
- Cross-Origin-Embedder-Policy (COEP) — requirements for cross-origin resources
That's the nine header assessments the auditor performs, plus a tenth check: whether the URL is actually served over HTTPS.
The Approach: One GET Request, No Crawling
The tool does a single, polite GET request per URL. It evaluates each response header against OWASP-baseline criteria and produces a 0-100 posture score with a letter grade, plus a prioritized fix list.
There's no crawling, no JavaScript rendering, no browser overhead, and nothing to install on the site being tested. A two-URL audit on the current build finished in about 2.6 seconds (build 0.1.14, measured 2026-09-23).
Here's a real dataset row — the score for https://example.com, measured on build 0.1.14:
{
"url": "https://example.com",
"http_status": 200,
"posture_score": 34,
"posture_grade": "F",
"issue_count": 9,
"https_enabled": true,
"top_fix": "Add: Content-Security-Policy: default-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'"
}
The same run scored https://github.com 75 (C) with 5 issues — all low severity, because GitHub already sets CSP, HSTS with a max-age of 31536000 (plus includeSubDomains and preload), X-Frame-Options, X-Content-Type-Options and Referrer-Policy. What it is missing is Permissions-Policy, COOP, CORP and COEP. That contrast between a hardened site and a bare one is the whole point of a numeric score.
Running the Audit
You can use the pre-built tool — HTTP Security Headers & OWASP Posture Auditor on the Apify Store — or port the assessment logic into your own pipeline:
- Go to https://apify.com/gp005/security-headers-auditor
- Enter one or more URLs in the input field (
{"urls": ["https://example.com"]}— a bare host is upgraded tohttps://) - Hit Run
Results arrive in the dataset within seconds. You get one row per URL: the score, the grade, the issue count, the top fix, the full issues array, and a per-header field (hsts, csp, x_frame_options, x_content_type_options, referrer_policy, permissions_policy, coop, corp, coep) with the raw value and the assessment.
Two optional inputs are worth knowing about: timeoutSecs (3-60, default 15) and verifyToken, which pairs with a <meta name="headers-audit-verify" content="TOKEN"> tag on your own site so a run can confirm it audited a domain you control.
Understanding the Score
The score starts at 100 and deducts per problem:
| Header | Deduction when missing | Deduction when present but weak |
|---|---|---|
| Content-Security-Policy | −20 | −12 |
| Strict-Transport-Security | −15 | −9 |
| X-Frame-Options | −8 | −5 |
| X-Content-Type-Options | −6 | −4 |
| Referrer-Policy | −4 | −2 |
| Permissions-Policy | −4 | −2 |
| COOP / CORP / COEP | −3 each | −2 each |
"Present but weak" means the header exists but does not do much: a CSP containing * or unsafe-inline, or an HSTS max-age under six months. A site not served over HTTPS loses 25 points and gets a critical issue at the top of the list.
The resulting grade bands:
| Grade | Posture score | Meaning |
|---|---|---|
| A | 90–100 | All critical headers present with restrictive values |
| B | 80–89 | Minor gaps only |
| C | 70–79 | Several headers weak or missing |
| D | 50–69 | Multiple critical gaps |
| F | 0–49 | Most or all headers missing |
What It Costs
This is a paid actor on the Apify Store, priced per event, so the honest answer is a formula rather than "free":
-
actor-start— $0.01 per run -
url-audited— $0.02 per URL fetched and scored -
issue-flagged— $0.01 per issue flagged, capped at 8 per URL
A 10-URL audit at an average of four issues per site is $0.01 + $0.20 + $0.40 = $0.61. A 100-URL audit by the same maths is $6.01. Because issue events are capped, a badly broken site still costs at most about $0.10 to audit. Apify plan tiers discount every event by 10–50% (BRONZE −10% up to DIAMOND −50%).
Integrating into Your Workflow
The auditor is designed to be composable:
- CI/CD pipeline — call the Apify API from GitHub Actions or GitLab CI and fail the build when a staging URL drops below your threshold
- Pre-launch checklist — run it alongside your existing security review
- Client onboarding or reporting — show a quantified posture score instead of a vague "you should fix headers"
- Compliance groundwork — header posture is evidence a reviewer will ask about during SOC 2 or ISO 27001 preparation
Because the output is JSON, the score is machine-checkable. The posture_score field is the one to gate on; issues[].severity tells you whether a regression is critical or cosmetic.
Frequently Asked Questions
How many headers does the auditor check?
Nine header assessments — CSP, HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, Permissions-Policy, COOP, CORP, COEP — plus one HTTPS-detection check, for ten checks per URL.
Does it support batch scanning of multiple URLs?
Yes. Pass hundreds of URLs in a single run; each is fetched and scored independently, sequentially and politely.
Can I use this in automated CI/CD?
Yes. The Apify API returns JSON, so you can call it from any build pipeline and parse the results programmatically.
Is JavaScript rendering or crawling involved?
No. A single HTTP GET request per URL; the audit inspects response headers only. No browser, no JS execution, no page load.
Does the scan modify or slow down the target site?
No. It's read-only — one polite GET per URL. It does not crawl beyond the URLs you supply.
What can't it see?
It sees only the policies the server declares. It cannot detect whether a CSP actually holds at runtime (that needs script hashes and real page loads), and it does not discover subresources that may have different header configurations.
Summary
HTTP security headers are one of the highest-ROI security improvements you can make for any web application, and most of the work is a copy-paste of the right header value. This auditor tells you which headers are missing, which are technically present but weak, and exactly what to set — as a JSON row you can gate a pipeline on or hand to a client.
Top comments (0)