Blog

What Is a File Magic Number? Format Detection Explained

Published April 24, 2026 · 6 min read

How Does the OS Know What a File Is?

Rename a PNG to .txt. macOS Quick Look still previews it as an image. Run file renamed.txt on Linux — the output still reads PNG image data. The filename changed, but the format didn't. Why?

Because many format detectors inspect a sequence of bytes in the file itself — called a magic number (also known as a file signature or file header) — instead of trusting the filename alone.

Filename extensions still affect how operating systems associate and open files. Tools such as the Unix <code>file</code> command and some browser or server sniffing paths can additionally inspect known byte signatures, but they do not all apply identical rules.

What Is a Magic Number?

Every file format reserves a fixed sequence of bytes at the very beginning of the file to declare its type. These are called magic numbers (also known as file signatures or file headers).

Think of it like a passport: border control doesn't ask your name — they open to page one and confirm your nationality from the fixed format. A magic number is a file's "page one." No matter what the file is named, those first bytes tell you the truth.

This is how the Unix file command works: it maintains a magic database of byte patterns and compares the file contents with those patterns. That is useful evidence of the underlying format, but the filename, declared MIME type, and container metadata can still affect how a particular tool handles the file.

Magic Number Quick-Reference Table

Common format signatures you'll encounter in practice:

Format Magic Bytes (Hex) ASCII Notes
PNG 89 50 4E 47 0D 0A 1A 0A ‰PNG.... 8 bytes, one of the most recognizable
JPEG FF D8 FF — 3 bytes; 3rd byte varies by subtype
GIF 47 49 46 38 GIF8 Followed by 37 (GIF87a) or 39 (GIF89a)
PDF 25 50 44 46 %PDF Followed by version, e.g. -1.7
WebP 52 49 46 46 … 57 45 42 50 RIFF…WEBP RIFF container; check bytes 8–11
WAV 52 49 46 46 … 57 41 56 45 RIFF…WAVE RIFF container; subtype is WAVE
MP3 49 44 33 / FF Fx ID3 / sync With ID3 tag: starts with ID3; without tag: sync word FF Ex or FF Fx
FLAC 66 4C 61 43 fLaC Lossless audio, unambiguous signature
MP4 / MOV / M4A 00 00 00 xx 66 74 79 70 ....ftyp ftyp container; check brand at bytes 8–11
WebM 1A 45 DF A3 — EBML container header
OGG 4F 67 67 53 OggS OGG audio/video container
BMP 42 4D BM Windows bitmap

The Gotcha: Four Bytes Aren't Always Enough

Two container families share common prefixes across completely different media types. Stopping at byte 4 will give you the wrong answer.

RIFF Container (WebP / WAV / AVI)

WebP, WAV, and AVI all start with RIFF (52 49 46 46). The actual subtype is at bytes 8–11:

+0
RIFF
shared prefix
+4
file size (4 bytes)
+8
subtype WEBP / WAVE / AVI
actual format here
+12
chunk data

ftyp Container (MP4 / MOV / M4A)

MP4, MOV, and M4A start with a variable 4-byte box size, then ftyp at bytes 4–7. The brand code at bytes 8–11 determines the actual format:

+0
box size (variable)
+4
ftyp
fixed marker
+8
brand isom / M4A / qt
actual format here
+12
compat list

Brand codes to know: isom / iso2 / avc1 = MP4, M4A = M4A (Apple audio), qt = QuickTime MOV.

Try It: The file Command Reads Magic Numbers Directly

On macOS and Linux, the file command identifies formats by reading magic numbers — not by looking at the filename:

# macOS / Linux
$ file -b photo.png
PNG image data, 617 x 875, 8-bit/color RGBA, non-interlaced

$ file -b photo.txt       # extension changed to .txt
PNG image data, 617 x 875, 8-bit/color RGBA, non-interlaced

file is a built-in tool on macOS and Linux. Windows has no native equivalent.

If you need to implement the same detection in code, the core logic is just a few lines of JavaScript:

// Read the first 18 bytes of a Base64 string for format detection
// (every 4 Base64 chars = 3 bytes)
const b64 = "iVBORw0KGgoAAAANSUhEUgAA...";
const bin = atob(b64.slice(0, 24));
const hex = [...bin]
  .map(c => c.charCodeAt(0).toString(16).padStart(2, "0"))
  .join(" ");
console.log(hex);
// → 89 50 4e 47 0d 0a 1a 0a ... (PNG)

Cross-reference the table: 89 50 4e 47 → PNG, ff d8 ff → JPEG, 25 50 44 46 → PDF.

Summary

Magic bytes are strong evidence about the underlying binary format, but they are not a complete universal type system. Read the relevant bytes, compare them with a documented signature, and account for MIME declarations, container metadata, and the rules of the tool consuming the file.

Renaming a file does not change its bytes, so content-based detectors can still recognize the original format; filename-based associations may behave differently.

Related Article

How to Debug Base64 Images in JSON API Responses →

ViewJSON applies magic number detection to every string in your JSON — Base64 images, audio, and video render as inline previews automatically.

Try It Now

Paste any JSON with Base64 content — ViewJSON auto-detects the format and renders images, audio, and video inline. No manual decoding.

Open ViewJSON →

Written and maintained by the ViewJSON Editorial Team. Examples are verified against the current browser tools before publication.

Published ; last reviewed . Corrections can be sent to support@viewjson.net.