Look up many sites
POST /v1/sites/batch looks up 1 to 50 sites in our stored results. Send the domains or URLs in domains, and optionally checks and maxAgeDays, which work as they do for GET /v1/sites/{domain}. The API returns 200 straight away and never starts a scan:
curl -X POST https://api.checkanysite.com/v1/sites/batch \
-H "Authorization: Bearer $CHECKANYSITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domains": ["stripe.com", "lovable.dev"], "checks": ["ai"]}'from checkanysite import CheckAnySite
client = CheckAnySite() # Reads the key from CHECKANYSITE_API_KEY.
batch = client.sites.batch(["stripe.com", "lovable.dev"], checks=["ai"])
for item in batch.data:
if item.result:
print(f"{item.domain}: {item.result.ai.level}")
else:
print(f"{item.input}: {item.error.message}"){
"data": [
{
"input": "wikipedia.org",
"domain": "wikipedia.org",
"result": {
"domain": "wikipedia.org",
"checks": [
"ai"
],
"scanId": "0b5a7a6e-1f7e-4d7c-9a4e-2f0d8b1c6a11",
"scannedAt": "2026-11-10T09:30:06.000Z",
"complete": true,
"pending": [],
"limited": null,
"finalUrl": "https://www.wikipedia.org/",
"resultUrl": "https://checkanysite.com/site/wikipedia.org?focus=ai",
"versions": {
"signatures": "0.6.1",
"score": "1.1"
},
"ai": {
"level": "none",
"builders": [],
"patterns": []
},
"readiness": null,
"popularity": null,
"tech": null,
"dns": null,
"trust": null,
"score": null,
"summary": null,
"history": null,
"notes": []
}
},
{
"input": "https://unscanned.example/pricing",
"domain": "unscanned.example",
"error": {
"code": "no_result",
"message": "We have no stored result for this site with these checks, or none as recent as you asked for."
}
},
{
"input": "not a domain",
"domain": null,
"error": {
"code": "invalid_domain",
"message": "The address isn’t a public domain name we can check, such as an IP address, a private name or a typo."
}
}
]
}Scan many sites
POST /v1/scans/batch scans 1 to 10 sites. It takes optional checks and again, which work as they do for POST /v1/scans. The API returns 202 with a scan for each site, or 200 if every scan is already complete. Read each scan’s links.self until its complete is true; reading a scan is free:
curl -X POST https://api.checkanysite.com/v1/scans/batch \
-H "Authorization: Bearer $CHECKANYSITE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domains": ["stripe.com", "lovable.dev"], "checks": ["readiness"]}'{
"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"
}
}
]
}Results and errors
datahas one item per site, in the order each site first appears. A site sent twice, for example as a domain and as a URL, gets one item.- In a lookup batch, each item has
input(the value you sent),domainandresult. In a scan batch, each item is the site’s scan. - A site that can’t be answered gets an item with
input,domainand anerror, which has acodeand amessage. An input that isn’t a domain hasdomain: nulland the code invalid_domain; a site without a stored result has no_result. An error in one item never affects the others. - The whole batch fails only when the request itself is wrong: no key, a body that isn’t JSON or has too many domains, or no credits left.
Cost
A batch costs the same as its sites requested one by one. In a lookup batch, each site found costs its checks’ stored price, and a site not found costs nothing. For example, 50 sites asked for the ai check, of which 40 have a stored result, cost 40 credits. In a scan batch, each new scan costs its checks’ scan price. The X-Credits-Cost header gives the total.
Send a batch once
Send an Idempotency-Key with every batch. If the connection drops and you send it again, the API returns the first response and charges nothing twice (Idempotency).