> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pocketutils.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Rate Limits & Credits

> Credit costs per endpoint, plan limits, top-up packs, and the headers every response carries.

PocketUtils meters usage in two independent ways. It's worth keeping them separate, because they answer different questions:

<CardGroup cols={2}>
  <Card title="Credits" icon="coins">
    **How much** you may spend before your cycle renews or you top up. Set by your plan.
  </Card>

  <Card title="Rate limit" icon="gauge">
    **How fast** you may spend it, in requests per minute. Also set by your plan.
  </Card>
</CardGroup>

A request that would exceed either one is rejected before any work happens, and rejected requests never spend a credit.

## Credit cost per endpoint

Endpoints come in two tiers. **Light** endpoints fetch and parse — no browser involved. **Render** endpoints boot headless Chromium, or crawl more than one page.

| Endpoint                                             | Method | Tier   | Credits |
| ---------------------------------------------------- | ------ | ------ | ------- |
| [`/screenshot`](/api-reference/screenshot)           | POST   | Render | 2       |
| [`/url-to-pdf`](/api-reference/url-to-pdf)           | POST   | Render | 2       |
| [`/broken-links`](/api-reference/broken-links)       | POST   | Render | 2       |
| [`/broken-links/crawl`](/api-reference/broken-links) | POST   | Render | 2       |
| [`/meta-scan`](/api-reference/meta-scan)             | GET    | Light  | 1       |
| [`/ssl-scan`](/api-reference/ssl-scan)               | GET    | Light  | 1       |
| [`/down-check`](/api-reference/down-check)           | GET    | Light  | 1       |
| [`/link-extract`](/api-reference/link-extract)       | GET    | Light  | 1       |
| [`/link-extract/crawl`](/api-reference/link-extract) | POST   | Light  | 1       |
| [`/xbel-decrypt`](/api-reference/xbel-decrypt)       | POST   | Light  | 1       |
| [`/xbel-to-html`](/api-reference/xbel-to-html)       | POST   | Light  | 1       |
| `/quota`                                             | GET    | —      | Free    |
| `/broken-links/crawl/:jobId` (status)                | GET    | —      | Free    |
| `/link-extract/crawl/:jobId` (status)                | GET    | —      | Free    |
| `/xbel-decrypt/download/:filename`                   | GET    | —      | Free    |
| `/xbel-to-html/download/:filename`                   | GET    | —      | Free    |

Starting a crawl costs credits once, when you start it; polling its status and downloading the resulting file are always free and don't count toward your rate limit either. See [Async Jobs & Polling](/async-jobs).

## Failed requests are never billed

Credits are reserved *before* your request runs and confirmed only after it finishes — so a burst of concurrent requests can never collectively overdraw a balance that each one individually saw as sufficient. If the request then fails (any non-2xx response, or the connection drops mid-render), the reservation is automatically refunded. You are only ever charged for a response that actually succeeds.

## Plans

| Plan           | Price   | Credits / cycle   | Requests / min | API keys      | Usage history |
| -------------- | ------- | ----------------- | -------------- | ------------- | ------------- |
| **Free**       | \$0     | 100               | 20             | Not available | 30 days       |
| **Starter**    | \$9/mo  | 5,000             | 60             | 2             | 1 year        |
| **Growth**     | \$29/mo | 20,000            | 300            | 10            | 2 years       |
| **Scale**      | \$99/mo | 80,000            | 1,200          | Unlimited     | 5 years       |
| **Enterprise** | Custom  | Custom (250,000+) | 5,000          | Unlimited     | 5 years       |

The Free plan's 100 credits/month is the allowance for a signed-in visitor using the website's tool pages — it does not include API key access. Programmatic access starts on Starter.

### Anonymous (signed-out) allowance

No account at all still gets a small, deliberately limited allowance, tracked per IP:

* **10 credits per day**
* **10 requests per minute**

### Top-up packs

On any paid plan, buy additional credits that don't expire with the billing cycle:

| Pack        | Credits | Price |
| ----------- | ------- | ----- |
| `pack_5k`   | 5,000   | \$10  |
| `pack_25k`  | 25,000  | \$45  |
| `pack_100k` | 100,000 | \$160 |

Cycle credits are spent before top-up credits.

## Response headers

Every `/v1` response carries these headers, whether it succeeds or fails:

<ResponseField name="X-Request-Id" type="string">
  Unique ID for this request. Include it when contacting support about a specific call.
</ResponseField>

<ResponseField name="X-Credits-Cost" type="integer">
  Credits this request cost (0 for free endpoints).
</ResponseField>

<ResponseField name="X-Credits-Remaining" type="integer">
  Your balance immediately after this request was reserved.
</ResponseField>

<ResponseField name="RateLimit-Limit" type="integer">
  Your plan's requests-per-minute ceiling.
</ResponseField>

<ResponseField name="RateLimit-Remaining" type="integer">
  Requests left in the current one-minute window.
</ResponseField>

<ResponseField name="RateLimit-Reset" type="integer">
  Seconds until the window resets.
</ResponseField>

<Note>
  Light `GET` endpoints also send `Cache-Control: no-store`. Without it, a browser or intermediary could serve a stale scan from cache, or silently revalidate and re-run the whole thing for a `304` — neither is what re-running a scan should do.
</Note>

## 429 vs. 402: which limit did you hit

| Status | Code                   | Meaning                                                   | What to do                                         |
| ------ | ---------------------- | --------------------------------------------------------- | -------------------------------------------------- |
| `429`  | `rate_limited`         | Too many requests in the current minute                   | Back off and retry after `RateLimit-Reset` seconds |
| `429`  | `free_quota_exhausted` | Anonymous daily allowance used up                         | Sign in, or wait for the daily reset               |
| `402`  | `insufficient_credits` | Signed-in/API-key balance too low for this request's cost | Buy a top-up pack, or wait for cycle renewal       |

`402` responses include a `creditsRequired` field so you know exactly how far short you were:

```json theme={null}
{
  "success": false,
  "error": {
    "code": "insufficient_credits",
    "message": "Not enough credits for this request. Buy a top-up pack or wait for your cycle to renew.",
    "creditsRequired": 2
  }
}
```

<CardGroup cols={2}>
  <Card title="Authentication" icon="key" href="/authentication">
    How each caller type is identified and billed.
  </Card>

  <Card title="Errors" icon="triangle-exclamation" href="/errors">
    The full error code reference.
  </Card>
</CardGroup>


## Related topics

- [Introduction](/index.md)
- [Get quota](/api-reference/quota.md)
- [Authentication](/authentication.md)
- [Quickstart](/quickstart.md)
- [Errors](/errors.md)
