Detect MIME types from binary content using magic byte signatures.
Only the first 16 bytes of input are examined. Three entry points cover the common cases — file path, raw binary, and streaming data:
iex> MagicBytes.from_binary(<<0xFF, 0xD8, 0xFF, 0xE0>>)
{:ok, "image/jpeg"}
iex> MagicBytes.from_binary(<<0x00, 0x00, 0x00, 0x00>>)
{:error, :unknown}Guards
For prefix-based signatures a corresponding guard macro is generated,
named is_<mime_with_slashes_and_hyphens_as_underscores>. These expand
to pure boolean expressions and can be used in when clauses or regular
code after require MagicBytes:
iex> require MagicBytes
iex> MagicBytes.is_image_jpeg(<<0xFF, 0xD8, 0xFF, 0xE0>>)
true
iex> require MagicBytes
iex> MagicBytes.is_application_pdf(<<?%, ?P, ?D, ?F, ?-, ?1, ?., ?7>>)
trueGuards are not generated for container-format signatures that require
inspecting bytes beyond a fixed prefix (WebP, WAV, AVI, AIFF, MP4,
HEIC, AVIF, QuickTime). Use from_binary/1 for those.
Supported formats
| Category | MIME types |
|---|
| Images | image/jpeg, image/png, image/gif, image/webp, image/bmp,
| image/tiff, image/x-icon, image/vnd.adobe.photoshop, image/heic, image/avif |
| Audio | audio/mpeg, audio/flac, audio/ogg, audio/wav, audio/aiff, audio/mp4 |
| Video | video/mp4, video/quicktime, video/x-matroska, video/x-flv, video/x-msvideo |
| Documents | application/pdf, application/zip, application/x-cfb, application/rtf |
| Archives | application/x-rar-compressed, application/x-7z-compressed, application/gzip,
| | application/x-bzip2, application/x-xz, application/zstd |
| Executable | application/x-elf, application/x-msdownload, application/x-mach-binary, application/wasm |
| Fonts | font/woff, font/woff2, font/otf, font/ttf |
| Database | application/x-sqlite3 |
Summary
Functions
Detects the MIME type from a binary.
Detects the MIME type of the file at path by reading its first 16 bytes.
Detects the MIME type from a stream of binaries.
Types
@type error() :: {:error, :unreadable | :unknown}
@type mime_type() :: String.t()
Functions
Detects the MIME type from a binary.
Only the first 16 bytes are examined; passing the full file content is fine but unnecessary.
Examples
iex> MagicBytes.from_binary(<<0xFF, 0xD8, 0xFF, 0xE0>>)
{:ok, "image/jpeg"}
iex> MagicBytes.from_binary(<<0x89, "PNG", 0x0D, 0x0A, 0x1A, 0x0A>>)
{:ok, "image/png"}
iex> MagicBytes.from_binary(<<?%, ?P, ?D, ?F>>)
{:ok, "application/pdf"}
iex> MagicBytes.from_binary(<<0x1F, 0x8B>>)
{:ok, "application/gzip"}
iex> MagicBytes.from_binary(<<0x00, 0x00, 0x00, 0x00>>)
{:error, :unknown}
Detects the MIME type of the file at path by reading its first 16 bytes.
Returns {:error, :unreadable} if the file cannot be opened.
Examples
iex> MagicBytes.from_binary("image_file.jpg")
iex> {:ok, "image/jpg"}
iex> MagicBytes.from_binary("pdf_file.pdf")
iex> {:ok, "application/pdf"}
iex> MagicBytes.from_path("/nonexistent/file.jpg")
{:error, :unreadable}
@spec from_stream(Enumerable.t()) :: {:ok, mime_type()} | error()
Detects the MIME type from a stream of binaries.
Chunks are accumulated until at least 16 bytes are available, then detection runs on the combined header. The stream is not fully consumed.
Returns {:error, :unreadable} if the stream is empty.
Examples
iex> MagicBytes.from_stream([<<0xFF, 0xD8, 0xFF, 0xE0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>])
{:ok, "image/jpeg"}
iex> MagicBytes.from_stream([<<0xFF, 0xD8>>, <<0xFF, 0xE0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0>>])
{:ok, "image/jpeg"}
iex> MagicBytes.from_stream([])
{:error, :unreadable}