---
title: "Batches · API docs · CheckAnySite"
description: "Look up as many as 50 sites, or scan as many as 10, in one request. Each site gets its own result or error."
url: "https://docs.checkanysite.com/batches"
---

Concepts

# Batches

Look up as many as 50 sites, or scan as many as 10, in one request. Each site gets its own result or error.

## 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}](https://docs.checkanysite.com/api/get-site). The API returns `200` straight away and never starts a scan:

```bash cURL
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"]}'
```

```python
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}")
```

```json Response 200
{
  "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](https://docs.checkanysite.com/api/start-scan). 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:

```bash cURL
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"]}'
```

```json Response 202
{
  "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

- `data` has 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), `domain` and `result`. In a scan batch, each item is the site’s scan.
- A site that can’t be answered gets an item with `input`, `domain` and an `error`, which has a `code` and a `message`. An input that isn’t a domain has `domain: null` and the code [invalid\_domain](https://docs.checkanysite.com/errors#invalid_domain); a site without a stored result has [no\_result](https://docs.checkanysite.com/errors#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](https://docs.checkanysite.com/idempotency)).
