mrkeyoor.com_
Sat 08 Aug 17:38 UTC
PyPIUtilsupdated 08 Aug 2026

python-magic

python-magic is a ctypes wrapper around the operating system's libmagic library, the same file-identification engine used by the Unix `file` command. It identifies content from a path, byte buffer, or file descriptor and can return a human description, MIME type, encoding, likely extensions, or information from inside compressed files. The Python wheel contains the wrapper, not libmagic or its signature database.

Verdict

Choose python-magic when you specifically want libmagic and can own the native dependency. For portable wheels, reproducible results, or security-sensitive file acceptance, a pure-Python detector or format-specific parser is usually the calmer fit.

API stability4/5Version 0.4.27 exposes a small long-standing surface: from_file, from_buffer, from_descriptor, and the Magic class with flag-like constructor options. The README states that minor releases should be backward compatible and major releases may break, but behavior can still change underneath this API when the system libmagic library or database changes.
Docs3/5The README gives direct examples for descriptions, MIME types, buffers, compressed files, installation commands, Windows architecture errors, missing databases, module-name conflicts, testing, and versioning. It remains a single short page, has no dedicated current API site, and leaves several options such as keep_going, raw, extensions, and limits mostly to source inspection.
Maintenance2/5The repository is not archived and was pushed in July 2026, with 27 open issues and pull requests, so the source project is alive. The published package tells a different story: PyPI's current 0.4.27 wheel and source archive were uploaded in June 2022. That multi-year release gap is material for users who install from PyPI rather than GitHub.
Ecosystem4/5The supplied weekly figure is 7,174,890 downloads and the repository has 2,914 stars. libmagic itself is mature, broadly packaged by Linux and macOS distributions, and understands many formats. That reach comes with system-package coupling, platform-specific DLL work on Windows, and output tied to an external database rather than a self-contained Python ecosystem.

Use it if

  • You already deploy libmagic and want the same content-based identification as the file command from Python
  • You need MIME guesses from file headers rather than trusting a user-supplied filename extension
  • You need to inspect buffers, open descriptors, compressed content, or a custom magic database
  • You can tolerate platform-dependent descriptions and pin the operating-system libmagic package in deployment
Skip it if

Setup reality

`pip install python-magic` installs a pure Python wheel, but import still fails unless the native libmagic shared library and its magic database are available. On Debian or Ubuntu the README names `libmagic1`; on macOS it names Homebrew's `libmagic` or MacPorts' `file`. Minimal containers commonly need an extra OS-package layer. Windows is more awkward: the README points to `python-magic-bin` as a bundled alternative and warns that Python and the libmagic DLL must have matching 32-bit or 64-bit architecture. A `WindowsError: [Error 193]` usually means they do not match, while `MagicException: could not find any magic files` means the library cannot locate its database and may need an explicit `magic_file` path. The distribution imports as `magic`, which collides with the different Python bindings shipped by some libmagic packages. Detection quality depends on how many bytes are available; the README recommends at least the first 2,048 bytes for buffer checks because smaller samples can be wrong. Do not read an entire untrusted upload just to classify it. The convenience functions cache Magic instances, while the README cautions against sharing a manually created Magic instance across threads, so use per-thread instances when concurrency matters. `uncompress=True` inspects compressed payloads and increases CPU, memory, and decompression-bomb exposure. Pin both the Python package and OS-level libmagic version if reproducible output matters, and test the exact production image rather than only a developer laptop.

Patterns

Get a human-readable file descriptiondescribe-file

import magic

description = magic.from_file('document.pdf')
print(description)

The exact text can vary with the installed libmagic version and signature database; do not persist it as a stable enum.

Detect a file's MIME typedetect-mime-file

import magic

mime_type = magic.from_file('document.pdf', mime=True)
assert mime_type == 'application/pdf'

Content detection is stronger than trusting the extension, but it is still heuristic and not sufficient authorization for opening an upload.

Classify an upload from its leading bytesdetect-mime-buffer

import magic

with open('upload.bin', 'rb') as stream:
    sample = stream.read(2048)

mime_type = magic.from_buffer(sample, mime=True)

The README recommends at least 2,048 bytes because shorter buffers can produce incorrect identification.

Identify an already open filedetect-file-descriptor

import magic

with open('archive.tar', 'rb') as stream:
    description = magic.from_descriptor(stream.fileno())

Keep the descriptor open for the call. Descriptor behavior depends on what the native libmagic build supports on the platform.

Detect MIME type and character encodingdetect-encoding

import magic

detector = magic.Magic(mime=True, mime_encoding=True)
result = detector.from_file('notes.txt')
print(result)

Encoding identification is heuristic. Decode with explicit error handling rather than assuming the reported charset is always correct.

Look inside compressed contentinspect-compressed-file

import magic

detector = magic.Magic(uncompress=True)
description = detector.from_file('payload.gz')

Uncompressing hostile input costs extra CPU and memory and can expose decompression-bomb risk; use resource limits around untrusted files.

Load a specific magic databaseuse-custom-database

import magic

detector = magic.Magic(
    mime=True,
    magic_file='/opt/app/share/misc/magic.mgc',
)
mime_type = detector.from_file('sample.bin')

Pinning the database improves reproducibility, but the file must be compatible with the deployed libmagic build and readable by the process.

Ask libmagic for likely extensionslist-likely-extensions

import magic

detector = magic.Magic(extension=True)
extensions = detector.from_file('unknown.bin').split('/')

The source raises NotImplementedError when the installed libmagic is too old for extension reporting. Results are suggestions, not a safe rename policy.

Keep more than the first signature matchkeep-all-matches

import magic

detector = magic.Magic(keep_going=True)
print(detector.from_file('ambiguous.bin'))

Multiple matches are libmagic-formatted text, not a structured Python list, and formatting can differ by native library version.

Create one detector per worker threadthread-local-detector

from threading import local
import magic

_state = local()

def detector():
    if not hasattr(_state, 'magic'):
        _state.magic = magic.Magic(mime=True)
    return _state.magic

The README cautions that a Magic instance should not be shared across multiple threads; thread-local instances avoid that coupling.

Surface libmagic failures clearlyhandle-native-errors

import magic

try:
    mime_type = magic.from_file('/srv/uploads/item')
except (OSError, magic.MagicException) as error:
    raise RuntimeError('file identification unavailable') from error

Missing files can raise an OS error, while loading or native identification failures use MagicException. Import itself can fail when libmagic is absent.

Report the native libmagic versioncheck-libmagic-version

import magic

print('libmagic version:', magic.version())

Record this alongside the OS image when debugging output differences; the Python package version alone does not identify the detection engine.

Alternatives

PackageRegistryPick it when
puremagicPyPIYou need signature-based detection without installing a system C library
filetypePyPIYou want a small pure-Python detector for common binary formats and accept a narrower signature set
mimetypes-magicPyPIYou want a maintained libmagic wrapper distribution with bundled platform-oriented packaging choices