The extension is a sticky note. The first bytes are the file.
Rename holiday.png to holiday.jpg and nothing inside changes. Windows picks a new icon, the browser reports image/jpeg, and an upload form checking only the name lets the file through. The pixels still sit in a PNG container, opening with the same eight bytes every PNG has carried since the format was published in 1996: 89 50 4E 47 0D 0A 1A 0A.
Those leading bytes are the file signature, also called the magic number. Format designers put them there on purpose, so a program has a fixed marker to test before parsing anything. The Unix file command and its libmagic database work this way, and so does this page, inside your browser tab.
Every card puts two claims next to each other. On the left, what the name says. On the right, what the bytes say, with the exact bytes and offsets behind the call. You check the reasoning yourself instead of trusting a badge.
The type your browser reports for a picked file comes from the extension, looked up in the operating system or a built-in table. The browser never opens the file to confirm. Rename a file and its MIME type changes with the name. Server code trusting the Content-Type header of an upload inherits the same blind spot, since the browser filled in the header from the same lookup.
Reading a signature by hand
Signatures are short, and many spell out ASCII on purpose. A PDF opens with %PDF-. A ZIP opens with PK, the initials of Phil Katz, who wrote PKZIP. A Windows program opens with MZ, after Mark Zbikowski, one of the MS-DOS engineers. Not every signature sits at byte zero, which is why the offset column matters.
| Format | Offset | Bytes (hex) | As text |
|---|---|---|---|
| PNG | 0 | 89 50 4E 47 0D 0A 1A 0A | .PNG.... |
| JPEG | 0 | FF D8 FF | ... |
| GIF | 0 | 47 49 46 38 39 61 | GIF89a |
| 0 | 25 50 44 46 2D | %PDF- | |
| ZIP, DOCX, XLSX, JAR, APK | 0 | 50 4B 03 04 | PK.. |
| Windows EXE and DLL | 0 | 4D 5A | MZ |
| Linux ELF binary | 0 | 7F 45 4C 46 | .ELF |
| MP4, MOV, HEIC, AVIF | 4 | 66 74 79 70 | ftyp |
| SQLite database | 0 | 53 51 4C 69 74 65 20 66 | SQLite f |
| tar archive | 257 | 75 73 74 61 72 | ustar |
| ISO 9660 disc image | 32769 | 43 44 30 30 31 | CD001 |
The PNG signature is the clever one. The 0D 0A pair and the lone 0A break if a transfer rewrites line endings. The high byte 89 breaks if a channel strips the eighth bit. 1A stops the old DOS type command from printing binary to the screen. A mangled PNG fails at the first eight bytes instead of halfway through decoding.
One signature, many formats
The hard cases are formats built inside someone else's container. A signature match only names the container. Telling the members apart means reading further into the file, and the page does so for the families below. The evidence line on each card switches from "Signature match" to "Signature + structure" when this deeper read decides the answer.
- ZIP familyDOCX, XLSX, PPTX, JAR, APK, EPUB, ODT and 3MF all begin with
PK 03 04. The page jumps to the end of the file, reads the ZIP central directory, and checks entry names.word/document.xmlmeans DOCX.AndroidManifest.xmlbesideclasses.dexmeans APK.META-INF/MANIFEST.MFmeans JAR. EPUB and OpenDocument files store an uncompressed entry calledmimetypeas the first member, and its text names the format outright. - OLE compound filesLegacy DOC, XLS, PPT, MSI and Outlook MSG files share
D0 CF 11 E0 A1 B1 1A E1, hex-speak for "docfile". Inside sits a small FAT file system of its own. The page reads the first directory sector and looks for a stream namedWordDocument,WorkbookorPowerPoint Document, then checks the root class ID for installer packages. A password-protected DOCX also lands here, because Office wraps encrypted OOXML in an OLE file with a stream namedEncryptedPackage. - ISO base mediaMP4, MOV, M4A, HEIC, AVIF and 3GP put the box type
ftypat offset 4, followed by a four-letter brand.isomormp42reads as MP4,qtas QuickTime,heicas an iPhone photo,M4Aas audio. Files carrying the genericmif1brand get a second look at the compatible brand list to separate AVIF from HEIC. - RIFFWAV, AVI and WebP all start with
RIFF, a length, then a form type at offset 8:WAVE,AVIorWEBP. For WAV the card also reads the format chunk, so you see sample rate, bit depth and channel count. - CA FE BA BEJava class files and macOS universal binaries share these four bytes. The next four settle the question. A universal binary stores its architecture count there, a small number. A class file stores its version, 45 or higher. Java 21 classes carry major version 65.
Text files have no magic number
JSON, CSV, HTML, Python and plain notes start with whatever character the author typed first. No signature exists, so for text the page stops matching and starts reasoning. The evidence label changes to "Text heuristic" to say so.
- Encoding first. A byte order mark settles encoding:
EF BB BFfor UTF-8,FF FEorFE FFfor UTF-16. Without one, the sample has to decode as UTF-8 with no NUL bytes and almost no control characters to count as text at all. - Shape second. A leading
{or[triggers a real JSON parse for files up to 5 MB. A#!line names the interpreter.<svg,<htmland<?xmlpoint at markup.-----BEGINmarks PEM keys and certificates. An identical count of commas, tabs or semicolons across the first lines reads as CSV or TSV. - Everything else is plain text. A
.md,.logor.ymlfile landing here counts as a match. Text has no wrong extension unless the content has a stronger identity.
Text cards also report line endings. A file mixing CRLF and LF lines is a common reason two copies of the same document hash differently.
The CSV check is the weakest test on the page. A quoted field holding a comma throws the column count off, so a real CSV full of street addresses sometimes lands as plain text. Treat a text verdict as a strong hint, not a ruling.
Reading a result card
Load sample files drops six made-up files on the page, each built to land on a different verdict:
storefront-banner.jpgholds a PNG. Amber, "Extension is wrong". Rename it to.pngand image editors stop complaining. Renaming converts nothing, so if you need a real JPEG, convert it.invoice-0425.pdfholds a 64-bit Windows executable header. Red, the only verdict worth stopping for. This is the shape of a classic phishing attachment.q3-signups.csvholds a JSON array. Amber. Spreadsheet imports choke on files like this one, and the parse confirms the JSON is valid.release-notes.txtis plain UTF-8 text with Windows line endings. Green.nightly-backuphas no extension. The gzip header inside stores the original file name,orders-2026-10.sql, and the card shows it.manuscript-draft.zipis a Word document. Blue, "Right family, narrower type". The ZIP name is not wrong, only vague, and Word wants.docx.
Open the hex dump on any card to see the bytes the verdict rests on, highlighted in place. For formats with a signature past byte 64, such as tar, the dump adds the row holding the match.
When a mismatch matters
Most mismatches are harmless. A phone saving HEIC under a .jpg name. A reporting tool exporting HTML with an .xls name so Excel opens it. A CSV download holding JSON. Those cards stay amber.
Red is reserved for executable content under a non-executable name, and for double extensions such as report.pdf.exe. Windows hides known extensions by default, so the second one displays as report.pdf with a PDF-looking icon if the attacker embedded one.
If you run an upload form, check content on the server as well. A check in the browser protects the visitor, and an attacker skips the browser by posting straight to your endpoint. In PHP, the fileinfo extension reads the same signatures:
$finfo = new finfo(FILEINFO_MIME_TYPE);$mime = $finfo->file($_FILES['upload']['tmp_name']);if (!in_array($mime, ['image/png', 'image/jpeg', 'image/webp'], true)) {http_response_code(415);exit;}From a shell, file --mime-type upload.bin answers the same question. Signature checks stop renamed files. Polyglots get past them: a file built to be a valid GIF and a valid JAR at once passes a GIF test. For image uploads, re-encoding on the server removes the whole class of problem, and header checks alone do not.
Where this page stops
- Not hereMalware scanning. A clean PDF signature says nothing about the JavaScript inside the PDF. Send suspicious files to your antivirus or a multi-engine scanner such as VirusTotal.
- Not hereEncrypted volumes and raw compressed streams. A VeraCrypt container or a bare deflate stream has no header by design. The card reports byte entropy instead. Close to 8 bits per byte means compressed or encrypted, with no way to say which.
- WeakMP3 files without an ID3 tag. Raw MPEG audio is spotted by an 11-bit frame sync pattern, and the page confirms a second frame where possible. Random binary occasionally starts with the same bits.
- WeakCamera RAW. NEF, ARW and DNG are TIFF inside, so they read as TIFF and get the blue related verdict. Canon CR2 and CR3 are told apart.
- Not hereFormats outside the table of 103 signatures. They show as unknown binary, with the hex dump left for you to read. Readable strings in the first rows often name the program behind the file.
- Works wellBig batches of any size. Only the edges of each file are read, plus the ZIP directory or the first OLE directory sector when a container needs a closer look.
When you need the full metadata of one known file rather than its identity, the File Metadata Extractor goes deeper. To confirm two files with the same detected type hold the same bytes, hash both in the File Hash Calculator.