The mimetypes module maps filenames to MIME types. Essential for web servers, file uploads, and any code that needs to know what kind of file it's handling.

Guess MIME Type

Get type from filename:

import mimetypes
 
# From filename
mime_type, encoding = mimetypes.guess_type('document.pdf')
print(mime_type)   # application/pdf
print(encoding)    # None
 
# Compressed files
mime_type, encoding = mimetypes.guess_type('data.txt.gz')
print(mime_type)   # text/plain
print(encoding)    # gzip

Common Types

import mimetypes
 
files = ['image.jpg', 'script.js', 'style.css', 'data.json', 
         'page.html', 'doc.docx', 'video.mp4', 'song.mp3']
 
for filename in files:
    mime, _ = mimetypes.guess_type(filename)
    print(f"{filename}: {mime}")
 
# image.jpg: image/jpeg
# script.js: text/javascript
# style.css: text/css
# data.json: application/json
# page.html: text/html
# doc.docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document
# video.mp4: video/mp4
# song.mp3: audio/mpeg

Guess Extension

Get extension from MIME type:

import mimetypes
 
# Single extension
ext = mimetypes.guess_extension('image/jpeg')
print(ext)  # .jpg
 
ext = mimetypes.guess_extension('text/html')
print(ext)  # .html
 
ext = mimetypes.guess_extension('application/json')
print(ext)  # .json

All Extensions for Type

import mimetypes
 
# Get all known extensions for a type
exts = mimetypes.guess_all_extensions('image/jpeg')
print(exts)  # ['.jpe', '.jpeg', '.jpg']
 
exts = mimetypes.guess_all_extensions('text/plain')
print(exts)  # ['.txt', '.c', '.h', ...]

Add Custom Types

import mimetypes
 
# Add custom type
mimetypes.add_type('application/x-custom', '.custom')
 
# Now it works
mime, _ = mimetypes.guess_type('file.custom')
print(mime)  # application/x-custom

Initialize Database

import mimetypes
 
# Initialize with system files (usually done automatically)
mimetypes.init()
 
# Add custom files
mimetypes.init(files=['/etc/mime.types', 'my-types.txt'])

Check Type Categories

import mimetypes
 
def get_type_category(filename):
    """Get broad category of file type."""
    mime, _ = mimetypes.guess_type(filename)
    
    if mime is None:
        return 'unknown'
    
    main_type = mime.split('/')[0]
    return main_type
 
files = ['photo.png', 'song.mp3', 'movie.mp4', 'doc.txt', 'app.exe']
for f in files:
    print(f"{f}: {get_type_category(f)}")
 
# photo.png: image
# song.mp3: audio
# movie.mp4: video
# doc.txt: text
# app.exe: application

File Upload Validation

import mimetypes
 
ALLOWED_TYPES = {'image/jpeg', 'image/png', 'image/gif'}
 
def is_allowed_upload(filename):
    """Check if file type is allowed."""
    mime, _ = mimetypes.guess_type(filename)
    return mime in ALLOWED_TYPES
 
print(is_allowed_upload('photo.jpg'))   # True
print(is_allowed_upload('script.js'))   # False
print(is_allowed_upload('image.png'))   # True

HTTP Content-Type Header

import mimetypes
 
def get_content_type(filename):
    """Get Content-Type header value."""
    mime, encoding = mimetypes.guess_type(filename)
    
    if mime is None:
        return 'application/octet-stream'
    
    # Add charset for text types
    if mime.startswith('text/'):
        return f'{mime}; charset=utf-8'
    
    return mime
 
print(get_content_type('page.html'))  # text/html; charset=utf-8
print(get_content_type('image.png'))  # image/png
print(get_content_type('unknown.xyz'))  # application/octet-stream

Static File Server

import mimetypes
from http.server import HTTPServer, SimpleHTTPRequestHandler
 
class ContentTypeHandler(SimpleHTTPRequestHandler):
    def guess_type(self, path):
        """Override to use mimetypes."""
        mime, _ = mimetypes.guess_type(path)
        if mime:
            return mime
        return 'application/octet-stream'

URL Handling

Works with URLs too:

import mimetypes
 
url = 'https://example.com/images/photo.jpg?size=large'
mime, _ = mimetypes.guess_type(url)
print(mime)  # image/jpeg

Strict Mode

import mimetypes
 
# Strict mode only uses official IANA types
mime, _ = mimetypes.guess_type('file.mp3', strict=True)
print(mime)  # audio/mpeg
 
# Non-strict includes platform-specific types
mime, _ = mimetypes.guess_type('file.mp3', strict=False)
print(mime)  # audio/mpeg

List All Types

import mimetypes
 
# All extension mappings
print(mimetypes.types_map)  # {'.js': 'text/javascript', ...}
 
# Common types
print(mimetypes.common_types)  # Core types only

Image Type Helper

import mimetypes
 
def is_image(filename):
    """Check if file is an image."""
    mime, _ = mimetypes.guess_type(filename)
    return mime is not None and mime.startswith('image/')
 
def get_image_type(filename):
    """Get specific image format."""
    mime, _ = mimetypes.guess_type(filename)
    if mime and mime.startswith('image/'):
        return mime.split('/')[1]  # jpeg, png, gif, etc.
    return None
 
print(is_image('photo.jpg'))  # True
print(get_image_type('photo.jpg'))  # jpeg

Email Attachment Types

import mimetypes
 
def get_attachment_params(filename):
    """Get MIME parts for email attachment."""
    mime, _ = mimetypes.guess_type(filename)
    
    if mime is None:
        return 'application', 'octet-stream'
    
    maintype, subtype = mime.split('/')
    return maintype, subtype
 
maintype, subtype = get_attachment_params('report.pdf')
print(f"maintype={maintype}, subtype={subtype}")
# maintype=application, subtype=pdf

Limitations

import mimetypes
 
# Based on extension, not content!
mime, _ = mimetypes.guess_type('malware.jpg')  # Still returns image/jpeg
 
# For content-based detection, use python-magic:
# import magic
# magic.from_file('file.jpg', mime=True)

When to Use mimetypes

Use mimetypes when:

  • Setting Content-Type headers
  • Validating file uploads (by extension)
  • Routing files to handlers
  • Email attachments

Use python-magic when:

  • Need content-based detection
  • Security-critical file validation
  • Extension might be wrong/missing

The mimetypes module is fast and dependency-free—perfect for most file type needs based on filename.

React to this post: