How to check whether a web page has changed since you read it, step by step with curl
Last updated: 2026-10-13
To find out whether a page you read earlier still says the same thing, send its receipt (or its URL and text hash) to POST /v1/recheck (US$0.003 per call). AttestPage fetches the page again and compares its clean text with the baseline. It answers unchanged, changed, gone or unreadable, lists the fields that differ, and returns a signed receipt that names both the old and the new hash.
This guide runs the call with curl and jq against https://vehcdj664efetfrsolne5umanq.srv.us, then shows the same call as an MCP tool. For every field and error, see Re-check a page.
What the recheck does
- Fetches the page again. It fetches the URL in the baseline, following redirects again, and extracts the clean text the same way as the first time.
- Compares byte for byte.
content_sha256is the hash of the clean text. Markup-only changes leave it the same. A page with a date, a counter or rotating text reads as changed on every visit. - Lists what differs.
differencesnames each compared field that is not the same, such ascontent_sha256,http_statusorfinal_url. - Signs a receipt. The new receipt is itself a baseline: send it in the next call to build a chain.
- Stores nothing and calls nobody. There is no schedule and no webhook. You call when you want to know.
Price
US$0.003 per call, paid in USDC with x402 v2 on Base mainnet (real USDC). No account, key or sign-up. A request with a bad baseline gets 400 before payment and is never charged. Once the page is fetched, the call is charged even when the answer is gone or unreadable, because the fetch was done. All prices: pricing.json.
1. See an answer for free
The free sample rechecks the demo page against its own hash, so it reads unchanged.
curl -s https://vehcdj664efetfrsolne5umanq.srv.us/v1/sample/recheck | jq '{change, changed, differences, content_sha256: .page.content_sha256}'
{
"change": "unchanged",
"changed": false,
"differences": [],
"content_sha256": "0e429607fdb16c005ef662414e758c53edb82e1cb24c3cbec239e4c1d6a7dfa0"
}
2. Read the price from the 402 offer
Step 3 explains the body. A request with a valid body gets the payment offer without being charged. The PAYMENT-REQUIRED header is base64 JSON:
curl -si -X POST https://vehcdj664efetfrsolne5umanq.srv.us/v1/recheck -H 'content-type: application/json' \
-d '{ "url": "https://vehcdj664efetfrsolne5umanq.srv.us/v1/sample/page", "content_sha256": "0e429607fdb16c005ef662414e758c53edb82e1cb24c3cbec239e4c1d6a7dfa0" }' \
| grep -i '^payment-required:' | cut -d' ' -f2 | tr -d '\r' | base64 -d \
| jq '.accepts[0] | {scheme, network, amount, payTo}'
amount is in USDC base units (6 decimals), so 3000 is US$0.003.
3. Recheck the page
Send exactly one of two baselines:
receipt: the compact receipt from an earlier call to this service (/v1/fetch,/v1/verify/quoteor/v1/recheck, paid or trial; a sample receipt is not accepted).urlandcontent_sha256: thepage.content_sha256from our own fetch of that URL. A hash from another tool will not match.
Add "return_text": true to also get up to 20,000 characters of the new clean text. This body uses the demo page and its hash:
cat > body.json <<'EOF'
{ "url": "https://vehcdj664efetfrsolne5umanq.srv.us/v1/sample/page", "content_sha256": "0e429607fdb16c005ef662414e758c53edb82e1cb24c3cbec239e4c1d6a7dfa0" }
EOF
Pay with any x402 v2 client: it reads the offer from step 2, signs it and sends the same request again with a PAYMENT-SIGNATURE header. One x402 payment step by step shows this with plain fetch, and the MCP server does it for you. Save the answer as answer.json.
4. Read the answer
jq '{change, changed, differences, elapsed_seconds, advice}' answer.json
change | What it means |
|---|---|
unchanged | The clean text is the same as in the baseline. |
changed | The text differs. Fetch the page again or check your quote before you rely on it. |
gone | The page no longer exists: 404, 410, or the site's name no longer resolves. If the baseline was already gone, the answer is unchanged, and advice says the page was gone then and is still gone. |
unreadable | We could not read the page this time, so we cannot say whether it changed. page.content_kind says why. Try again later. |
elapsed_seconds is the time since the baseline was fetched. It is null when you sent a URL and hash.
5. Keep the receipt and chain it
The receipt field is a compact JWS. Check it with the free verify route:
jq '{receipt}' answer.json \
| curl -s -X POST https://vehcdj664efetfrsolne5umanq.srv.us/v1/receipt/verify -H 'content-type: application/json' -d @- | jq .valid
For the next recheck, send this receipt as receipt instead of the URL and hash. Its baseline.receipt_sha256 is the SHA-256 of the receipt you sent, which links the chain.
With MCP
The same call is the MCP tool attestpage_recheck, with the body from step 3 as its arguments. To use it from an MCP client with nothing to install, add the remote endpoint:
{
"mcpServers": {
"attestpage": { "type": "http", "url": "https://vehcdj664efetfrsolne5umanq.srv.us/mcp" }
}
}
One call to the remote endpoint with curl. _meta["attestpage/trial"] set to false asks for the payment offer rather than a trial call, so nothing is charged:
curl -s -X POST https://vehcdj664efetfrsolne5umanq.srv.us/mcp -H 'content-type: application/json' -d @- <<'EOF' \
| jq '.result.structuredContent.accepts[0] | {scheme, network, amount}'
{ "jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": { "name": "attestpage_recheck",
"arguments": { "url": "https://vehcdj664efetfrsolne5umanq.srv.us/v1/sample/page", "content_sha256": "0e429607fdb16c005ef662414e758c53edb82e1cb24c3cbec239e4c1d6a7dfa0" },
"_meta": { "attestpage/trial": false } } }
EOF
{
"scheme": "exact",
"network": "eip155:8453",
"amount": "3000"
}
The result has isError: true and the x402 payment requirements in structuredContent, with the same amount as step 2. Sign one of accepts, put the payload in _meta["x402/payment"] and call again: structuredContent is then the same JSON as answer.json.
Questions
How much does a recheck cost?
US$0.003 per call, one page per call. Checking one page every day for 30 days takes 30 calls.
Is a recheck charged if the page is gone?
Yes. When the page was fetched, the call is charged and the answer is gone or unreadable. A bad baseline or a body that fails validation is a 400 before payment and is never charged.
Does unchanged mean nothing on the page moved?
No. It means the clean text is the same byte for byte. Markup, scripts and images can still differ, and differences shows raw_sha256 when the raw bytes moved.