How to Verify a WACZ Web Archive Independently (Step-by-Step)

July 12, 2026

Somebody hands you a web archive file and says it proves what a page looked like. Maybe it arrived in discovery, maybe a source sent it to your newsroom, maybe it is your own capture and opposing counsel wants to check it. The question is always the same: can you verify this thing without trusting whoever made it?

If the file is a WACZ, the answer is yes, with free tools, in a few minutes, and offline for all but the last step. This guide shows how. It is written for the moderately technical reader, using standard free tools.

What a WACZ actually is

WACZ stands for Web Archive Collection Zipped, an open specification maintained by Webrecorder. In the spec’s words, it is “a media type that allows web archive collections to be packaged and shared on the web as a discrete file”: a ZIP that packages WARC data (the raw recorded web traffic) and metadata in a defined directory structure. The current spec, version 1.1.1, is stable and in active use.

Two design choices make WACZ verifiable rather than merely portable. First, the package must contain a manifest, datapackage.json, listing every file inside with its size and fixity, in practice a SHA-256 hash per file. Second, an optional companion spec, WACZ Signing and Verification (currently a working draft, version 0.1.0), adds datapackage-digest.json, “which contains a hash and signature of the datapackage.json.” Sign the manifest and you have sealed the whole package: any change to any file breaks its hash in the manifest, and any change to the manifest breaks the signature.

The format has serious institutional users. Webrecorder’s own Browsertrix crawler generates WACZ natively, and Scoop, the “high-fidelity, browser-based, web archiving capture engine” from Harvard’s Library Innovation Lab, outputs WACZ with what its README calls “accurate and complete provenance information.”

Step 1: Look at it (nothing to install)

Go to replayweb.page in a browser, press Choose File, and pick the WACZ. The page replays locally; as Webrecorder’s docs put it, “the archived item is loaded directly in the browser and is not uploaded anywhere.” You are now browsing the capture as it rendered, offline if you like.

This step verifies nothing cryptographic. It answers the prior question: is the content in this archive actually the page in dispute?

Step 2: Check the file hashes against the manifest

Unzip the WACZ (it is a plain ZIP; rename to .zip if your tool insists) and open datapackage.json. Each entry lists a path and a hash like sha256:8a7fc0d3.... Recompute any file’s hash and compare:

shasum -a 256 archive/data.warc.gz        # macOS
sha256sum archive/data.warc.gz            # Linux

If the computed value matches the manifest, that file is byte-for-byte what the manifest describes. Do this for every file. Webrecorder’s own Python package (pip install wacz) also validates a package with wacz validate myfile.wacz.

At this point you know the package is internally consistent. What you do not yet know is who sealed it and when.

Step 3: Verify the signature

A signed WACZ carries datapackage-digest.json, with the hash of the manifest and a signature over it. The signing spec supports two modes: a signature backed by a domain’s TLS certificate (verify the certificate chain and that the domain matches), or a bare public-key signature, where verification means, in the spec’s words, “validate the signature of the specified hash with the publicKey.”

For an Ed25519 key, OpenSSL does this directly. In a signed WACZ, the hash and the base64-encoded signature both live inside datapackage-digest.json; extract each to its own file first. One practical detail: Ed25519 does not use OpenSSL’s streaming digest commands, so use pkeyutl with -rawin:

openssl pkeyutl -verify -rawin -pubin -inkey signer-public.pem \
  -in datapackage-hash.txt -sigfile signature.bin

A valid signature ties the sealed package to the signer’s key. If the signer also anchored that signature in time, a timestamp you can independently check, you now have the full chain: these exact bytes existed, sealed by this key, no later than this moment.

Step 4: Check the independent copy

A verified package on your disk still has a single-point-of-failure problem: your disk. If the capture was also stored on Arweave, a decentralized permanent storage network, fetch the stored copy from a gateway by its transaction ID (the URL pattern is https://<gateway>/<transaction-id>, per the AR.IO gateway docs, whose gateways “verify that retrieved and cached data matches what was committed to Arweave” using Merkle-proof data roots). Hash what you download and compare it to the manifest from Step 2. Same hashes, same evidence, now confirmed to exist on a public permanent network that no single party, including the vendor, can alter.

What this adds up to

Run all four steps and you have verified, without trusting the capture vendor at any point: the content is the page in dispute; every file matches the sealed manifest; the manifest signature is valid; and an unalterable public copy matches too. That verification path is what makes an archive evidence-grade rather than just a saved file, and it is what a certification under FRE 902(13) and 902(14) can then describe on paper, a topic we cover in our plain-English guide to those rules.

How Permavault packages this

Every Permavault capture is built for exactly this checklist: the sealed web archive, a signed manifest of every file hash (Ed25519), the signing public key, timestamp proofs, and the permanent Arweave copy on roughly 300 independent nodes funded by a long-term storage endowment, plus one-command verify scripts so the four steps above run as bash verify.sh with standard tools. You can test-drive the whole flow on the sample evidence package from our homepage, no account needed.

Each capture is $4.99, with an optional Certificate of Authenticity from $9. The Legal tier adds a qualified electronic timestamp from Disig a.s., an EU-listed qualified trust service provider, applied to the signed capture manifest, plus an independent Bitcoin-anchored timestamp and a declaration template designed to support authentication under FRE 902(13) and 902(14). Under eIDAS Article 41, a qualified electronic timestamp carries a presumption of the accuracy of its date and time in EU courts.

Do not take anyone’s word for what a capture proves. The whole point of the format is that you do not have to.

This article is general information, not legal advice. Specifications and tool behaviors reflect the cited project documentation as of July 2026; the WACZ signing specification is a working draft and may change.

Need a web page preserved exactly as it exists right now?

Capture it with Permavault