Skip to content
SecuritySeptember 16, 20264 min read

File Signatures & Magic Bytes: How to Identify Any File's Real Type

Every file starts with a signature that reveals what it really is. Learn the most common magic bytes, why extensions lie, and how to inspect files safely in your browser.

By FernandesLabs

Founder & Lead Developer · Published September 16, 2026

Share:

A file's name says nothing about its content

You can rename malware.exe to invoice.pdf with two clicks. The extension is metadata — an arbitrary label — while the file's actual format is determined by its bytes. Operating systems hide extensions by default, which makes it trivially easy to send someone a disguised file that looks like a document in an email or a chat app.

Fortunately, almost every file format starts with a predictable byte pattern called a file signature — informally, magic bytes. Read those first few bytes and the file tells you what it really is.

Famous magic bytes you can learn by heart

Signature (hex)File typeWhy you recognize it
FF D8 FFJPEG imageStarts with the "JPEG SOI" marker
89 50 4E 47 0D 0A 1A 0APNG imageThe infamous ‰PNG opening
47 49 46 38GIF imageASCII GIF8
25 50 44 46 2DPDF documentASCII %PDF-
50 4B 03 04ZIP archiveAlso .docx, .xlsx, .jar, .apk — they are all ZIPs
D0 CF 11 E0 A1 B1 1A E1Legacy OfficeOld .doc / .xls binary format
7F 45 4C 46Linux executable (ELF)DEL + ELF
4D 5AWindows executableASCII MZ — Mark Zbikowski, the DOS developer
1F 8Bgzip archiveCompressed Linux downloads
52 49 46 46RIFF containerWAV and AVI files
42 4DBMP imageASCII BM

The 50 4B 03 04 ZIP signature explains a useful trick: a .docx that "won't open" can often be unzipped manually — because it is a zip file containing XML.

How signature detection works

A detector reads the file at offset 0 and compares the leading bytes against a table of known signatures. In JavaScript it is a few lines over an ArrayBuffer:

const buf = await file.slice(0, 16).arrayBuffer();
const bytes = new Uint8Array(buf);
if (bytes[0] === 0x89 && bytes[1] === 0x50) console.log('PNG');
if (bytes[0] === 0xFF && bytes[1] === 0xD8) console.log('JPEG');
if (bytes[0] === 0x25 && bytes[1] === 0x50) console.log('PDF');

Some formats hide their signature at a fixed non-zero offset — e.g. disk images or some container formats mark their header a few hundred bytes in — so robust inspectors check a small set of known offsets and use content heuristics (like UTF-8 validation for text formats) as a fallback. That is exactly what the File Signature Inspector does: it reads the header locally in your browser, decodes the signature, and tells you the most likely true format.

Why this matters for security

Attack 1 — the spoofed extension. Email attachment: Report.pdf whose signature is 4D 5A — a Windows executable. The PDF reader association never gets involved because there is no PDF inside. Users who "always open PDFs" never see it coming.

Attack 2 — the polyglot file. Crafted files that are valid in two formats at once — a file that is both a harmless GIF to the image validator and a PHP script to the server. Signature checks at offset 0 alone can be fooled by polyglots; that is why upload pipelines layer checks (see below).

Attack 3 — the renamed upload. A web app that validates uploads by extension only will happily accept payload.exe renamed to payload.png — and then serve it. If the server also declares it image/png while the bytes are an executable, extension-based "validation" has achieved nothing.

A defense-in-depth upload checklist

If you run any app that accepts uploads, validate in this order:

  1. Size limit first — cheap DoS protection before any parsing happens.
  2. MIME type from content, not from the client-supplied header: read the magic bytes with the MIME Detector logic (server-side) or a library.
  3. Signature check for the exact expected type — a PNG must start with 89 50 4E 47, not merely "look like an image".
  4. Re-encode the image if applicable (ImageMagick, sharp) — this destroys polyglot payloads by rewriting every pixel.
  5. Serve uploads safely: never as text/html, ideally from a sandboxed domain, with X-Content-Type-Options: nosniff.
  6. Checksum the stored file with the File Checksum tool so its integrity can be verified later.

Inspecting a suspicious file in 30 seconds — safely

The golden rule: do not open the file with its default application. Instead:

  1. Open the File Signature Inspector.
  2. Drop the file in. Everything is read locally by your browser — the file never touches a server, so even genuinely malicious files cannot execute (a browser reading bytes is not an execution context).
  3. Read the verdict: the detected signature and true format.
  4. Cross-check with the MIME Detector and, for images, peek at embedded location and camera data with the Image Metadata Viewer.

If invoice.pdf turns out to start with 4D 5A, delete it — and if it arrived by email, report it. The magic bytes never lie, because unlike the filename, nobody thought to forge them.

Related free tools

Try these free online tools — all run in your browser with no sign-up.

Keep reading

More hand-written guides from the blog.

Was this guide helpful?

Anonymous — one tap, no sign-up.

Get new guides in your inbox

One short email when we publish a new guide or tool. No spam, unsubscribe anytime.

We store your email only to send occasional updates. See our privacy policy — no sharing, no spam.