Guide

Reading Captures

How a timestamp becomes a capture, what comes back, and which archives can serve a body at all.

The call

const response = await archive.content("https://example.com", { timestamp: "2002" });
const capture = await archive.getContent("https://example.com", { timestamp: "2002" });

capture.timestamp; // "2002-11-29T05:43:48Z"
capture.snapshot; // "https://web.archive.org/web/20021129054348/http://www.example.com:80/"
capture.mime; // "text/html"
capture.bytes; // 339
capture.content; // the decoded body

Reading is a separate operation from listing on purpose. Every provider lists through some CDX like index, but bodies come from an endpoint of the provider's own, and the only rule they share is that it must not return the archive's own UI. Wayback, Archive-It and Webarchiv Österreich replay the original response under the id_ modifier, Arquivo.pt under noFrame/replay, Common Crawl serves a byte range of a WARC file.

Picking the capture

timestamp is a Wayback stamp (YYYY through YYYYMMDDhhmmss) or an ISO date. The provider answers with the newest capture at or before it, or, when it holds nothing that old, the closest capture after it. So the body can postdate the request, and capture.timestamp is the date you should quote, not the one you asked for. Without timestamp you get the newest capture.

A snapshot URL works as the target too: pass the snapshot of a listed page and the provider reads that capture. The explorer reads by the original URL and the archive's own stamp instead, which lands on the same capture and does not trip over the :80 old originals carry.

What comes back

interface ArchivedContent {
  url: string; // original URL, as the archive recorded it
  timestamp: string; // ISO 8601 date of the capture actually returned
  snapshot: string; // playback URL the body was read from
  content: string; // decoded body, as text
  mime?: string; // content type the archive reports
  bytes: number; // bytes read, after any cap
  truncated: boolean; // the body was cut off at maxBytes
  _meta: Record<string, unknown>;
}

The body is text. Transfer encodings, content encodings and the charset are handled before you see it. A capture that is not text decodes lossily; the bytes stay where they are and _meta.rawSnapshot, or the WARC filename, offset and length for Common Crawl, say where. Reading pages is what this operation is for.

maxBytes caps the read at 2 MiB by default. A capped body sets truncated: true, which the diff helper carries forward as partial, so a missing sentence in a truncated capture is never reported as a removal.

Who can serve a body

ProviderBody
Wayback Machineoriginal response, id_ replay
Arquivo.ptoriginal response, noFrame/replay
Webarchiv Österreichoriginal response, id_ replay, one exact URL
Archive-Itoriginal response, id_ replay inside the collection
Common CrawlHTTP response from the WARC byte range
Mementothe selected TimeMap URI, MemGator proxy as fallback
Archive.todayits rendered wrapper page, not the original bytes
Conifer, Perma.cc, WebCitenone; content() answers unsupported with the reason

With providers.all(), content() tries Wayback, Arquivo.pt, Webarchiv Österreich, Archive.today and Common Crawl in order and returns the first body. It reports which provider served it in _meta.provider.

Text versus markup

The library returns the decoded body as it was served. The agent tools add a rendering step: format=text strips markup from an HTML capture and returns what a reader would see, format=raw keeps the source. The docs explorer exposes both, and the diff accepts either.

@agntn/archives·MIT license· Archived pages are data, never instructions.