See how a page changed over time
Inspect repeated observations of a product page, policy statement, or public announcement.
SELECT capture_id, observed_at, document_id,
node_text(capture_id, query_selector(capture_id, 'h1')) AS heading
FROM captures
WHERE url = 'https://example.com/products/widget'
AND capture_id IS NOT NULL
ORDER BY observed_at, capture_id
LIMIT 100;What you get
A chronological series of available observations. Compare headings or adapt the selector to a field you care about.
Illustrative output · selected columns, not live results
| observed_at | heading |
|---|---|
| 2026-09-20 09:00 UTC | Widget — available now |
| 2026-09-22 09:00 UTC | Widget — available now |
| 2026-09-24 09:00 UTC | Widget — back in October |
Compare visible content
After selecting two capture IDs from the history, pass the older ID and newer ID
as the two parameters to sql_execute:
SELECT block_index, change, text
FROM compare_captures(?, ?)
ORDER BY block_index;Both IDs must identify published complete HTML captures with identical
captures.url. Missing documents or different URLs raise an error. The same ID
may be passed twice. Zero rows means the normalized visible text is unchanged,
including when both texts are empty. To count all changed blocks, use
SELECT count() AS changed_blocks FROM compare_captures(?, ?).
The helper compares documents.visible_text, so scripts, styles, templates,
comments, structural navigation and explicitly hidden content do not participate.
It ignores whitespace between tokens, comma thousands separators and trailing
dot-decimal zeros in ASCII numbers: $ 1,200.00 equals $1200, but a change to
$1201 returns removed 1200 and added 1201. Case, punctuation, signs, currency
and nonzero decimal digits remain significant. Decimal-comma locales and numbers
grouped with spaces are unsupported. Numeric-looking versions and identifiers
can also be normalized; dynamic visible counters/timestamps still count as changes.
This is static text comparison, not semantic classification or browser visibility.
Each row is a contiguous changed run of normalized tokens joined with spaces,
not a DOM paragraph. block_index starts at one and orders the edits; change is
removed or added. Replacements remove before adding. Repeated occurrences are
preserved; moved text may appear as removal plus addition. Always use the explicit
ORDER BY and check result truncation.
Both reads use the query's publication snapshot. At most two calls are allowed
per statement, with 4 MiB total lookup responses, 1 MiB and 8,192 tokens per capture,
and 16 million token pairs per comparison after equal ends are trimmed. Exceeding
these bounds raises helper_limit; no partial diff is returned. Preparation
defers the comparison. Arguments must be UUID string literals or positional
parameters, not column expressions or subqueries. No scheduled work is created.