Guides Create account 🇬🇧 🇩🇪
  • Guides
  • Create account
  • Sign in
  • 🇬🇧 🇩🇪
  • Developer API

    A securityheaders.com API alternative

    One endpoint, one dimension: the security result of a scan as JSON, without walking the full report schema. Built for CI pipelines, dashboards and agency tooling that check response headers on a schedule.

    Get an API token Jump to the migration

    01 Authentication

    A bearer token per account

    Every request carries an API token as a bearer token in the Authorization header. Tokens are created and revoked on the API tokens page of your account, and a token only ever sees the scans of the account it belongs to. API access is part of the Agency plan.

    02 The endpoint

    Read the security result of a scan

    The endpoint returns the security dimension of a finished scan and nothing else. It reads what the scan stored and measures nothing of its own, so the same scan token answers the same way from the full report endpoint.

    GET /api/v1/scans/{token}/security JSON

    curl -H "Authorization: Bearer $SCAN_API_TOKEN" \ "https://scan.erseni.com/api/v1/scans/8f14e45fceea167a5a36dedd4bea2543/security?locale=en-gb"
    { "schemaVersion": 6, "token": "8f14e45fceea167a5a36dedd4bea2543", "url": "https://example.com/", "status": "finished", "resultAvailable": true, "scanErrorMessage": null, "progressStage": null, "progressPercent": 100, "security": { "dimension": "security", "measured": true, "score": 62, "band": "warn", "rank": "needs_work", "checkSummary": { "passed": 21, "violated": 9, "notChecked": 8, "notApplicable": 10, "ran": 30, "total": 48 }, "checks": [ { "key": "strict-transport-security", "state": "passed", "label": "Strict-Transport-Security", "reason": "Enforces HTTPS for every later request." } ], "findings": [ { "code": "security.missing-header.content-security-policy", "severity": "high", "riskLevel": "high", "effort": "medium", "title": "Content-Security-Policy header missing", "detail": "...", "riskStatement": "...", "remediation": "..." } ] } }

    03 Starting a scan

    Two calls, not one

    A scan runs a real browser against the page, so it is asynchronous. The first call queues it and hands back a token, the second reads the result once the status is finished. Poll the security endpoint: while the scan is still running it answers with the status and progress and a null security block.

    POST /api/v1/scans

    curl -X POST \ -H "Authorization: Bearer $SCAN_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com/"}' \ "https://scan.erseni.com/api/v1/scans"
    { "token": "8f14e45fceea167a5a36dedd4bea2543", "id": 4711, "status": "queued", "statusUrl": "/api/v1/scans/8f14e45fceea167a5a36dedd4bea2543" }

    04 Reading the answer

    What each field means

    The answer is the JSON object itself, without a wrapper around it. Nothing in the answer is a legal statement, and nothing is filled in for the sake of a tidy shape. A dimension that was never measured comes back as measured false with a null score rather than a zero.

    score

    The security score of the scan from 0 to 100, or null when the dimension was not measured. band is good, warn, poor or unknown; rank is the finer seven-step scale used in the report.

    measured

    False when the scan carries no security score. Everything else in the block may still be present, but no score stands behind it.

    checkSummary

    How many of the declared security checks passed, were violated, could not be run (notChecked) and do not apply to the site (notApplicable). ran is passed plus violated, total counts all of them. Null for a scan taken before the check ledger existed.

    checks

    One entry per check with its key, its state, a label and the reason it is checked. The list is either complete for the dimension or null: a partial list would present the checks that happen to be named as the full scope of what was tested.

    findings

    The public security findings of the scan. code is a stable fingerprint you can key on; the four texts are rendered in the requested locale.

    locale

    Optional query parameter, en-gb by default, de-de also supported. It selects the language of the labels, reasons and finding texts. Keys, codes and states never change with the locale.

    05 Errors

    What the endpoint answers when it cannot answer

    Every error carries the HTTP status and a JSON body with errorMessage at the top level; a rejected request body adds fieldErrors, keyed by field. Branch on the status code, not on the text: the wording may change, the codes do not.

    Status codes 400 Unsupported locale, or a POST body without a valid URL. The locale query parameter carries a value we do not serve; supported are en-gb and de-de, and omitting it selects en-gb. A rejected body names the field in fieldErrors. 401 Invalid or missing API token. The Authorization header is absent, malformed, or the bearer token was revoked. 403 API access requires an Agency plan. The token authenticated, but its account is not on the plan that includes API access. 404 Scan not found. The scan token does not exist, or it belongs to another account. Both cases answer alike on purpose, so that a token cannot be used to probe which scans exist elsewhere. 429 Rate limit exceeded, counted per account and calling IP address, per minute. The answer usually carries a Retry-After header with the seconds to wait; wait that long rather than retrying at once, and fall back to a minute when the header is absent.

    06 Migration

    Coming from the securityheaders.com API

    Snyk is retiring the securityheaders.com API in April 2026. The mapping below is deliberately literal: where we mean something different, it says so instead of bending our answer into a shape that would read as compatible and quietly report something else.

    Field mapping grade No equivalent. We return score from 0 to 100 with band and rank. We do not emit a letter grade, because ours would be computed from a different set of checks and an A would not mean their A. missing headers checks entries whose state is violated, plus a findings entry with a stable code. A header we could not read at all is notChecked, not violated. raw headers Not returned by this endpoint. It answers with the risk description of each finding rather than the observed response of a foreign site. warnings The checks information-disclosure, x-xss-protection and cors-configuration, each with its own finding. q=<url> POST /api/v1/scans with a JSON body {"url": "https://example.com/"}. The response carries the scan token you then read. hide=on No equivalent. Every finished scan appears on the public /scans list with its URL, its creation time and its token. followRedirects Always followed. Note that a browser upgrades HTTP to HTTPS internally on an HSTS-preloaded domain, so an empty redirect chain is not proof that a site does not redirect. synchronous answer Asynchronous. POST queues the scan and returns a token, GET reads the result once the status is finished.

    07 Beyond the headers

    What we check in addition

    The security dimension is wider than a header list. These checks come with the same call and appear in checks and findings alongside the header ones.

    • TLS certificate and transport: validity, hostname match, trust chain, key strength and signature algorithm, plus which protocol versions the server actually offers, including legacy TLS 1.0 and 1.1.
    • HSTS beyond presence: whether the policy is effective and whether it qualifies for the preload list, rather than only whether the header exists.
    • CSP delivery and strength: the enforcing header, the report-only header and a CSP delivered as a meta element, and how strong the directives actually are.
    • Cookie attributes: Secure, HttpOnly and SameSite, including the insecure SameSite=None case.
    • DNS and mail security: SPF, DMARC, DNSSEC, CAA, MTA-STS and TLS-RPT.
    • security.txt, subresource integrity, mixed content and the HTTPS redirect.

    08 Limits

    What we deliberately do not do

    The honest half of the comparison. None of these is an oversight, and each one is a decision we would rather state than have you discover in production.

    • No letter grade, for the reason given in the mapping above.
    • This endpoint answers with findings, not with the evidence payload. The report itself shows the evidence to everyone.
    • No active probing of foreign infrastructure: no port scans, no subdomain enumeration, no admin panel or backup discovery.
    • OCSP stapling is not checked. PHP does not hand out the stapled response, so the check would be a claim rather than a measurement.
    • A header value longer than 512 characters is stored truncated and is reported as notChecked. A long, correct Content-Security-Policy must not come back as a weak one.
    • Rate limits apply per account and calling IP address, counted per minute, and a scan is queued rather than run on the spot.

    09 Plan

    API access comes with Agency

    The API is part of the Agency plan and allows 60 requests per minute, counted per account and calling IP address. There is no free API quota; scanning in the browser stays free.

    Compare the plans

    Ready to wire it up?

    Create a token in your account, run one scan by hand to see the shape of the answer, then point your pipeline at it.

    Manage API tokens See the plans
    Recent scans Guides Local leagues Pricing Methodology For hosters API Data protection Imprint Accessibility Terms Cancel contracts here © 2026 Erseni