Scan API
The scanner,
without the browser.
Two calls: start a scan, then poll it until it is done. No key and no account — these are the same public endpoints this site's own front page uses, under the same five-scans-an-hour limit.
Start a scan
Returns 201 with a scan id, immediately. The scan itself runs in the background, so this call does not wait for it.
curl -s -X POST https://scs-health.onrender.com/api/scans \
-H 'Content-Type: application/json' \
-d '{"url":"https://example.com"}'
{"id":"5f3c…","url":"https://example.com","status":"running","score":null, … }Read the report
Poll until status is completed or failed. The site polls every two seconds; a scan usually finishes inside forty.
curl -s https://scs-health.onrender.com/api/scans/5f3c…
{
"status": "completed",
"score": 72,
"unreachable": false,
"summary": { "checksRun": 71, "passed": 62, "failed": 9 },
"cappedBy": "critical",
"categories": [
{ "category": "security", "score": 40, "checksRun": 12, "passed": 9, "failed": 3,
"findings": [
{ "severity": "critical", "title": "SSL certificate has expired",
"detail": "Expired 2026-07-02", "remediation": { … } }
] }
],
"aiReadiness": { … },
"crawl": { "status": "not_requested", "pagesScanned": null }
}Three things worth knowing before you build on it
A report is delivered exactly once
GET for the same id returns 410 Gone. Keep the first response — this is the same deliver-once behaviour the browser gets, not an API restriction. Responses are sent no-store for the same reason.No score is different from a low score
score is null and unreachable is true. Nothing about the site was measured, so treating a missing score as zero would be wrong — a site behind a bot wall is not a site that failed.Five scans an hour, per IP
Retry-After. If the service has been idle the first call can take up to a minute to answer; later ones are immediate.Using it in CI
There is no official action or CLI yet. The shape below is what people write by hand — fail the build when the score drops under a threshold you pick.
id=$(curl -s -X POST https://scs-health.onrender.com/api/scans \
-H 'Content-Type: application/json' \
-d "{\"url\":\"$SITE_URL\"}" | jq -r .id)
# poll until it settles
until [ "$(curl -s $BASE/api/scans/$id | jq -r .status)" != "running" ]; do sleep 2; done
# NOTE: the report is erased once read, so capture it in one call
report=$(curl -s https://scs-health.onrender.com/api/scans/$id)
echo "$report" | jq '.summary, .score'
test "$(echo "$report" | jq -r '.score // 0')" -ge 80Scheduled re-scans, alerting and a stable versioned API are what the paid tiers on pricing are being built around. If you are considering it for a pipeline, say so — that is the feedback that decides what gets built first.
Try it against your own site first.
The browser version runs the same scan and shows the same findings.
Run a scan