file-type, mime, mime-db, mime-lookup, and mime-types are npm packages that help developers work with MIME types—essential identifiers for file formats and content types on the web. file-type detects MIME types by examining the first bytes of a file (magic number detection), making it ideal for verifying uploaded files. The other four packages focus on mapping between file extensions and MIME types, but differ in scope and layering: mime-db is a raw JSON database of MIME type definitions; mime-types and mime-lookup build on top of it to provide lookup utilities; and mime offers a higher-level, all-in-one API that includes both extension-to-type and type-to-extension conversion. These tools are commonly used in file upload handlers, static asset servers, and content negotiation logic.
When building applications that handle files—whether in a Node.js backend, a browser-based uploader, or a static site generator—you’ll often need to answer two fundamental questions:
The five packages under review address these needs in different ways. Let’s break down their roles, capabilities, and trade-offs.
file-type Does Thisfile-type is in a category of its own: it reads the first few bytes of a file (the “magic number”) to determine its true format. This is essential when you can’t trust the filename or user input.
// In Node.js
import { fileTypeFromBuffer } from 'file-type';
const buffer = await fs.readFile('unknown-file');
const result = await fileTypeFromBuffer(buffer);
console.log(result?.mime); // e.g., 'image/png'
// In the browser
import { fileTypeFromBlob } from 'file-type';
const blob = new Blob(['...'], { type: 'application/octet-stream' });
const result = await fileTypeFromBlob(blob);
console.log(result?.mime); // actual detected type
None of the other packages (mime, mime-db, etc.) can do this—they only work with extensions or known type strings. If your use case involves file validation or security, file-type is non-negotiable.
The remaining packages help you convert between file extensions (like .css) and MIME types (like text/css). But they differ significantly in design and maintenance status.
mime: Self-Contained and Simplemime ships with its own built-in list of common types. You don’t need to pull in external data.
import mime from 'mime';
console.log(mime.getType('txt')); // 'text/plain'
console.log(mime.getExtension('image/png')); // 'png'
It’s fast, has zero dependencies, and works everywhere. But its dataset isn’t as comprehensive or frequently updated as the official IANA registry.
mime-db: Raw Data Onlymime-db exports a plain JSON object containing the full IANA MIME type database. It provides no functions—just data.
import db from 'mime-db';
console.log(db['image/png']);
// { source: 'iana', extensions: ['png'] }
// You’d have to write your own lookup logic:
function lookup(ext) {
for (const [type, info] of Object.entries(db)) {
if (info.extensions?.includes(ext)) return type;
}
}
This is useful only if you’re building a MIME library yourself. Application code should avoid it.
mime-lookup: Deprecated and Redundantmime-lookup was a thin wrapper over mime-db for extension-to-type lookups:
// ⚠️ Do not use in new projects — deprecated
import lookup from 'mime-lookup';
console.log(lookup('js')); // 'application/javascript'
However, its npm page states it’s deprecated, and the GitHub repo is archived. Use mime-types instead.
mime-types: The Standard for Accurate Lookupsmime-types uses mime-db under the hood but provides a clean, well-tested API for both directions:
import * as mimeTypes from 'mime-types';
console.log(mimeTypes.lookup('style.css')); // 'text/css'
console.log(mimeTypes.extension('text/html')); // 'html'
console.log(mimeTypes.charset('text/plain')); // 'UTF-8'
It’s actively maintained, follows the official registry closely, and handles nuances like default charsets for text types—something mime doesn’t do.
You’re building a profile picture uploader and must ensure users can’t upload HTML files disguised as .jpg.
file-type to inspect the file’s binary header.mime or mime-types—they only check the extension.const fileType = await fileTypeFromBuffer(fileBuffer);
if (fileType?.mime !== 'image/jpeg' && fileType?.mime !== 'image/png') {
throw new Error('Only JPEG/PNG allowed');
}
You’re writing a minimal HTTP server and need to set Content-Type based on file extensions.
mime-types for accuracy and charset support.mime works if you only serve common assets and want fewer dependencies.// With mime-types
res.setHeader('Content-Type', mimeTypes.contentType(path.extname(filename)));
// With mime
res.setHeader('Content-Type', mime.getType(filename));
You’re creating a new framework and need to embed MIME logic.
mime-db directly if you want full control over parsing and caching.mime-types if you want correctness without reinventing lookup logic.mime-lookup—it’s deprecated.mime-lookup is deprecated. Its npm page says: “This package is deprecated. Use mime-types instead.” Do not use it in new code.mime-db is not a utility—it’s a data source. It hasn’t changed much because it mirrors a stable standard, but that doesn’t mean it’s meant for direct app use.file-type is the only option for content-based detection. No other package in this group reads file bytes.| Package | Detects from Content? | Extension → Type | Type → Extension | Uses Official DB? | Actively Maintained? |
|---|---|---|---|---|---|
file-type | ✅ Yes | ❌ No | ❌ No | N/A | ✅ Yes |
mime | ❌ No | ✅ Yes | ✅ Yes | ❌ Bundled subset | ✅ Yes |
mime-db | ❌ No | ❌ (raw data) | ❌ (raw data) | ✅ Yes | ✅ (as data mirror) |
mime-lookup | ❌ No | ✅ Yes | ❌ No | ✅ Yes | ❌ Deprecated |
mime-types | ❌ No | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
file-typemime-typesmimemime-dbmime-lookup? → Don’t. It’s deprecated—use mime-types instead.In most real-world applications, you’ll end up using file-type for uploads and mime-types for serving, covering both security and correctness needs.
Choose mime-types when you need a robust, up-to-date utility for bidirectional MIME type lookups (extension ↔ type) based on the official mime-db dataset. It’s actively maintained, supports both Node.js and bundlers, and handles edge cases like charset defaults for text types. It’s ideal for web servers, file processors, or any system that must accurately interpret or generate Content-Type headers.
Choose file-type when you need to reliably determine a file's true MIME type by inspecting its binary content rather than trusting its extension or user-provided metadata. This is critical for security-sensitive contexts like file uploads, where an attacker might disguise a malicious script as an image. It works in both Node.js and modern browsers via ArrayBuffer or Blob inputs, but cannot infer types from filenames or extensions alone.
Choose mime when you want a simple, self-contained utility for common tasks like converting .jpg to image/jpeg or vice versa, without managing dependencies on external databases. It bundles its own compact MIME type dataset, so it works offline and loads quickly. It’s well-suited for lightweight servers, CLI tools, or frontend apps that need basic extension/type mapping without extra overhead.
Choose mime-db only if you're building a low-level library that requires direct access to the full, unprocessed IANA MIME type database in JSON format. It provides no helper functions—just raw data—so it’s not intended for direct application use. Most developers should instead use mime-types or mime, which consume this data and expose convenient APIs.
Choose mime-lookup if you specifically need a minimal, focused package that maps file extensions to MIME types using the mime-db dataset, and you don’t require reverse lookups (type to extension). However, note that this package is deprecated as of 2023 and should be avoided in new projects; prefer mime-types or mime instead.
The ultimate javascript content-type utility.
Similar to the mime@1.x module, except:
mime-types simply returns false, so do
var type = mime.lookup('unrecognized') || 'application/octet-stream'.new Mime() business, so you could do var lookup = require('mime-types').lookup..define() functionality.lookup(path)Otherwise, the API is compatible with mime 1.x.
This is a Node.js module available through the
npm registry. Installation is done using the
npm install command:
$ npm install mime-types
This package considers the programmatic api as the semver compatibility. Additionally, the package which provides the MIME data
for this package (mime-db) also considers it's programmatic api as the semver contract. This means the MIME type resolution is not considered
in the semver bumps.
In the past the version of mime-db was pinned to give two decision points when adopting MIME data changes. This is no longer true. We still update the
mime-db package here as a minor release when necessary, but will use a ^ range going forward. This means that if you want to pin your mime-db data
you will need to do it in your application. While this expectation was not set in docs until now, it is how the pacakge operated, so we do not feel this is
a breaking change.
If you wish to pin your mime-db version you can do that with overrides via your package manager of choice. See their documentation for how to correctly configure that.
All mime types are based on mime-db, so open a PR there if you'd like to add mime types.
var mime = require('mime-types')
All functions return false if input is invalid or not found.
Lookup the content-type associated with a file.
mime.lookup('json') // 'application/json'
mime.lookup('.md') // 'text/markdown'
mime.lookup('file.html') // 'text/html'
mime.lookup('folder/file.js') // 'application/javascript'
mime.lookup('folder/.htaccess') // false
mime.lookup('cats') // false
Create a full content-type header given a content-type or extension.
When given an extension, mime.lookup is used to get the matching
content-type, otherwise the given content-type is used. Then if the
content-type does not already have a charset parameter, mime.charset
is used to get the default charset and add to the returned content-type.
mime.contentType('markdown') // 'text/x-markdown; charset=utf-8'
mime.contentType('file.json') // 'application/json; charset=utf-8'
mime.contentType('text/html') // 'text/html; charset=utf-8'
mime.contentType('text/html; charset=iso-8859-1') // 'text/html; charset=iso-8859-1'
// from a full path
mime.contentType(path.extname('/path/to/file.json')) // 'application/json; charset=utf-8'
Get the default extension for a content-type.
mime.extension('application/octet-stream') // 'bin'
Lookup the implied default charset of a content-type.
mime.charset('text/markdown') // 'UTF-8'
A map of content-types by extension.
A map of extensions by content-type.