API Documentation

HeaderTest API

A free, open API for scanning a site's HTTP security headers and Content Security Policy. No sign-up, no API key — built to be called by scripts and AI agents.

For AI agents

Base URL https://headertest.com/api. No authentication and no rate limiting. Scanning is asynchronous:

  1. POST /api/analyze → returns a job_id immediately.
  2. Poll GET /api/jobs/{job_id} every ~2s until status is completed or failed (usually a few seconds).

Machine-readable summary for agents: /llms.txt.

POST/api/analyze

Start a scan. Body: { "url": "https://example.com", "timeout"?: 60 } (timeout in seconds, 10–120, default 60; scheme is added if omitted).

request
curl -s -X POST https://headertest.com/api/analyze \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com"}'
response
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "accepted",
  "message": "Analysis started. Check job status for results."
}

GET/api/jobs/{job_id}

Poll a job. status ∈ pending | running | completed | failed. When complete, results holds the full report.

request
curl -s https://headertest.com/api/jobs/550e8400-e29b-41d4-a716-446655440000
response (completed)
{
  "status": "completed",
  "completed_at": "2026-07-18T18:00:05+00:00",
  "results": {
    "url": "https://example.com",
    "risk_score": 35,
    "letter_grade": "B",
    "has_csp": true,
    "security_headers": { /* per-header checks */ },
    "issues": [ /* findings */ ],
    "recommendations": [ /* fixes */ ],
    "headers_present": 6,
    "headers_missing": 3
  }
}

GET/api/domains/{domain}/history

Up to the 30 most recent scans for a domain, with the risk-score change vs. the previous scan. 404 if the domain has never been scanned.

curl -s https://headertest.com/api/domains/example.com/history

GET/api/stats

Totals: { "total_scans": int, "total_domains": int }.

curl -s https://headertest.com/api/stats

Grade

security_score = 100 - risk_score, then banded: 90+ A+, 80–89 A, 70–79 B, 60–69 C, 50–59 D, 40–49 D-, else F. Lower risk_score is better.

End-to-end example

bash
JOB=$(curl -s -X POST https://headertest.com/api/analyze \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://example.com"}' | jq -r .job_id)

for i in $(seq 1 60); do
  RESP=$(curl -s "https://headertest.com/api/jobs/$JOB")
  STATUS=$(echo "$RESP" | jq -r .status)
  [ "$STATUS" = completed ] || [ "$STATUS" = failed ] && break
  sleep 2
done
echo "$RESP" | jq '{grade:.results.letter_grade, risk:.results.risk_score}'

Errors

CodeMeaning
400Missing/invalid url, bad job UUID, or bad domain
404Domain/job not found
500Backend error
503Too many pending scans queued — retry shortly

Embeddable badge

Every domain has a live SVG grade badge at https://headertest.com/api/badge/{domain}. Link it back to the domain's report:

html
<a href="https://headertest.com/results/example.com">
  <img src="https://headertest.com/api/badge/example.com" alt="HeaderTest security grade" />
</a>

Infrastructure & exposure data

HeaderTest covers HTTP response headers. For the layer underneath — IPs, open ports, known CVEs, hosting network, DNS and WHOIS — use our sister project OSN, a free internet exposure search. Same deal: no key required.

bash
# Open ports, CVEs, hosting, DNS and WHOIS for a domain (OSN, no key)
curl -s https://beta.osn.lt/api/v1/domain/example.com | jq '{hosts, whois}'

Try it now

No key required — scan any site from the homepage or straight from the API.

Scan Now - Free
API Documentation — Free Open Security Header API | HeaderTest