---
title: "Scan a site · API docs · CheckAnySite"
description: "Starts a scan of a site with the checks you ask for."
url: "https://docs.checkanysite.com/api/start-scan"
---

API reference

# Scan a site

POST `/v1/scans`

Starts a scan of a site with the checks you ask for.

If a result from the last day already has those checks, the API returns it with 200. If a scan of the site is already running, it returns that scan with 202; otherwise it starts a new scan and returns 202. Read the scan at `links.self` until `complete` is true: the first results arrive within seconds, and slower sources follow. A scan runs only what its checks need, so fewer checks are faster and cost less. A read-only key gets a recent result or a running scan, but never starts a new one (`read_only_key`). To check a fix, ask for the `readiness` check with `again: true`: once its last result is a few minutes old, the check runs again.

Credits

Each check costs its scan price, up to 15 for every check, when a new scan starts; its stored price, up to 3, when a recent result or a running scan answers.

## Request

```bash cURL
curl -X POST "https://api.checkanysite.com/v1/scans" \
  -H "Authorization: Bearer $CHECKANYSITE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"domain": "wikipedia.org", "checks": ["ai"]}'
```

```python
from checkanysite import CheckAnySite

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

scan = client.scans.create("wikipedia.org", checks=["ai"])
```

```javascript
const url = 'https://api.checkanysite.com/v1/scans';
const response = await fetch(url, {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.CHECKANYSITE_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ domain: 'wikipedia.org', checks: ['ai'] }),
});
const scan = 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.

- `domain` string required body

  A domain, or a URL whose host is used.
- `checks` array of one of: ai, readiness, popularity, tech, dns, trust, summary, history body

  The checks to answer; left out, every check. A scan runs only what they need, and the call costs what they cost.
- `again` boolean body

  With the `readiness` check: ask it again once its answer is 3 minutes old, to check a fix. Without it, and for other checks, a result from the last 24 hours answers.

  Default: `false`

## Response

| Status | Body | When |
| --- | --- | --- |
| 200 OK | `Scan` | A recent result had the checks; the scan is complete. |
| 202 Accepted | `Scan` | A scan is running. Read it at `links.self`, which the `Location` header also gives. |

```json Response 202: A scan on its way
{
  "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"
  }
}
```

- `id` string

  The scan’s id.
- `domain` string

  The domain scanned.
- `checks` array of one of: ai, readiness, popularity, tech, dns, trust, summary, history

  The checks its result holds: those asked that the scan answers.
- `status` string

  Where it is: `queued`, `running`, `completed` or `failed`.

  One of: `queued`, `running`, `completed`, `failed`.
- `createdAt` date-time

  When it was asked for.
- `finishedAt` date-time or null

  When it finished; null while it runs.
- `complete` boolean

  True once the scan failed, or completed with every slow source in.
- `failure` object or null

  Why the scan couldn’t finish; null unless `status` is `failed`.
- `result` object or null

  The result once `status` is `completed`.
- `links` object

  Where to poll the scan, and where its result is shown.

Once completed, `result` holds the site’s result, as on [the result object](https://docs.checkanysite.com/api/result).

## 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 |
| 400 | [invalid\_domain](https://docs.checkanysite.com/errors#invalid_domain) | Not a public domain |
| 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 |
| 403 | [read\_only\_key](https://docs.checkanysite.com/errors#read_only_key) | Read-only key |
| 422 | [site\_refused](https://docs.checkanysite.com/errors#site_refused) | Site not checked |
| 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 |
| 429 | [scan\_limit\_reached](https://docs.checkanysite.com/errors#scan_limit_reached) | Daily scan limit reached |
| 503 | [capacity](https://docs.checkanysite.com/errors#capacity) | No scan capacity |
| 500 | [internal\_error](https://docs.checkanysite.com/errors#internal_error) | Internal error |
