What is libmagic?
libmagic is the library behind the Unix file command. It identifies files by inspecting their magic bytes — byte patterns at specific offsets in the file content — rather than trusting the file extension or any user-supplied metadata.
libmagic ships with a database of over 1,000 patterns covering virtually every common file format: images, documents, archives, executables, audio, video, and more. When you call it on a file it reads the first bytes, matches them against the database rules, and returns either a human-readable description or a MIME type string.
A file named image.png renamed to image.txt still returns image/png — the bytes do not lie. This protects upload endpoints that rely on file extensions or Content-Type headers, both of which are fully user-controlled. Validate what the file actually is before processing it.
Example Identifications
| File type | MIME type | Description string |
|---|---|---|
| JPEG image | image/jpeg | JPEG image data, JFIF standard 1.01 |
| PDF document | application/pdf | PDF document, version 1.7 |
| ZIP archive | application/zip | Zip archive data, at least v2.0 to extract |
| ELF binary | application/x-executable | ELF 64-bit LSB executable, x86-64 |
| Shell script | text/x-shellscript | POSIX shell script, ASCII text executable |
| UTF-8 text | text/plain; charset=utf-8 | UTF-8 Unicode text |
| Empty file | inode/x-empty | empty |
Flag Modes
Flags control what information libmagic returns. Pass them to Open() or change them later with SetFlags().
| Flag | Description |
|---|---|
| mfNone | Human-readable description string (default mode) |
| mfMimeType | Return only the MIME type, e.g. image/jpeg |
| mfMime | Return MIME type plus charset, e.g. text/plain; charset=utf-8 |
| mfMimeEncoding | Return character encoding only, e.g. utf-8, binary |
| mfCompress | Peek inside compressed files (.gz, .bz2) and identify the inner content |
| mfSymlink | Follow symbolic links to the target file |
| mfDevices | Look at device files |
| mfContinue | Return all matches, not just the best one |
| mfNoCheckCompress | Do not decompress; identify the outer container only |
Types
TMagicHandle
An opaque integer handle representing an open libmagic context (the magic cookie). Obtain one with Open, OpenMIME, or OpenDesc; release it with Close. Each thread should use its own handle.
TMagicFlags
type
TMagicFlags = (
mfNone = $0000000, { human-readable description }
mfDebug = $0000001, { print debug info }
mfSymlink = $0000002, { follow symlinks }
mfCompress = $0000004, { check inside compressed files }
mfDevices = $0000008, { look at device files }
mfMimeType = $0000010, { return MIME type }
mfContinue = $0000020, { return all matches }
mfCheck = $0000040, { validate magic database }
mfPreserveAtime = $0000080, { restore file atime after read }
mfRaw = $0000100, { don't translate unprintable chars }
mfError = $0000200, { return error for unknown files }
mfMimeEncoding = $0000400, { return MIME encoding }
mfMime = $0000410, { MIME type + encoding }
mfApple = $0000800, { return Apple creator/type }
mfExtension = $1000000, { return file extension list }
mfNoCheckCompress = $0001000, { don't decompress }
mfNoCheckELF = $0010000, { don't check ELF details }
mfNoCheckText = $0020000, { don't check text files }
mfNoCheckCDF = $0040000, { don't check CDF (MS Office) }
mfNoCheckCSV = $0080000 { don't check CSV }
);
API Reference
Open / Close
| Function | Description |
|---|---|
| Open(Flags, MagicFile) | Open a magic context with the given flags. Pass an empty string for MagicFile to use the system database. |
| OpenMIME | Open with mfMimeType mode. Most common for web and upload validation. |
| OpenDesc | Open with description mode (human-readable output). |
| Close(M) | Close the handle and free all associated resources. |
Detection
| Function | Description |
|---|---|
| IdentifyFile(M, Path) | Identify a file by path. Returns MIME type or description depending on the flags set on M. |
| IdentifyBuffer(M, Data) | Identify from an in-memory string buffer. No file needed — useful for stream data. |
One-shot Convenience
These functions open and close a handle internally. Convenient for single calls; for multiple files use an open handle instead.
| Function | Description |
|---|---|
| GetMIMEType(Path) | Return the MIME type of a file. |
| GetDescription(Path) | Return the human-readable description of a file. |
| GetMIMETypeFromBuffer(Data) | Return the MIME type detected from an in-memory buffer. |
| GetEncoding(Path) | Return the character encoding (e.g. utf-8, iso-8859-1, binary). |
Type Helpers
| Function | Description |
|---|---|
| IsMIMEType(Path, MIMEType) | Return True if the file matches the given MIME type exactly. |
| IsImage(Path) | Return True if the MIME type starts with image/. |
| IsText(Path) | Return True if the MIME type starts with text/. |
| IsPDF(Path) | Return True if the file is application/pdf. |
| IsArchive(Path) | Return True if the file is a ZIP, TAR, GZ, or other archive format. |
| IsExecutable(Path) | Return True if the file is an ELF, PE, or Mach-O executable. |
Database
| Procedure | Description |
|---|---|
| LoadDatabase(M, Path) | Load a custom magic database file into the handle, replacing the default. |
| CompileDatabase(SourcePath, OutputPath) | Compile a text-format magic rules file into a binary database. |
Flags & Error
| Function | Description |
|---|---|
| SetFlags(M, Flags) | Change the flags on an already-open handle. |
| GetError(M) | Return the last error message for the handle, or an empty string if none. |
Code Example — Validate File Uploads
uses libmagic;
var
MIME: string;
AllowedTypes: array of string;
begin
{ One-shot MIME detection }
MIME := GetMIMEType('/uploads/user_file.jpg');
WriteLn('Detected: ', MIME); { image/jpeg }
{ Validate upload }
if not IsImage('/uploads/user_file.jpg') then begin
WriteLn('Rejected: not an image');
Exit;
end;
{ Check specific types }
if IsPDF('/uploads/document') then
WriteLn('Processing PDF...');
{ Use open handle for multiple files (more efficient) }
var M := OpenMIME;
WriteLn(IdentifyFile(M, 'data.bin')); { detect binary }
WriteLn(IdentifyBuffer(M, #$89'PNG')); { PNG magic bytes }
Close(M);
end.
Always validate uploaded files by their content, not by the file extension or Content-Type header. Both are fully user-controlled and trivially spoofed. libmagic reads the actual bytes, making it the correct tool for enforcing file type policies at upload endpoints.
Install
About
Powers the Unix file command. Database of 1,000+ patterns for identifying file formats by magic bytes.
API
- Open(Flags, MagicFile)
- OpenMIME
- OpenDesc
- Close(M)
- IdentifyFile(M, Path)
- IdentifyBuffer(M, Data)
- GetMIMEType(Path)
- GetDescription(Path)
- GetMIMETypeFromBuffer(Data)
- GetEncoding(Path)
- IsMIMEType(Path, Type)
- IsImage(Path)
- IsText(Path)
- IsPDF(Path)
- IsArchive(Path)
- IsExecutable(Path)
- LoadDatabase(M, Path)
- CompileDatabase(Src, Out)
- SetFlags(M, Flags)
- GetError(M)
Each thread should open its own TMagicHandle with OpenMIME or Open. Handles are not thread-safe to share.