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) |
| 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:
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:
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 →