search

Found

info Overview

Identifies 40+ file formats from the first 64 bytes (PNG, JPEG, PDF, ZIP, MP4), flags ZIP containers (docx, xlsx, jar), and warns when the extension lies.

📘 How to Use

  1. Select a file or paste hex bytes
  2. Read the detected format and MIME type from the leading bytes
  3. Check the warning if the filename extension doesn't match the bytes

MIME Magic Byte Detector

※ The file you choose is read locally in your browser and never uploaded anywhere.

search

Drop a file or paste hex bytes to see the detection result.

※ Detection only inspects the first 64 bytes, so secondary payloads hidden later in the file (polyglots) are not caught.

Article

MIME Magic Byte Detector | Trust the first bytes, not the extension

A file named config.exe that's actually a ZIP. A .png that's secretly a polyglot. An attachment called report.pdf whose first four bytes are 3C 3F 78 6D (<?xml). Filenames and Content-Type headers lie; the first few bytes of a file (its magic number, or file signature) do not. This tool reads only the first 64 bytes of a dropped file in your browser and matches them against 40+ signatures — PNG, JPEG, PDF, ZIP containers, MP4, ELF, PE, Mach-O, SQLite, WOFF, and more — to report the actual MIME type.

💡 About this tool

If you've ever written a file-upload endpoint, you know the trap. The naïve version rejects payload.exe and accepts image.png. The slightly less naïve version checks Content-Type on the multipart body — but the client picks that header, and an attacker happily picks image/png. The serious version reads the first few bytes server-side and compares against the magic-number table, which is exactly what file(1) on Linux and python-magic are doing under the hood.

This tool runs the same check in your browser. The dropped file is read with FileReader.readAsArrayBuffer capped at 64 bytes; nothing is uploaded, hashed, or telemetered. The matched bytes get highlighted in green in the hex preview, and the matched signature rule is shown verbatim — so you can copy 89 50 4E 47 0D 0A 1A 0A straight into a unit test fixture or a Snort rule.

ZIP containers get an extra warning card. PK\x03\x04 could mean a plain .zip, but it could also mean .docx, .xlsx, .pptx, .odt, .epub, .jar, .apk, or .kmz — they all share the ZIP local-file header. There's also a hex-paste mode for the case where you don't have the file itself: paste FF D8 FF E0 from an incident-response writeup and you get JPEG.

🧐 Frequently Asked Questions

Q. Why only 64 bytes? Almost every modern signature fits in the first 16 bytes. The ISO 9660 CD format is the famous outlier — its signature lives at offset 0x8001 — but if you're reading ISO images in a browser there are better tools. Capping at 64 bytes also means a 1 GB disk image is parsed in microseconds because we never load the rest.

Q. The result says "ZIP container" — how do I know which container exactly? You can't, from the leading bytes alone. .docx, .xlsx, .pptx, .odt, .epub, .jar, .apk, .kmz and .zip itself all share 50 4B 03 04. They differ in the entries inside the archive, not the header. To tell them apart, unzip and look at the first directory listing: [Content_Types].xml is Office Open XML, META-INF/MANIFEST.MF is JAR, META-INF/CERT.SF is APK, mimetype as the first entry is ODT/EPUB.

Q. Does it detect polyglot files? Not as a dedicated check. The matcher walks the signature table and returns the first hit, so a file that's simultaneously valid as PDF and JAR will be reported as whichever appears first in the table. The one case it does call out is ZIP-container ambiguity (docx vs xlsx vs jar vs apk vs epub vs odt), via the container warning card. For real polyglot analysis, reach for binwalk or file -k (keep going past the first match).

Q. How does the extension-mismatch warning work? The tool extracts the filename suffix with the regex /\.([a-z0-9]{1,8})$/ and compares it to the extension list for the detected format. If invoice.pdf produces 50 4B 03 04 (ZIP), you get a red .pdf vs .zip/.docx/.xlsx/... warning. Useful for the moment a frontend dev hands you "the PDF" and curl says application/zip.

Q. Will it catch a plain text file? Plain text has no fixed signature, so it falls through as "no known signature matched". XML/SVG (<?xml), RTF ({\rtf), and Postscript (%!) start with literal ASCII signatures and are detected. UTF-8/UTF-16 BOMs are not in the current signature table.

Q. Does the file leave my machine? No. The first 64 bytes are read into a Uint8Array, never sent over the network, and the file handle is discarded as soon as the result renders. You can confirm in DevTools — there's no fetch or XHR triggered during detection. Safe to use on suspicious attachments you can't upload anywhere.

📚 Fun Facts

The richest signature reference is still Gary Kessler's File Signatures table, which catalogs over 700 formats and is the source most YARA rule authors quote. Wikipedia's "List of file signatures" stays current with newer container formats — ZSTD's 28 B5 2F FD frame magic, AVIF's 66 74 79 70 61 76 69 66 ftyp at offset 4, and the newer EBML profiles for MKV/WebM. The most quoted oddity is probably the Microsoft Compound Document D0 CF 11 E0 A1 B1 1A E1 — half a kilobyte of structure under that header still appears every time someone opens a pre-2007 .doc or .xls.

Magic-byte detection has a long lineage in security tooling. Suricata, Snort, and Zeek all do file-extraction by matching signatures inside HTTP/SMTP streams. The libmagic database that ships with Linux distros — the same one Python's python-magic wraps — has over 4,000 entries and includes amusing edge cases like detecting the difference between TrueType and OpenType fonts by reading the 4-byte version number, or differentiating MP3 frames from AAC by the bit layout of the second byte after FF. Modern WAFs typically combine the same magic-number checks with deep-content sniffing for archives, because once you have a ZIP container in flight you have to recursively re-check whatever comes out of it.