---
title: "Retrieve stored results for many sites · API docs · CheckAnySite"
description: "Looks up as many as 50 sites at once, and returns each site’s stored result as GET /sites/{domain} does, in the order you sent them."
url: "https://docs.checkanysite.com/api/batch-sites"
---

API reference

# Retrieve stored results for many sites

POST `/v1/sites/batch`

Looks up as many as 50 sites at once, and returns each site’s stored result as GET /sites/{domain} does, in the order you sent them.

A site sent twice gets one item. A site without a stored result, or an input that isn’t a domain, gets an `error` in its place, and the other sites are still returned. It never starts a scan.

Credits

Each result found costs its checks’ stored price, up to 3 each; sites without a result cost nothing. The batch is charged as a whole: if your credits don’t cover every result found, the request is refused and nothing is charged.

## Request

```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", "tech"]}'
```

```python
from checkanysite import CheckAnySite

client = CheckAnySite()  # Reads the key from CHECKANYSITE_API_KEY.

batch = client.sites.batch(["stripe.com", "lovable.dev"], checks=["ai", "tech"])
```

```javascript
const url = 'https://api.checkanysite.com/v1/sites/batch';
const response = await fetch(url, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CHECKANYSITE_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    domains: ['stripe.com', 'lovable.dev'],
    checks: ['ai', 'tech'],
  }),
});
const batch = await response.json();
```

## Parameters

- `Idempotency-Key` string header

  A 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 returns `idempotency_key_reused`.

## Request body

JSON, with `Content-Type: application/json`. A field we don’t know is refused, so a typo never passes silently.

- `domains` array of string required body

  1 to 50 domains, or URLs whose host is used. A domain sent twice is answered once, in its first place.
- `checks` array of one of: ai, readiness, popularity, tech, dns, trust, summary, history body

  The checks to answer for each domain; left out, every check.
- `maxAgeDays` integer body

  Answer only with results at most this many days old; older ones are `no_result`.

## Response

| Status | Body | When |
| --- | --- | --- |
| 200 OK | `SiteBatch` | A result or an error for each site. |

```json Response 200: A result, and a site we have none for
{
  "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": "example.org",
      "domain": "example.org",
      "error": {
        "code": "no_result",
        "message": "We have no result for example.org yet. Scan it with POST /v1/scans."
      }
    }
  ]
}
```

- `data` array of value

  One item per domain: its `result`, or an `error`.

## Errors

| Status | Code | What happened |
| --- | --- | --- |
| 400 | [invalid\_json](https://docs.checkanysite.com/errors#invalid_json) | Invalid JSON |
| 400 | [invalid\_parameter](https://docs.checkanysite.com/errors#invalid_parameter) | Invalid parameter |
| 415 | [unsupported\_media\_type](https://docs.checkanysite.com/errors#unsupported_media_type) | Unsupported content type |
| 413 | [request\_too\_large](https://docs.checkanysite.com/errors#request_too_large) | Body too large |
| 401 | [missing\_api\_key](https://docs.checkanysite.com/errors#missing_api_key) | No API key |
| 401 | [invalid\_api\_key](https://docs.checkanysite.com/errors#invalid_api_key) | Unknown API key |
| 401 | [revoked\_api\_key](https://docs.checkanysite.com/errors#revoked_api_key) | Revoked API key |
| 401 | [expired\_api\_key](https://docs.checkanysite.com/errors#expired_api_key) | Expired API key |
| 429 | [rate\_limited](https://docs.checkanysite.com/errors#rate_limited) | Too many requests |
| 422 | [idempotency\_key\_reused](https://docs.checkanysite.com/errors#idempotency_key_reused) | Idempotency key reused |
| 409 | [idempotency\_key\_in\_use](https://docs.checkanysite.com/errors#idempotency_key_in_use) | Request in progress |
| 429 | [quota\_exceeded](https://docs.checkanysite.com/errors#quota_exceeded) | Monthly credits used up |
| 429 | [key\_limit\_reached](https://docs.checkanysite.com/errors#key_limit_reached) | Key limit reached |
| 500 | [internal\_error](https://docs.checkanysite.com/errors#internal_error) | Internal error |
