mime-types vs file-type
File Identification and MIME Type Handling
mime-typesfile-typeSimilar Packages:

File Identification and MIME Type Handling

file-type and mime-types both handle file identification in JavaScript, but they solve different problems. file-type inspects the actual content of a file (magic numbers) to determine its true type, making it secure against extension spoofing. mime-types maps file extensions to MIME type strings, which is useful for setting HTTP headers but relies on the filename being correct. Choose file-type for security validation and mime-types for routing or content negotiation based on known file structures.

Npm Package Weekly Downloads Trend

3 Years

Github Stars Ranking

Stat Detail

Package
Downloads
Stars
Size
Issues
Publish
License
mime-types171,095,1851,47922.9 kB26a year agoMIT
file-type33,619,2564,339142 kB08 days agoMIT

File Identification and MIME Type Handling: file-type vs mime-types

Both file-type and mime-types help developers work with file formats, but they operate at different layers of the stack. file-type looks inside the file to see what it really is, while mime-types looks at the filename to guess what it should be. Understanding this difference is critical for building secure and reliable applications.

πŸ” Detection Method: Content Inspection vs Extension Mapping

file-type reads the actual bytes of a file.

  • It checks "magic numbers" (specific byte signatures at the start of a file).
  • It works even if the file has no extension or a wrong extension.
// file-type: Reads buffer content
import { fileTypeFromBuffer } from 'file-type';

const buffer = await fs.readFile('upload.dat');
const result = await fileTypeFromBuffer(buffer);

console.log(result); 
// Output: { ext: 'png', mime: 'image/png' } 
// Even if the file was named 'upload.dat'

mime-types reads the file path or extension string.

  • It looks up the extension in a internal database.
  • It returns false if the extension is unknown.
// mime-types: Reads path string
import mime from 'mime-types';

const type = mime.lookup('upload.dat');

console.log(type); 
// Output: false or 'application/octet-stream'
// It cannot see inside the file

πŸ›‘οΈ Security: Preventing Spoofing vs Trusting Names

file-type protects against extension spoofing.

  • If a user uploads virus.exe renamed to image.jpg, this package detects it is an executable.
  • Essential for public upload forms where you cannot trust the user.
// file-type: Catches spoofed files
const buffer = getUploadedFileBuffer(); // Contains EXE data
const result = await fileTypeFromBuffer(buffer);

if (result?.mime !== 'image/jpeg') {
  throw new Error('Invalid file content'); // Blocks the EXE
}

mime-types trusts the filename completely.

  • If you pass virus.exe renamed to image.jpg, it will return image/jpeg.
  • Using this for validation creates a serious security hole.
// mime-types: Vulnerable to spoofing
const type = mime.lookup('virus.jpg'); // File is actually EXE

console.log(type); 
// Output: 'image/jpeg'
// This incorrectly validates the malicious file

πŸ“¦ Module System: Modern ESM vs Legacy CJS

file-type is ESM only in recent versions (v18+).

  • You must use import syntax or dynamic import().
  • This may require configuration changes in older Node.js projects.
// file-type: Requires ESM
import { fileTypeFromFile } from 'file-type';

// Cannot use require() directly in modern versions
const result = await fileTypeFromFile('path/to/file');

mime-types supports CommonJS and ESM.

  • Works with require() out of the box.
  • Easier to drop into legacy Express or Koa applications.
// mime-types: Works with CommonJS
const mime = require('mime-types');

// Also works with import
import mime from 'mime-types';

const type = mime.lookup('file.txt');

πŸ“€ Return Data: Structured Objects vs Simple Strings

file-type returns a detailed object.

  • Provides both the extension and the MIME type.
  • Returns undefined if the type is not recognized.
// file-type: Rich return value
const result = await fileTypeFromBuffer(buffer);

if (result) {
  console.log(result.ext);  // 'png'
  console.log(result.mime); // 'image/png'
}

mime-types returns a simple string or boolean.

  • Returns the MIME type string or false.
  • You need separate calls to get the extension from a type.
// mime-types: Simple return value
const type = mime.lookup('file.png'); // 'image/png'
const ext = mime.extension('image/png'); // 'png'

if (!type) {
  console.log('Unknown type');
}

🌱 Similarities: Shared Ground Between Packages

While their methods differ, both packages aim to standardize file handling in Node.js. Here are key overlaps:

1. 🌐 Both Provide MIME Strings

  • Both ultimately help you identify the image/png or application/pdf string.
  • Useful for setting HTTP Content-Type headers.
// file-type: Get MIME from content
const { mime } = await fileTypeFromBuffer(buffer);
res.setHeader('Content-Type', mime);

// mime-types: Get MIME from extension
const type = mime.lookup('image.png');
res.setHeader('Content-Type', type);

2. βš™οΈ Both Run in Node.js Environments

  • Designed primarily for server-side JavaScript.
  • file-type also supports browsers and Deno, while mime-types is mostly Node-focused.
// Both work in standard Node.js scripts
import { fileTypeFromBuffer } from 'file-type';
import mime from 'mime-types';

// Usage in server logic

3. βœ… Both Handle Common Formats

  • Support images, videos, audio, and documents.
  • file-type supports more obscure binary formats via magic numbers.
  • mime-types supports web-standard extensions via IANA registry.
// file-type: Detects binary signatures
await fileTypeFromBuffer(pdfBuffer); // { ext: 'pdf', mime: 'application/pdf' }

// mime-types: Maps known extensions
mime.lookup('doc.pdf'); // 'application/pdf'

πŸ“Š Summary: Key Similarities

FeatureShared by file-type and mime-types
Core Output🌐 MIME type strings
Environmentβš™οΈ Node.js support
Use CaseπŸ“ File handling logic
Formatsβœ… Images, audio, video, docs

πŸ†š Summary: Key Differences

Featurefile-typemime-types
DetectionπŸ” Reads file content (bytes)🏷️ Reads file extension (string)
SecurityπŸ›‘οΈ Safe against spoofing⚠️ Vulnerable to spoofing
Module SystemπŸ“¦ ESM Only (v18+)πŸ“¦ CommonJS + ESM
Return ValueπŸ“„ Object { ext, mime }πŸ“ String or false
Input RequirementπŸ—‚οΈ Needs Buffer/Stream/FileπŸ“ Needs Path/Extension string

πŸ’‘ The Big Picture

file-type is like a security guard πŸ›‘οΈ β€” it checks the ID inside the packet, not just the label on the outside. Use this for uploads, processing pipelines, and any situation where trust is low.

mime-types is like a postal sorter πŸ“¬ β€” it looks at the address label to decide where the packet goes. Use this for setting headers, routing, and serving static assets where extensions are controlled.

Final Thought: Never use mime-types to validate user uploads. The small convenience of checking a string is not worth the risk of executing malicious code. For validation, always inspect the content with file-type.

How to Choose: mime-types vs file-type

  • mime-types:

    Choose mime-types when you need to map known file extensions to MIME types for HTTP responses or static file serving. It is lightweight and perfect for setting Content-Type headers in Express or Koa when you already trust the file extension. Do not use this for security validation, as it cannot detect if a file's content matches its extension.

  • file-type:

    Choose file-type when security is critical, such as validating user uploads where a malicious actor might rename an executable to .jpg. It reads the file content directly, so it works even if the extension is missing or wrong. This is the right choice for backend validation pipelines, image processing services, and any scenario where trusting the filename is unsafe.

README for mime-types

mime-types

NPM Version NPM Downloads Node.js Version Build Status Test Coverage

The ultimate javascript content-type utility.

Similar to the [email protected] module, except:

  • No fallbacks. Instead of naively returning the first available type, mime-types simply returns false, so do var type = mime.lookup('unrecognized') || 'application/octet-stream'.
  • No new Mime() business, so you could do var lookup = require('mime-types').lookup.
  • No .define() functionality
  • Bug fixes for .lookup(path)

Otherwise, the API is compatible with mime 1.x.

Install

This is a Node.js module available through the npm registry. Installation is done using the npm install command:

$ npm install mime-types

Note on MIME Type Data and Semver

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.

Adding Types

All mime types are based on mime-db, so open a PR there if you'd like to add mime types.

API

var mime = require('mime-types')

All functions return false if input is invalid or not found.

mime.lookup(path)

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

mime.contentType(type)

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'

mime.extension(type)

Get the default extension for a content-type.

mime.extension('application/octet-stream') // 'bin'

mime.charset(type)

Lookup the implied default charset of a content-type.

mime.charset('text/markdown') // 'UTF-8'

var type = mime.types[extension]

A map of content-types by extension.

[extensions...] = mime.extensions[type]

A map of extensions by content-type.

License

MIT