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 operating systems never rely on filenames to identify formats. They read a fixed sequence of bytes at the very beginning of the file — called a magic number (also known as a file signature or file header).

Windows Explorer, macOS Finder, browser MIME sniffing — they all use the same approach: read the first few bytes, compare against known signatures, draw a conclusion.

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 exactly how the Unix file command works: it maintains a magic database of byte patterns and matches against them — never relying on extensions. Windows Explorer, macOS Finder, and browser MIME sniffing all work the same way. File type is determined by content, not by name.

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

File type is determined by the magic bytes at the start of the binary content — not by the filename or extension. Read the first few bytes, compare against known signatures, and you can identify any format without any surrounding context.

It's also why renaming a file doesn't fool the OS — or any tool that reads magic numbers.

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 →