CI Hex Version Hex Downloads License

Detects MIME types from binary content using magic byte signatures. Only the leading bytes of a file are examined, making detection fast regardless of file size.

Installation

def deps do
  [
    {:magic_bytes, "~> 0.2"}
  ]
end

Usage

From a file path

MagicBytes.from_path("image.png")
#=> {:ok, "image/png"}

MagicBytes.from_path("archive.tar.gz")
#=> {:ok, "application/gzip"}

MagicBytes.from_path("/nonexistent/file")
#=> {:error, :unreadable}

From a binary

Useful when bytes are already in memory — e.g. an upload buffer or a database blob. Only the leading bytes matter; passing the full content works but is not required.

MagicBytes.from_binary(<<0xFF, 0xD8, 0xFF, 0xE0>>)
#=> {:ok, "image/jpeg"}

MagicBytes.from_binary(file_contents)
#=> {:ok, "application/pdf"}

MagicBytes.from_binary(<<0x00, 0x00, 0x00, 0x00>>)
#=> {:error, :unknown}

From a stream

Chunks are accumulated until enough bytes are available, then detection runs. The stream is not fully consumed.

File.stream!("video.mkv", 1024)
|> MagicBytes.from_stream()
#=> {:ok, "video/x-matroska"}

Guards

For prefix-based signatures a corresponding guard macro is generated and exported from MagicBytes. Guard names follow the pattern is_<mime_type> with / and - replaced by _.

require MagicBytes

def process(bin) when MagicBytes.is_image_jpeg(bin), do: ...
def process(bin) when MagicBytes.is_image_png(bin), do: ...
def process(bin) when MagicBytes.is_application_pdf(bin), do: ...
def process(_bin), do: {:error, :unsupported}

Guards also work as boolean expressions outside when clauses:

require MagicBytes
MagicBytes.is_application_gzip(data)  #=> true | false

Guards are not generated for container-format signatures where the distinguishing bytes appear beyond a fixed prefix (WebP, WAV, AVI, AIFF, MP4, HEIC, AVIF, QuickTime). Use from_binary/1 for those formats.

Custom signatures

Define a module with use MagicBytes.DefineSignatures, configure it once, and all from_* functions will check your signatures first, falling back to the built-ins automatically.

defmodule MyApp.Signatures do
  use MagicBytes.DefineSignatures, guards: true

  # Prefix-based: magic bytes at offset 0
  defsignature("application/x-cld", <<0xCA, 0xFE, 0xD0, 0x0D>>)

  # Offset-based: magic bytes at a specific byte offset
  defsignature_at("application/x-tar", 257, "ustar")
end
# config/config.exs
config :magic_bytes,
  extra_signatures: MyApp.Signatures,
  # Required when using offset-based signatures — set to offset + byte_size(magic)
  read_bytes: 262
MagicBytes.from_binary(data)
#=> {:ok, "application/x-cld"}  # or any built-in type

Passing guards: true generates guard macros on your module for both prefix and offset signatures. Because your module compiles after the magic_bytes dependency, guards live on your module rather than on MagicBytes:

require MyApp.Signatures

def process(bin) when MyApp.Signatures.is_application_x_cld(bin), do: ...
def process(bin) when MyApp.Signatures.is_application_x_tar(bin), do: ...

ZIP-based formats

Formats that are ZIP files internally (.docx, .xlsx, .odt, etc.) are correctly detected as application/zip. Distinguishing between them requires parsing the ZIP structure, which is outside the scope of this library. Pair with a ZIP parser for sub-format detection if needed.

Configuration

All options are resolved at compile time via Application.compile_env.

KeyTypeDefaultDescription
:extra_signaturesmodulenilModule with additional signatures defined via use MagicBytes.DefineSignatures
:read_bytespos_integerautoBytes read from input. Defaults to the minimum required by the built-in signatures. Set explicitly when using offset-based custom signatures.
:onlylist(string)nilWhen set, only these MIME types are returned; all others become {:error, :unknown}
:excludelist(string)[]MIME types to suppress. Ignored when :only is set.

Supported formats

CategoryMIME types
Imagesimage/jpeg image/png image/gif image/webp image/bmp image/tiff image/x-icon image/vnd.adobe.photoshop image/heic image/avif image/jp2 image/jxl image/flif
Audioaudio/mpeg audio/flac audio/ogg audio/wav audio/aiff audio/mp4
Videovideo/mp4 video/quicktime video/x-matroska video/x-flv video/x-msvideo
Documentsapplication/pdf application/zip application/x-cfb application/rtf
Archivesapplication/x-rar-compressed application/x-7z-compressed application/gzip application/x-bzip2 application/x-xz application/zstd application/x-lz4
Dataapplication/vnd.apache.parquet application/vnd.apache.arrow.file
Executablesapplication/x-elf application/x-msdownload application/x-mach-binary application/wasm application/vnd.android.dex
Fontsfont/woff font/woff2 font/otf font/ttf
Databaseapplication/x-sqlite3