Skip to main content

sigtype

Small, dependency-free, fast Python package to infer binary file types checking the magic numbers signature.

It works by looking at the first bytes of a file, buffer or stream, so it doesn't rely on file extensions and can correctly identify files even when they are renamed or have no extension at all. Images, video, audio, archives, documents and fonts are supported out of the box.

Installation

pip install sigtype

Usage

Guess a file type

guess() accepts a path, bytes, bytearray, memoryview or a file-like object, and returns a Type instance (with .mime and .extension) or None if the type could not be determined.

import sigtype

kind = sigtype.guess("sample.jpg")

if kind is None:
    print("Cannot guess file type!")
else:
    print(f"File extension: {kind.extension}")
    print(f"File MIME type: {kind.mime}")

The same works with raw bytes:

import sigtype

buf = bytearray([0xFF, 0xD8, 0xFF, 0x00, 0x08])
kind = sigtype.guess(buf)

print(kind.mime)  # image/jpeg
print(kind.extension)  # jpg

How much data is read

Matchers see the first sigtype.SIGNATURE_SIZE bytes (8192) of the input, so passing more than that is pointless. Paths are opened and read for you. For file-like objects the position is restored after the call and reading always starts from the beginning of the stream, so the same object can be passed again. Streams that are not seekable are read from their current position.

A few formats keep their identifying data further into the file, e.g. the directory of a Word or Excel document, or a FLAC marker behind a large ID3 tag. For paths, in-memory buffers and seekable streams sigtype reads the missing parts on demand. If your data lives elsewhere (an HTTP server, object storage), pass a read_at callable that returns up to size bytes starting at offset:

import sigtype

head = fetch_range(url, 0, sigtype.SIGNATURE_SIZE)


def read_at(offset: int, size: int) -> bytes:
    return fetch_range(url, offset, size)


kind = sigtype.guess(head, read_at=read_at)

read_at is only called by the matchers that need it, and only when the leading bytes are not enough. Without it those matchers fall back to what they can tell from the leading bytes.

If you only need the MIME type or the extension, use the dedicated shortcuts:

import sigtype

sigtype.guess_mime("sample.jpg")  # "image/jpeg"
sigtype.guess_extension("sample.jpg")  # "jpg"

Check a specific file family

Helpers are available to check whether a file belongs to a given family without inspecting the result manually:

import sigtype

sigtype.is_image("sample.jpg")  # True
sigtype.is_archive("sample.zip")  # True
sigtype.is_video("sample.mp4")  # True
sigtype.is_audio("sample.mp3")  # True
sigtype.is_font("sample.ttf")  # True
sigtype.is_document("sample.docx")  # True

To tell text from binary data (no magic number exists for plain text), use is_text() and is_binary(). They look at the first 8192 bytes: text is UTF-8 (or UTF-16/UTF-32 with a BOM) without NUL bytes and control characters other than whitespace.

import sigtype

sigtype.is_text("notes.txt")  # True
sigtype.is_binary("sample.jpg")  # True

guess() returns None for plain text on purpose. If you want txt and md results too, pass the opt-in matchers explicitly after the regular ones. Markdown detection is a heuristic: it only reacts to fenced code blocks, links to URLs or paths and bold text.

import sigtype
from sigtype.types import PLAIN_TEXT, TYPES

kind = sigtype.match("README.md", [*TYPES, *PLAIN_TEXT])
print(kind.mime)  # text/markdown

You can also check whether a MIME type or an extension is supported at all:

import sigtype

sigtype.is_mime_supported("image/jpeg")  # True
sigtype.is_extension_supported("jpg")  # True

Command line interface

sigtype also ships a small CLI to inspect files directly from the terminal:

python -m sigtype sample.jpg sample.zip
sample.jpg: image/jpeg (jpg)
sample.zip: application/zip (zip)

Wildcards are supported, since arguments are expanded with glob:

python -m sigtype ./fixtures/*

Adding a custom type matcher

You can register your own matcher by subclassing sigtype.types.Type and registering an instance with add_type():

import sigtype
from sigtype.types import Type


class Foo(Type):
    MIME = "application/foo"
    EXTENSION = "foo"

    def __init__(self) -> None:
        super().__init__(mime=Foo.MIME, extension=Foo.EXTENSION)

    def match(self, buf: bytes | bytearray) -> bool:
        return len(buf) > 2 and buf[0] == 0x46 and buf[1] == 0x4F and buf[2] == 0x4F


sigtype.add_type(Foo())

kind = sigtype.guess_mime("sample.foo")
print(kind)  # "application/foo"

A matcher that needs data beyond the first 8192 bytes sets needs_read_at = True and overrides match_at(). read_at is None when the input cannot be read back, and the matcher must handle that:

from typing import ClassVar

from sigtype.types import Type
from sigtype.utils import ReadAt


class Bar(Type):
    needs_read_at: ClassVar[bool] = True

    def __init__(self) -> None:
        super().__init__(mime="application/bar", extension="bar")

    def match(self, buf: bytes | bytearray) -> bool:
        return self.match_at(buf, None)

    def match_at(self, buf: bytes | bytearray, read_at: ReadAt | None) -> bool:
        if read_at is None:
            return False
        return read_at(100_000, 3) == b"BAR"

Supported types

  • Image: jpg, jpx, jxl, apng, png, gif, webp, tiff, cr2, bmp, jxr, psd, ico, heic, dcm, avif, qoi, dds, dwg, xcf, svg
  • Video: mp4, m4v, mkv, webm, mov, avi, wmv, mpg, flv, m3gp
  • Audio: aac, mid, mp3, m4a, ogg, opus, flac, wav, amr, aiff
  • Archive: br, rpm, dcm, epub, zip, tar, rar, gz, bz2, 7z, pdf, exe, swf, rtf, nes, crx, cab, eot, ps, xz, sqlite, deb, ar, z, lzop, lz, elf, lz4, zst
  • Font: woff, woff2, ttf, otf
  • Document: doc, docx, odt, xls, xlsx, ods, ppt, pptx, odp, msg, fb2, eml, ofd, mobi, djvu
  • Application: wasm

Metadata

Release files for sigtype 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sigtype 0.2.1
File Size Uploaded
sigtype-0.2.1.tar.gz 29.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sigtype 0.2.1
File Interpreter ABI Platform
sigtype-0.2.1-py3-none-any.whl Python 3 none any Details

Total release size: 64.5 kB

Release files / sigtype-0.2.1.tar.gz

Download URL sigtype-0.2.1.tar.gz
Size 29.2 kB
Tags Source
SHA-256 checksum
How to use checksums
18590d55245de64a29cbea2f024f3c911f7d15e17e6c41ee09de2a7e3a0862f4
BLAKE2b-256 checksum
How to use checksums
9487337c641f24eafc121f799072621f24642b20bf30772a6a0b278743148d96
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / sigtype-0.2.1-py3-none-any.whl

Download URL sigtype-0.2.1-py3-none-any.whl
Size 35.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2dbe5ea2b0d3644c01758011b6123652e46d22eea07e4d5cd86068dc600d4cab
BLAKE2b-256 checksum
How to use checksums
eb6c6c07e46816a7ba5353e661133d8a46b68d912b9d2a771997e3c10c0641c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.17 {"installer":{"name":"uv","version":"0.12.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 release files

0.2.0

26 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page