Each site is handled as POST /scans would handle it (a recent result, a running scan or a new scan), in the order you sent them. A site refused by your credits, the daily limits or our rules gets an error in its place, and the other sites go ahead. Read each scan at its links.self.
Credits
Each site is charged as POST /scans charges it: its checks’ scan price for a new scan, or their stored price for a recent result or a running scan. Each scan’s credits are counted before the next site.
Request
curl -X POST "https://api.checkanysite.com/v1/scans/batch" \
-H "Authorization: Bearer $CHECKANYSITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domains": ["example.com", "example.org"], "checks": ["ai"]}'from checkanysite import CheckAnySite
client = CheckAnySite() # Reads the key from CHECKANYSITE_API_KEY.
batch = client.scans.batch(["example.com", "example.org"], checks=["ai"])const url = 'https://api.checkanysite.com/v1/scans/batch';
const response = await fetch(url, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHECKANYSITE_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
domains: ['example.com', 'example.org'],
checks: ['ai'],
}),
});
const batch = await response.json();Parameters
Idempotency-KeystringheaderA unique value for this request, such as a UUID. A retry with the same key within 24 hours returns the first response (
Idempotent-Replayed: true), and never starts a second scan or charges twice. The same key with a different request returnsidempotency_key_reused.
Request body
JSON, with Content-Type: application/json. A field we don’t know is refused, so a typo never passes silently.
domainsarray of stringrequiredbody1 to 10 domains, or URLs whose host is used. A domain sent twice is answered once, in its first place.
checksarray of one of: ai, readiness, popularity, tech, dns, trust, summary, historybodyThe checks to answer for each domain; left out, every check.
againbooleanbodyWith the
readinesscheck: ask it again, as on POST /scans.Default:
false
Response
| Status | Body | When |
|---|---|---|
| 200 OK | ScanBatch | Every scan is complete, from recent results. |
| 202 Accepted | ScanBatch | Some scans are running. Read each at its links.self. |
{
"data": [
{
"id": "0b5a7a6e-1f7e-4d7c-9a4e-2f0d8b1c6a11",
"domain": "wikipedia.org",
"checks": [
"ai"
],
"status": "queued",
"createdAt": "2026-11-10T09:30:00.000Z",
"finishedAt": null,
"complete": false,
"failure": null,
"result": null,
"links": {
"self": "https://api.checkanysite.com/v1/scans/0b5a7a6e-1f7e-4d7c-9a4e-2f0d8b1c6a11?checks=ai",
"result": "https://checkanysite.com/site/wikipedia.org?focus=ai"
}
},
{
"input": "localhost",
"domain": null,
"error": {
"code": "invalid_domain",
"message": "That’s not a public website address."
}
}
]
}dataarray of valueOne item per domain: its scan (poll each
links.self), or anerror.
Errors
| Status | Code | What happened |
|---|---|---|
| 400 | invalid_json | Invalid JSON |
| 400 | invalid_parameter | Invalid parameter |
| 415 | unsupported_media_type | Unsupported content type |
| 413 | request_too_large | Body too large |
| 401 | missing_api_key | No API key |
| 401 | invalid_api_key | Unknown API key |
| 401 | revoked_api_key | Revoked API key |
| 401 | expired_api_key | Expired API key |
| 429 | rate_limited | Too many requests |
| 422 | idempotency_key_reused | Idempotency key reused |
| 409 | idempotency_key_in_use | Request in progress |
| 500 | internal_error | Internal error |