What is this file?

A document pipeline starts by trusting a filename, and filenames lie. I built a small check that reads a few kilobytes of the file's structure and says what it really is, and whether it's locked, renamed or cut off. Then I tested it against three well-known tools on files it had never seen.

Made
Written by
Claude Opus 5.5 in Claude Code, directed by me
Built with
Rust, compiled to WebAssembly
Status
Working; try it below

Try it

With JavaScript on, you can drop any file here and the check runs on it in your browser. The file is never uploaded.

The question

Before a pipeline can read an upload, it has to route it: PDF to one parser, spreadsheet to another, old binary Word files to a third. Most systems route on the extension. The costly failures are the ones the extension hides: a password-protected .docx that no parser can open, a spreadsheet saved as .pdf, a download that stopped halfway.

Checking the first few bytes, the "magic number", is a solved problem, and it isn't enough. Every modern Office file starts the same way as any zip, and every old Office file, Outlook message and locked document starts the same way as each other. So: can a check with no model and no dependencies tell these apart, correctly, in microseconds? And does it beat Magika, Google's deep-learning detector, and the long-standing tools?

How it works

How I tested it

Results

1,914 of 1,917held-out files identified correctly
47 of 47password-protected Office files; Magika found none
Held-out results on parser-verified files
govdocs1 002Apache POITotal
This check517 / 5181,397 / 1,3991,914 (99.8%)
Trust the extension516 / 5181,358 / 1,3991,874 (97.8%)
Magika 1.0.3515 / 5181,356 / 1,3991,871 (97.6%)
libmagic 5.45512 / 5181,345 / 1,3991,857 (96.9%)
file-type 22.1.1370 / 518633 / 1,3991,003 (52.3%)

The second row is the honest headline. On ordinary files, trusting the extension is right 97.8% of the time, about as often as Magika. The average isn't where the difference is. It's in the cases a pipeline pays for.

Where it matters

Speed and size

Time per file and footprint
Per fileFootprint
This check0.04–0.09 ms from disk; about 5 µs in WebAssembly39 KB WebAssembly; 219 KB native
file-type (Node)0.6–0.7 ms580 KB of packages
Magika (Python)9–20 ms3.2 MB model + 46 MB runtime
libmagic15–36 msits pattern database

These cross languages and runtimes, so read them as orders of magnitude, not a race; this laptop also drifts about two times between runs. The WebAssembly build gave the same answer as the native one on all 3,765 files. The check typically asks for 8 to 9 KB of a file, and at most 182 KB (overlapping reads counted twice).

What this doesn't prove

What didn't work

Credits