# How to verify a quote an LLM cites

Last updated: 2026-10-10

To check a quote an LLM attributes to a web page, fetch that page yourself and search its text for the quote, allowing for small differences in punctuation and spacing. `POST /v1/verify/quote` does this in one call (US$0.01): it answers `exact`, `fuzzy` or `none`, says whether the page loaded as real content, and signs a receipt.

## Why a quick check is not enough

LLMs often produce quotes that are close to the source but not on it: a word changed, two sentences joined, or a line from a different page. A plain `fetch` and string search misses three things:

- **Small differences.** Curly quotes, dashes, line breaks and invisible characters make an exact search fail on a quote that is really there. We normalise both texts (Unicode NFKC, plain quotes and dashes, one space for any whitespace) and also accept close matches above a threshold you set.
- **Pages that did not load.** A bot challenge, a JavaScript shell, a paywall or an error page has no quote on it either. A `none` on such a page means the page could not be read, not that the quote is absent. Every answer carries a `content_kind` verdict so you can tell the two apart.
- **No record.** If someone later asks where the quote came from, you have nothing to show. The signed receipt records the URL, the time, the hash of the page text and the match.

## One quote

```sh
curl -s https://vehcdj664efetfrsolne5umanq.srv.us/v1/sample/quote
```

That free sample runs the paid route on a demo page. A real call sends the URL and the quote:

```json
{ "url": "https://www.iana.org/help/example-domains", "quote": "These domains may be used as illustrative examples in documents" }
```

Read `page.content_kind` first, then `result.match`. Full details: [Verify a quote](/docs/verify-quote). Step by step with `curl`, from the free sample to checking the receipt: [How to check a quote an LLM cites, step by step with curl](/guides/verify-llm-quote).

## Pay per call with x402

No account or key is needed. A valid request with no payment gets `402 Payment Required` with the price in a `PAYMENT-REQUIRED` header; an x402 v2 client signs that offer and sends the request again. With `@x402/fetch` (`npm install @x402/fetch @x402/evm viem`) and a Base Sepolia wallet made only for testing, holding test USDC:

```js
import { wrapFetchWithPayment, x402Client } from '@x402/fetch';
import { registerExactEvmScheme } from '@x402/evm/exact/client';
import { privateKeyToAccount } from 'viem/accounts';

const client = new x402Client();
registerExactEvmScheme(client, { signer: privateKeyToAccount(process.env.ATTESTPAGE_X402_KEY) });
const payingFetch = wrapFetchWithPayment(fetch, client);

const res = await payingFetch('https://vehcdj664efetfrsolne5umanq.srv.us/v1/verify/quote', {
  method: 'POST',
  headers: { 'content-type': 'application/json' },
  body: JSON.stringify({ url: 'https://www.iana.org/help/example-domains', quote: 'These domains may be used as illustrative examples in documents' }),
});
const answer = await res.json();
console.log(answer.page.content_kind, answer.result.match);
```

The wrapper signs the offer it gets. To check the price and network before signing, see [One x402 payment step by step](/docs/examples/fetch-x402).

## Every citation in an answer

`POST /v1/verify/citations` (US$0.10 per batch) takes up to 10 quote and URL pairs, fetches each page once and returns the same verdict for each citation under one receipt. Run it on the sources at the end of an answer before the user sees it. Details: [Verify citations](/docs/verify-citations).

## The LLM paraphrased instead of quoting

Send `"match": "passages"` and the claim as `quote`. You get the 3 passages of the page that share most of its words, to judge yourself; it is evidence to read, not a verdict. Try it free: [`GET /v1/sample/quote?match=passages`](https://vehcdj664efetfrsolne5umanq.srv.us/v1/sample/quote?match=passages).

## Questions

### Does a match mean the quote is correct?

No. A match means the words are on the page our fetcher saw at that time. It says nothing about whether the page itself is right.

### What if the page blocks bots?

The answer says so: `content_kind` is `bot_wall`, `js_shell` or `paywall`, and the advice field explains it. Treat the quote as unchecked, not as false.

### Can an agent call this without an account?

Yes. Calls are paid per call with x402 (USDC on Base Sepolia, a test network), there is a small free trial, and the [MCP server](/docs/mcp) exposes the same check as a tool.

### How do I check the receipt later?

With [POST /v1/receipt/verify](/docs/receipt-verify), or offline with our single-file checker: [Verify receipts offline](/docs/verify-offline).
