El módulo mimetypes de la biblioteca estándar de Python relaciona extensiones de archivo con tipos de medios utilizados por HTTP, correo electrónico, almacenamiento y aplicaciones de escritorio. Permite estimar si un nombre terminado en .png debería usar image/png, si un documento JSON corresponde a application/json y qué valor aplicar cuando una extensión no es reconocida.
El módulo es pequeño y práctico, pero tiene un límite esencial: normalmente infiere el tipo a partir del nombre o de la URL. No inspecciona todos los bytes del contenido. Por eso es útil para metadatos, headers, organización y experiencia de usuario, pero no debe ser la única barrera de seguridad para cargas de archivos.
Qué es un tipo de medio
Un tipo de medio suele tener la forma tipo/subtipo. Algunos ejemplos son text/html, image/jpeg, application/pdf y application/zip. Navegadores, servidores y clientes usan este valor para decidir cómo transferir, mostrar, descargar, almacenar o procesar un recurso.
El nombre MIME surgió en el correo electrónico, pero hoy estos tipos son fundamentales en HTTP y en las APIs. El header Content-Type describe el cuerpo de una respuesta. Las cargas multipart pueden declarar un tipo para cada parte. Los sistemas internos también lo usan para elegir vistas previas, pipelines, políticas de retención y análisis de seguridad.
Primer ejemplo con guess_type
import mimetypes
tipo, codificacion = mimetypes.guess_type("informe.pdf")
print(tipo) # application/pdf
print(codificacion) # None
La función devuelve dos valores. El primero es el tipo estimado. El segundo puede indicar una codificación de contenido asociada al sufijo, como gzip. Esa codificación no es un charset: representa una capa de compresión o transformación.
Cuando la extensión es desconocida, el tipo puede ser None. La aplicación debe definir una política: usar application/octet-stream, rechazar el archivo, solicitar una selección del usuario o realizar una inspección adicional.
Nombres de archivo y URLs
El módulo acepta nombres y URLs, pero los parámetros y fragments no deben confundirse con la extensión. Conviene separar primero la ruta. La guía de urllib.parse en Python explica cómo descomponer URLs.
from urllib.parse import urlsplit
import mimetypes
url = "https://example.com/assets/manual.pdf?download=1"
ruta = urlsplit(url).path
tipo, codificacion = mimetypes.guess_type(ruta)
La inferencia del tipo no vuelve confiable una URL. Antes de descargar, valida esquema, origen, redirects, DNS, timeout y tamaño. Consulta urllib.request en Python para aplicar límites.
Definir Content-Type
Un servidor puede usar mimetypes para elegir el header de respuesta. Cuando no reconoce el sufijo, utiliza un fallback conservador.
import mimetypes
from pathlib import Path
def content_type_for(path: Path) -> str:
tipo, _ = mimetypes.guess_type(path.name)
return tipo or "application/octet-stream"
No permitas que el cliente seleccione libremente una ruta local. Resuelve la ruta contra una raíz autorizada, bloquea path traversal y comprueba que el resultado permanezca dentro del directorio permitido.
La extensión no demuestra el contenido
Un atacante puede renombrar un ejecutable como foto.jpg. El módulo probablemente devolverá image/jpeg porque solo ve el sufijo. Los bytes todavía pueden pertenecer a un ejecutable, script, archivo comprimido o documento malformado.
Valida las cargas por capas. Limita tamaño, cantidad y frecuencia. Genera un identificador interno en lugar de confiar en el nombre original. Después, inspecciona la firma o procesa el archivo con una biblioteca adecuada. Finalmente, almacena fuera de directorios ejecutables y entrega con headers defensivos.
Usa tempfile en Python para áreas temporales aisladas. Usa hashlib en Python para integridad y deduplicación controlada.
Extensiones compuestas y compresión
Un nombre como backup.tar.gz combina formato y codificación. El resultado puede indicar TAR como tipo y gzip como codificación. No confundas ese segundo valor con el tipo de los archivos después de extraer.
tipo, codificacion = mimetypes.guess_type("backup.tar.gz")
print(tipo)
print(codificacion)
Las cargas comprimidas requieren límites de expansión, cantidad de entradas, profundidad y rutas internas. Las guías de zipfile en Python y tarfile en Python explican estas protecciones.
Registrar tipos personalizados
Las aplicaciones pueden añadir mappings propios con add_type().
import mimetypes
mimetypes.add_type(
"application/vnd.example.report+json",
".rjson",
)
print(mimetypes.guess_type("datos.rjson"))
Registra los tipos críticos al iniciar la aplicación y documenta la decisión. Una biblioteca reutilizable debería evitar cambios globales inesperados. Los tests deben aislar o restaurar el estado.
Modo estricto
Varias funciones aceptan strict. El modo estricto prioriza tipos registrados oficialmente. Con strict=False, Python puede incluir extensiones comunes adicionales conocidas por la plataforma.
tipo, codificacion = mimetypes.guess_type(
"imagen.webp",
strict=False,
)
Elige una política estable. Los servicios públicos suelen preferir valores estandarizados. Las herramientas locales pueden aceptar un conjunto más amplio. Registra el tipo final para diagnosticar diferencias.
Diferencias entre sistemas operativos
Las tablas pueden variar porque Python carga información del sistema. Un tipo reconocido en el equipo de desarrollo puede faltar en un contenedor mínimo de producción. Prueba las extensiones relevantes y registra explícitamente los mappings esenciales.
No supongas que Windows, una distribución Linux de escritorio y una imagen Docker exponen exactamente la misma base de datos. Los tests deben confirmar el contrato de tu aplicación.
Del tipo a la extensión
La búsqueda inversa está disponible con guess_extension() y guess_all_extensions().
import mimetypes
print(mimetypes.guess_extension("image/jpeg"))
print(mimetypes.guess_all_extensions("image/jpeg"))
Un mismo tipo puede tener varios sufijos, como .jpg y .jpeg. No uses este resultado para reconstruir el nombre original. Elige una extensión canónica definida por tu política.
Los charsets son independientes
text/plain no indica si los bytes usan UTF-8, Latin-1 u otra codificación. El módulo no detecta charset. Si generas el texto, declara charset=utf-8. Para decodificación incremental y manejo de errores, consulta codecs en Python.
Sniffing del navegador
Algunos navegadores intentan adivinar el contenido cuando el servidor envía un tipo ausente o incorrecto. Esto puede ser peligroso con archivos de usuarios. Cuando corresponda, envía X-Content-Type-Options: nosniff y un Content-Disposition deliberado.
Los recursos que no deben ejecutarse ni mostrarse inline pueden forzarse como descarga. Los nombres dentro de headers también necesitan validación y escape.
Política práctica para APIs
Una API robusta puede comparar tres señales: extensión normalizada, tipo declarado por el cliente e inspección real del contenido. Una divergencia debería causar rechazo, cuarentena o revisión, no una corrección silenciosa.
Para imágenes, decodifica con una biblioteca mantenida y vuelve a codificar si es necesario. Para PDF, valida estructura, tamaño y política de procesamiento. Para texto, impone encoding y límite de bytes. Para archivos comprimidos, inspecciona entradas antes de extraer.
Tests recomendados
Prueba extensiones en mayúsculas y minúsculas, nombres sin extensión, varios puntos, URLs con query, tipos desconocidos, registros personalizados, sufijos comprimidos y distintos sistemas. Incluye casos hostiles como foto.jpg.exe, nombres enormes, caracteres de control y headers engañosos.
Los tests deben verificar la decisión final de la aplicación, no solo el retorno del módulo. Una estimación técnicamente correcta puede representar un formato prohibido por la política.
Errores comunes
Los errores frecuentes son confiar solo en la extensión, tratar la codificación de contenido como charset, ejecutar un archivo porque el tipo parece seguro, usar el nombre original como ruta, aceptar tipos desconocidos sin política, asumir mappings idénticos y olvidar headers defensivos.
Conclusión
mimetypes ofrece una forma rápida y sin dependencias de inferir tipos de medios a partir de nombres y URLs. Es útil para headers, metadatos, vistas previas y validación inicial. Su límite central debe quedar claro: normalmente estudia el nombre, no los bytes.
Úsalo como una capa de metadatos junto con parsing real, límites, almacenamiento seguro y headers defensivos. Consulta la documentación oficial de mimetypes y el registro de tipos de medios de IANA.







