Public API

Get a domain check as JSON. No key needed for light use (120 requests/hour per IP). Shared egress (Sheets, GitHub Actions) can use an optional account API key. Preferred path is /api/v1/check. Aliases /api/porcelain and /api/public/check stay stable.

Endpoint

https://httpsornot.com/api/v1/check?domain=<domain>

Replace <domain> with the hostname (e.g. example.com). Scheme and path are stripped.

CI policy (fail the PR)

Optional query params. When any are set and the check fails the policy, the API returns HTTP 422 with the full JSON plus policyFailures — so curl -f exits non-zero in GitHub Actions.

  • minGrade — composite sslGrade.grade (A+, A, A-, B+, B, C, F)
  • headersMinGrade — headers-only securityHeaders.grade (A+, A, B, C, D, F)
  • requireHsts=true — require HSTS enabled

Bot protection while a policy is requested also returns 422 (fail closed) — we do not invent a grade. Details: accuracy pledge.

curl -fsS "https://httpsornot.com/api/v1/check?domain=example.com&headersMinGrade=B&requireHsts=true"

SecurityHeaders.com API migration

The programmatic api.securityheaders.com API was discontinued in April 2026. Use headersMinGrade on /api/v1/check for a headers-only CI gate (HTTP 422 on fail). Full field map and before/after curl: SecurityHeaders alternative.

Copy-paste workflow (set DOMAIN):

name: Security headers (httpsornot)
on:
  push:
  schedule:
    - cron: "0 8 * * 1"   # weekly smoke

jobs:
  headers:
    runs-on: ubuntu-latest
    steps:
      - name: Fail if headers grade below B
        env:
          DOMAIN: example.com   # ← change this
        run: |
          set -euo pipefail
          # One check per job — public API is 120 req/hour/IP; GHA runners share egress IPs.
          # Optional: create a free account, Dashboard → API keys, then:
          #   -H "X-API-Key: hsn_…"
          # headersMinGrade: A+|A|B|C|D|F (not sslGrade A-/B+).
          # Policy fail / bot block → HTTP 422. Our rate limit → 429 (different!).
          curl -fsS \
            "https://httpsornot.com/api/v1/check?domain=${DOMAIN}&headersMinGrade=B" \
            -o result.json
          jq '{ grade: .securityHeaders.grade, policyOk, gradingVersion: .sslGrade.gradingVersion }' result.json
          # Optional composite HTTPS gate:
          # curl -fsS "https://httpsornot.com/api/v1/check?domain=${DOMAIN}&minGrade=A-&requireHsts=true"

CI only runs on push. Monitoring emails you when a deploy drops CSP or HSTS later.

Start monitoring

Rate limit

Without a key: 120 requests per hour per IP. Responses include RateLimit-* headers. Over limit → 429 with a Retry-After hint when available. For abuse prevention we may retain the caller IP, domain, and outcome for up to 90 days; see Privacy.

  • CI / GitHub Actions / Google Sheets: runners and UrlFetch often share egress IPs. Prefer one check per CI job, or create an API key so usage is counted against your account instead of that shared IP.
  • Do not poll in a tight loop; cache the JSON artifact in the workflow if several steps need it.
  • Policy failure is 422; rate limit is 429 — treat them differently in scripts.

API keys

Sign in, open Dashboard → API keys, and create a key. We store only a hash; the full secret is shown once. Send it as X-API-Key or Authorization: Bearer (not as a query parameter).

curl -fsS -H "X-API-Key: hsn_…" \
  "https://httpsornot.com/api/v1/check?domain=example.com"
  • Keyed requests skip the per-IP hourly cap and use a per-key burst (600/hour).
  • All keys on one account share one monthly quota, set by your plan: Free 10,000 · Solo 100,000 · Agency 500,000 checks per UTC calendar month. Creating more keys does not multiply the quota.
  • Quota headers: X-Quota-Limit, X-Quota-Remaining, X-Quota-Reset.
  • Key burst headers use X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. Both limits are enforced in PostgreSQL across backend replicas.
  • One valid domain request counts as one check, including cache hits, unreachable targets, and CI policy responses.
  • Keys apply only to GET /api/v1/check (and its porcelain aliases). They do not authenticate the homepage bulk form or POST /check-bulk.
  • Upgrading your monitoring plan (Solo / Agency) raises this API quota automatically. An admin can also pin a custom quota per account.
Sign in to create a key

OpenAPI specification

Machine-readable contract (paths, CI policy params, 422 shape). Import into Postman, Insomnia, or codegen.

Example

curl "https://httpsornot.com/api/v1/check?domain=example.com"

Response includes sslGrade.gradingVersion, securityHeaders, certificate, redirects, and more. Grading methodology. Migrating from SecurityHeaders.com API? Field map + GitHub Actions.

CORS

Access-Control-Allow-Origin: * is set for browser scripts and other origins.

For bulk checks or higher limits, use the main tool on the homepage.