# Fetch a web page as Markdown for an LLM with Keenable Page Fetch

Keenable Page Fetch returns one web page as Markdown, with its title, author and publish date, from Keenable's index or live from the source, or returns only the answer to an instruction about the page. Each fetch is one request at $4 per thousand requests from prepaid Credits, whichever way it reads the page.

## At a glance

- **Endpoint:** `GET https://zeroclick.keenable.ai/zcj/glh0rtba74dc/v1/zeroclick/fetch`, one page per request
- **Query parameters:** `url` (required, URL-encoded), `max_chars` (default `50000`), `live` (`true` or `false`, default `false`), `prompt` (up to 2,000 characters)
- **Price:** $4 per thousand requests, the same for an index fetch, a live fetch and a prompt fetch
- **Payment:** calls draw on the Credits plan. Buy Credits with `POST https://zeroclick.keenable.ai/zcj/glh0rtba74dc/plans/{planId}/purchase`, minimum $0.50, paid over x402, MPP or card.
- **Credential:** `Authorization: Bearer <token>`. The bearer credential is the agent identity the storefront issues, registered for free at [auth.md](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/auth.md).
- **Response:** JSON with `url`, `title`, `content` (Markdown), `author` and `published_at` (Unix seconds). The charge and remaining credit are in the `zc-billing` header.
- **Not billed:** any response that is not a 2xx, such as 404, 422, 502 or 504
- **Full purchase flow:** [the buyer skill](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/SKILL.md)

## Choose index, live or prompt

| You need | Set | What `content` holds |
| --- | --- | --- |
| A page's text for a model to read | `url`, optionally `max_chars` | Keenable's indexed copy as Markdown |
| The current copy of a page that changes, or a page not in the index | `live=true` | The page fetched from the source, as Markdown |
| One answer from the page, to keep your own context small | `prompt=<instruction>` | Only the answer to the instruction |

By default, Page Fetch only fetches pages that Keenable has indexed. A page outside the index returns an error unless you set `live=true`.

## Fetch a page as Markdown

1. Confirm your credential holds Credits:

   ```bash
   curl -s "https://zeroclick.keenable.ai/zcj/glh0rtba74dc/agent/entitlements" -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   A 200 lists your entitlements with `remainingCreditUsd`. If there are none, get a credential and Credits through [the buyer skill](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/SKILL.md) and [auth.md](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/auth.md).

2. Fetch the page, capping the content at 3,000 characters:

   ```bash
   curl -s "https://zeroclick.keenable.ai/zcj/glh0rtba74dc/v1/zeroclick/fetch?url=https%3A%2F%2Fkeenable.ai%2Fblog%2Fselect-the-tail-from-the-web&max_chars=3000" \
     -H "Authorization: Bearer $ACCESS_TOKEN"
   ```

   The response is a JSON object with `url`, `title`, `content`, `description`, `author` and `published_at`. A sample:

   ```json
   {
     "url": "https://keenable.ai/…",
     "title": "SELECT the tail FROM the web",
     "content": "## The model knows the best answer but gives the typical ones\n\nWhy doesn't the l…",
     "description": "",
     "author": "<author name>",
     "published_at": 1788393600
   }
   ```

   `url` is the final address after redirects. `published_at` is a Unix timestamp in seconds. `description` is deprecated and always empty, so read `content`.

3. Read the charge from the `zc-billing` response header:

   ```json
   {"status": "settled", "fundingSource": "credit", "chargedUsd": "<amount>", "remainingCreditUsd": "<balance>"}
   ```

   The example fetch drew $0.004 from credit. A delivered response without a `zc-billing` header billed nothing.

## Fetch the live copy

Add `live=true` to fetch the page from the source instead of the index:

```bash
curl -s "https://zeroclick.keenable.ai/zcj/glh0rtba74dc/v1/zeroclick/fetch?url=https%3A%2F%2Fkeenable.ai%2Fblog%2Fselect-the-tail-from-the-web&max_chars=3000&live=true" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

The live fetch returns the same fields and drew $0.004 from credit.

## Ask the page a question

Set `prompt` to an instruction and leave out the rest. A model reads the fetched page, and `content` holds only its output:

```bash
curl -s "https://zeroclick.keenable.ai/zcj/glh0rtba74dc/v1/zeroclick/fetch?url=https%3A%2F%2Fkeenable.ai%2Fblog%2Fselect-the-tail-from-the-web&prompt=In+three+short+bullet+points%2C+what+does+SELECT+do+and+what+does+one+query+return%3F" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

The other fields still describe the page, and `content` starts with the answer: `"- SELECT is an agentic tool that queries the web as a database using SQL-like sy…"`. This fetch drew $0.004 from credit. URL-encode the prompt once, like `url`, and keep it to 2,000 characters.

## Limits and charges

- One URL per request. Several pages take several requests.
- `max_chars` truncates content longer than the cap. Its minimum is `1`.
- `title`, `author` and `published_at` appear when the page has them.
- Every call draws on Credits held by your bearer credential. There is no per-call payment.
- A response that is not a 2xx is never billed, so retrying a failed fetch costs nothing until one succeeds.

## Errors

| Status or code | Meaning | Action |
| --- | --- | --- |
| `401 bearer_required` | No agent credential on the call | Register at [auth.md](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/auth.md), then retry with `Authorization: Bearer <token>` |
| `403 plan_required` | The credential holds no Credits (`reason`: `access_not_found`) | Buy Credits from the plan in the body's `plans`, then retry |
| `403 plan_required`, `reason`: `usage_exhausted` | Your Credits balance ran out | Top up with `POST https://zeroclick.keenable.ai/zcj/glh0rtba74dc/extend` and `{"amountUsd": "..."}`, or buy again |
| `404` | The target page does not exist | Check the URL. Not billed. |
| `422` | The page has no extractable content, or the target answered an HTTP error such as 410 or 451 | Read `message`. Not billed. |
| `429` | Your quota or the target server throttled the fetch | Wait for `Retry-After`, then retry |
| `502` | The source could not be reached: DNS, TLS, connection failure or a 5xx from the target | Retry. Not billed. |
| `503` | The storefront could not confirm your allowance | Retry after `Retry-After`. Nothing is charged. |
| `504` | The fetch from the source timed out | Retry later. Not billed. |

A fetch of a keenable.ai address that does not exist answers 404 with a JSON body holding `error` and `message`.

## Frequently asked questions

### Does a live fetch or a prompt cost more than an index fetch?

No. Each fetch is one request at $4 per thousand requests. The index fetch, the live fetch and the prompt fetch of the same page each drew the same amount from credit, $0.004 for the live one.

### Can I fetch a page without buying Credits?

No. Every call needs `Authorization: Bearer <token>` for a credential that holds Credits. A call without a credential answers 401 `bearer_required`, and a credential without Credits answers 403 `plan_required`.

### What format is published_at in?

An integer Unix timestamp in seconds, such as `1788393600`. Convert it in your client if you need a calendar date.

### Is a failed fetch charged?

No. A 404, 422, 502, 504 or any other non-2xx response draws nothing from your Credits. The `zc-billing` header appears only on a response that was charged.

### When should I use a prompt instead of the full page?

Use a prompt when you need one fact or a short summary and want to keep the full page out of your own context. Use the plain fetch when you need the page's text itself.

## Keep reading

- [The buyer skill](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/SKILL.md): the full purchase flow
- [Identity](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/auth.md): register and refresh the bearer credential
- [How to pay](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/payment.md): the 402 and each rail
- [Page Fetch API reference](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/services/fetch/openapi.json): every parameter and status
- [Error reference](https://zeroclick.keenable.ai/zcj/glh0rtba74dc/errors.md): every storefront error code

---

Updated 2026-11-04. All Keenable guides: https://zeroclick.keenable.ai/guides.md. Storefront: https://zeroclick.keenable.ai/zcj/glh0rtba74dc/llms.txt.
