mime-types vs content-disposition vs http-errors vs mime vs type-is vs content-type
HTTP Header and MIME Type Utilities for Node.js
mime-typescontent-dispositionhttp-errorsmimetype-iscontent-typeSimilar Packages:
HTTP Header and MIME Type Utilities for Node.js

These packages provide focused utilities for working with HTTP headers, MIME types, and error responses in Node.js applications. content-disposition and content-type parse and format specific HTTP headers. http-errors creates standard HTTP error objects with appropriate status codes and messages. mime and mime-types handle MIME type lookups and extensions, while type-is checks request content types against expected values. Together, they form a foundational toolkit for building robust HTTP servers and middleware.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
mime-types181,495,7871,44622.9 kB223 months agoMIT
content-disposition106,758,85923719.2 kB133 months agoMIT
http-errors100,187,0301,55419.1 kB173 months agoMIT
mime95,626,9982,343161 kB05 months agoMIT
type-is68,076,02822621.3 kB1410 months agoMIT
content-type57,016,86714210.5 kB43 years agoMIT

HTTP Header and MIME Type Utilities: A Practical Guide for Node.js Developers

When building HTTP servers or middleware in Node.js, you'll frequently encounter tasks like parsing headers, validating content types, generating proper error responses, and mapping file extensions to MIME types. The six packages in this comparison (content-disposition, content-type, http-errors, mime, mime-types, and type-is) each solve specific problems in this space with minimal, focused APIs. Let's explore how they work together and when to use each one.

📥 Content-Disposition: Safe File Downloads

The content-disposition package handles the Content-Disposition header, which tells browsers how to handle responses — particularly for file downloads.

Why not DIY? Manually constructing this header is risky because filenames can contain characters that break header parsing or enable response splitting attacks.

// Using content-disposition
const contentDisposition = require('content-disposition');

// Safe filename handling with proper encoding
const header = contentDisposition('résumé.pdf');
// Returns: 'inline; filename="resume.pdf"; filename*=UTF-8\'\'r%C3%A9sum%C3%A9.pdf'

// For attachments (downloads)
const attachmentHeader = contentDisposition('report.xlsx', { type: 'attachment' });

Without this package, you'd need to implement RFC 6266 compliance yourself, including UTF-8 encoding for international filenames and proper escaping.

🏷️ Content-Type: Parsing Media Types Correctly

The content-type package parses and formats Content-Type headers according to RFC 7231.

Why not DIY? Content-Type headers can include parameters (like charset=utf-8) and have subtle parsing rules around case sensitivity and whitespace.

// Using content-type
const contentType = require('content-type');

// Parsing a header
const parsed = contentType.parse('text/html; charset=utf-8');
// Returns: { type: 'text/html', parameters: { charset: 'utf-8' } }

// Formatting back to a string
const formatted = contentType.format(parsed);
// Returns: 'text/html; charset=utf-8'

// Works with request objects too
const reqType = contentType.parse(req);

Manual parsing would require handling edge cases like quoted parameters, multiple parameters, and ensuring the main type is normalized to lowercase.

❌ HTTP-Errors: Standard Error Objects

The http-errors package creates HTTP error objects with proper status codes, messages, and properties.

Why not DIY? Creating consistent error objects that work well with frameworks like Express requires setting multiple properties correctly.

// Using http-errors
const createError = require('http-errors');

// Creating specific errors
const notFound = createError(404, 'User not found');
const badRequest = createError.BadRequest('Invalid email format');
const unauthorized = createError.Unauthorized();

// Errors have proper properties
console.log(notFound.status); // 404
console.log(notFound.expose); // true (safe to show to users)

Without this, you'd manually set statusCode, status, expose, and other properties that Express and other middleware expect.

📁 MIME vs MIME-Types: Two Approaches to Type Lookup

Both mime and mime-types handle MIME type lookups, but with different scopes.

MIME Package (Full-Featured)

// Using mime
const mime = require('mime');

// Extension to type
const type = mime.getType('file.txt'); // 'text/plain'

// Type to extension
const ext = mime.getExtension('text/html'); // 'html'

// Custom types
mime.define({ 'application/custom': ['custom'] });

MIME-Types Package (Lightweight)

// Using mime-types
const mime = require('mime-types');

// Extension to type only
const type = mime.lookup('file.txt'); // 'text/plain'

// No reverse lookup available
// mime.extension('text/html') doesn't exist

// Get charset for a type
const charset = mime.charset('text/html'); // 'UTF-8'

Choose mime if you need bidirectional lookups or custom type definitions. Choose mime-types if you only need extension-to-type mapping and want a smaller dependency.

🔍 Type-Is: Content Type Validation

The type-is package checks if a request's Content-Type matches expected values.

Why not DIY? Content-Type validation needs to handle wildcards, specific types, and arrays of acceptable types while ignoring parameters.

// Using type-is
const typeis = require('type-is');

// Check against single type
if (typeis(req, 'application/json')) {
  // Handle JSON
}

// Check against array of types
if (typeis(req, ['json', 'urlencoded'])) {
  // Handle form data or JSON
}

// Wildcard support
if (typeis(req, 'application/*')) {
  // Handle any application type
}

// Get the actual matching type
const match = typeis(req, ['json', 'html']);
// Returns 'json', 'html', or false

Manual checking would require parsing the Content-Type header first and then implementing matching logic for wildcards and aliases.

🧩 How They Work Together

These packages are designed to complement each other in typical server scenarios:

// Example: File download endpoint
const express = require('express');
const createError = require('http-errors');
const contentDisposition = require('content-disposition');
const mime = require('mime');

app.get('/download/:filename', (req, res, next) => {
  const { filename } = req.params;
  
  // Validate file exists (simplified)
  if (!fileExists(filename)) {
    return next(createError.NotFound('File not found'));
  }
  
  // Set proper Content-Type
  const contentType = mime.getType(filename) || 'application/octet-stream';
  res.setHeader('Content-Type', contentType);
  
  // Set safe Content-Disposition
  res.setHeader('Content-Disposition', contentDisposition(filename));
  
  // Send file
  res.sendFile(filename);
});
// Example: API endpoint with validation
const typeis = require('type-is');
const createError = require('http-errors');

app.post('/api/users', (req, res, next) => {
  // Validate content type
  if (!typeis(req, ['json'])) {
    return next(createError.UnsupportedMediaType('Only JSON accepted'));
  }
  
  // Process JSON body
  // ...
});

⚠️ Common Pitfalls to Avoid

Don't Mix MIME Packages Unnecessarily

If you're already using mime, there's no need to also install mime-types. The mime package includes everything mime-types provides plus additional functionality.

Always Use content-disposition for Downloads

Never construct Content-Disposition headers manually:

// ❌ Dangerous - vulnerable to response splitting
res.setHeader('Content-Disposition', `attachment; filename="${userFilename}"`);

// ✅ Safe - properly escaped and encoded
res.setHeader('Content-Disposition', contentDisposition(userFilename));

Use http-errors Consistently

Mixing manual error objects with http-errors can lead to inconsistent behavior in error-handling middleware:

// ❌ Inconsistent
if (!user) {
  const err = new Error('Not found');
  err.statusCode = 404;
  next(err);
}

// ✅ Consistent
if (!user) {
  next(createError.NotFound('User not found'));
}

📊 When to Use Which Package

ScenarioRecommended Package(s)
Serving file downloadscontent-disposition + mime
Parsing request Content-Typecontent-type + type-is
Creating API error responseshttp-errors
Static file servermime-types (lighter) or mime (full-featured)
Validating request body formattype-is
Generating Content-Type headersmime

💡 Final Recommendation

These packages follow the Unix philosophy of doing one thing well. Rather than building monolithic utilities, they provide composable, focused tools that handle the tricky details of HTTP standards correctly.

  • Use content-disposition whenever you're setting that header — the security benefits alone justify the dependency.
  • Use content-type for parsing/formatting Content-Type headers — it handles RFC compliance so you don't have to.
  • Use http-errors for all error creation — it ensures consistency across your application.
  • Choose between mime and mime-types based on whether you need bidirectional lookups.
  • Use type-is for content type validation — it's much more reliable than manual string matching.

By using these specialized packages, you avoid common security vulnerabilities, ensure standards compliance, and write more maintainable code that clearly expresses its intent.

How to Choose: mime-types vs content-disposition vs http-errors vs mime vs type-is vs content-type
  • mime-types:

    Choose mime-types when you only need extension-to-MIME-type lookups and want a lighter dependency. It's essentially the lookup functionality extracted from the mime package but without extension-to-type support. This is ideal for static file servers that map file extensions to Content-Type headers without needing reverse lookups.

  • content-disposition:

    Choose content-disposition when you need to safely generate or parse the Content-Disposition header for file downloads. It properly handles filename encoding for special characters and prevents response splitting attacks by escaping newlines. This is essential for any application serving user-uploaded files or generating downloadable content.

  • http-errors:

    Choose http-errors when you need to create HTTP error objects that follow standard conventions. It provides named constructors for all HTTP status codes (like createError.NotFound()) and ensures errors have proper status codes, message properties, and expose settings. This is crucial for consistent error handling in Express.js applications and custom middleware.

  • mime:

    Choose mime when you need a comprehensive MIME type database with both type-to-extension and extension-to-type lookups. It includes a large built-in database and supports custom type definitions. Use this over mime-types if you need extension lookups or want a single package that handles both directions of MIME type resolution.

  • type-is:

    Choose type-is when you need to check if an incoming request's Content-Type matches expected values. It supports wildcards (like application/*), specific types, and arrays of acceptable types. This is commonly used in middleware to validate request bodies before processing, ensuring your handlers only receive appropriately formatted data.

  • content-type:

    Choose content-type when you need to parse or format Content-Type headers according to RFC 7231. It correctly handles media types with parameters (like charset) and provides normalized access to type and subtype. Use this instead of manual string parsing to avoid common pitfalls with parameter parsing and case sensitivity.

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 mime@1.x 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