File Hash Verification
Check a download against its published checksum. The file is hashed in your browser and never uploaded, whatever its size.
The algorithm is detected from the hash length. With a checksum list, the line matching the file's name is used.
| Algorithm | Digest |
|---|
Where your data goes
| Using this page | Using the API, MCP or A2A | |
|---|---|---|
| Where it runs | In your browser. The file is read with the browser File API in chunks and hashed in a Web Worker on this page; memory use stays flat whatever the file size. The file is never uploaded. | In a Cloudflare Pages Function at the Cloudflare data centre nearest the caller. |
| What leaves your device | Nothing you enter. After the page and its scripts load, no request
carries your input. The browser enforces this: the page's Content-Security-Policy
sets connect-src 'none' and form-action 'none', which
block fetch, XHR, WebSocket, EventSource, beacons and form posts.
| The server receives the data and the expected hash, hashes the data in memory, and returns the comparison. Your input is not stored or logged; only the per-call metadata row (operation, time, status, sizes) is recorded. Uploading a file means the server sees its full contents: for private or large files use the page, which hashes locally. |
| Stored | Nothing leaves the page. No cookies, analytics or third-party scripts; the browser keeps only your View → Inline config choice. | Your inputs and results: never. What is stored is your client record (client ID, a SHA-256 hash of your secret, expiry, and the profile you registered with) and one metadata row per call: operation, time, transport, status, error code, duration, request and response sizes, and country. |
| Logged | Nothing (no requests are made). | Only the per-call metadata above, attributed to your client ID. Never parameters, bodies, results, or credentials. Cloudflare, as the host, also processes request metadata (IP address, full URL including the query string, headers) under its own policies, so put inputs in POST bodies. |
| Access | Open to anyone. | Requires a client ID and secret (how to get one). HTTPS only; TLS terminates at Cloudflare. |
Details and how to verify this yourself: Security & privacy.
User guide
The tool sits in a window that works like a desktop app: menus on the top row and the full-screen icon at its right (Esc leaves full screen). The set-up options described below are in Settings → Options…, an overlay, and the Settings menu also lists the common choices directly. To keep the options in view instead, choose View → Inline config; the page remembers that choice. Help → Keyboard shortcuts… lists the keys.
- Drop the downloaded file on the box, or click it to choose one.
- Paste the expected checksum from the publisher. Any of these works:
- a hex hash:
9f86d081… - a Base64 or SRI hash:
sha384-oqVuAfXR… - a prefixed hash:
sha256:9f86… - the whole contents of a
SHA256SUMS,*.sha256orCHECKSUMSfile
- a hex hash:
- Read the verdict:
- Match names the algorithm that matched. The file is bit-for-bit what the checksum describes.
- Mismatch means the file is corrupted, incomplete, or a different file. Download it again from the official source.
You do not need to choose an algorithm: it is worked out from the length of the expected hash. With a checksum list, the line whose file name matches your file is used, ignoring any directory part.
Without an expected hash, the page simply computes the digests ticked under Algorithms to compute. Hashing a multi-gigabyte file takes a while in JavaScript; a progress bar shows how far it has got.
What a matching checksum proves. It proves the file matches the checksum, nothing more. If an attacker can replace the download, they can usually replace a checksum on the same website too. To know the checksum itself is genuine, verify a signed checksum file (PGP or similar) or get the checksum over a separate channel.
Specification
Expected-hash formats.
| Form | Example | How it is read |
|---|---|---|
| Hex | ba7816bf…20015ad | Case-insensitive; spaces and colons ignored |
| Base64 | ungWv48B…FAa0= | Either alphabet; padding optional |
| SRI / prefixed | sha256-…, SHA-256:…, blake3=… | Restricts the comparison to the named algorithm |
| GNU list | <hash> <file> or <hash> *<file> | sha256sum, md5sum, b2sum output |
| BSD list | SHA256 (<file>) = <hash> | shasum --tag, BSD sha256 output; algorithm taken from the line |
Algorithm detection. These are the candidates for each decoded digest length; all candidates are computed and compared:
| Bytes | Candidates |
|---|---|
| 16 | MD5 |
| 20 | SHA-1 |
| 32 | SHA-256, SHA3-256, BLAKE3 |
| 48 | SHA-384 |
| 64 | SHA-512, SHA3-512, BLAKE2b-512 |
Line selection in a checksum list.
- Multiple lines: the line whose file name equals the dropped file’s name is used, comparing the base names only.
- A single line is used whatever its file name.
- No matching line is reported as an error rather than a mismatch.
Processing on the page.
- Reading:
File.stream()chunks are fed to every selected hasher in a single pass, inside a dedicated Web Worker started with the page. - Cancelling: choosing another file cancels the running job by terminating the worker.
API differences.
- Size: at most 1 MiB of data per request, because of Cloudflare’s per-request CPU limits.
- Mismatches return
200with"match": false. - Unreadable expectations return
422.
API & MCP
The same logic is available over HTTP and as MCP tools. Unlike this page, these run on the server: see where your data goes.