npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@mjackson/multipart-parser

v0.10.1

Published

A fast, efficient parser for multipart streams in any JavaScript environment

Downloads

590,950

Readme

multipart-parser

multipart-parser is a fast, streaming multipart parser that works in any JavaScript environment, from serverless functions to traditional servers. Whether you're handling file uploads, parsing email attachments, or working with multipart API responses, multipart-parser has you covered.

🚀 Why multipart-parser?

  • Universal JavaScript - One library that works everywhere: Node.js, Bun, Deno, Cloudflare Workers, and browsers
  • Blazing Fast - Consistently outperforms popular alternatives like busboy in benchmarks
  • Zero Dependencies - Lightweight and secure with no external dependencies
  • Memory Efficient - Streaming architecture that yields files as they are found in the stream
  • Type Safe - Written in TypeScript with comprehensive type definitions
  • Standards Based - Built on the web standard Streams API for maximum compatibility
  • Production Ready - Battle-tested error handling with specific error types for common scenarios

📦 Features

  • Parse file uploads (multipart/form-data) with automatic field and file detection
  • Support for all multipart/* content types (mixed, alternative, related, etc.)
  • Convenient MultipartPart API with arrayBuffer, bytes, text, size, and metadata access
  • Built-in file size limiting to prevent abuse
  • First-class Node.js support with native http.IncomingMessage compatibility
  • Examples for every major runtime

Installation

Install from npm:

npm install @mjackson/multipart-parser

Or install from JSR:

deno add @mjackson/multipart-parser

Usage

The most common use case for multipart-parser is handling file uploads when you're building a web server. For this case, the parseMultipartRequest function is your friend. It automatically validates the request is multipart/form-data, extracts the multipart boundary from the Content-Type header, parses all fields and files in the request.body stream, and gives each one to you as a MultipartPart object with a rich API for accessing its metadata and content.

import { MultipartParseError, parseMultipartRequest } from '@mjackson/multipart-parser';

async function handleRequest(request: Request): void {
  try {
    for await (let part of parseMultipartRequest(request)) {
      if (part.isFile) {
        // Access file data in multiple formats
        let buffer = part.arrayBuffer; // ArrayBuffer
        console.log(`File received: ${part.filename} (${buffer.byteLength} bytes)`);
        console.log(`Content type: ${part.mediaType}`);
        console.log(`Field name: ${part.name}`);

        // Save to disk, upload to cloud storage, etc.
        await saveFile(part.filename, part.bytes);
      } else {
        let text = part.text; // string
        console.log(`Field received: ${part.name} = ${JSON.stringify(text)}`);
      }
    }
  } catch (error) {
    if (error instanceof MultipartParseError) {
      console.error('Failed to parse multipart request:', error.message);
    } else {
      console.error('An unexpected error occurred:', error);
    }
  }
}

Limiting File Upload Size

A common use case when handling file uploads is limiting the size of uploaded files to prevent malicious users from sending very large files that may overload your server's memory and/or storage capacity. You can set a file upload size limit using the maxFileSize option, and return a 413 "Payload Too Large" response when you receive a request that exceeds the limit.

import {
  MultipartParseError,
  MaxFileSizeExceededError,
  parseMultipartRequest,
} from '@mjackson/multipart-parser/node';

const oneMb = Math.pow(2, 20);
const maxFileSize = 10 * oneMb;

async function handleRequest(request: Request): Promise<Response> {
  try {
    for await (let part of parseMultipartRequest(request, { maxFileSize })) {
      // ...
    }
  } catch (error) {
    if (error instanceof MaxFileSizeExceededError) {
      return new Response('File size limit exceeded', { status: 413 });
    } else if (error instanceof MultipartParseError) {
      return new Response('Failed to parse multipart request', { status: 400 });
    } else {
      console.error(error);
      return new Response('Internal Server Error', { status: 500 });
    }
  }
}

Node.js Bindings

The main module (import from "@mjackson/multipart-parser") assumes you're working with the fetch API (Request, ReadableStream, etc). Support for these interfaces was added to Node.js by the undici project in version 16.5.0.

If however you're building a server for Node.js that relies on node-specific APIs like http.IncomingMessage, stream.Readable, and buffer.Buffer (ala Express or http.createServer), multipart-parser ships with an additional module that works directly with these APIs.

import * as http from 'node:http';
import { MultipartParseError, parseMultipartRequest } from '@mjackson/multipart-parser/node';

let server = http.createServer(async (req, res) => {
  try {
    for await (let part of parseMultipartRequest(req)) {
      // ...
    }
  } catch (error) {
    if (error instanceof MultipartParseError) {
      console.error('Failed to parse multipart request:', error.message);
    } else {
      console.error('An unexpected error occurred:', error);
    }
  }
});

server.listen(8080);

Low-level API

If you're working directly with multipart boundaries and buffers/streams of multipart data that are not necessarily part of a request, multipart-parser provides a low-level parseMultipart() API that you can use directly:

import { parseMultipart } from '@mjackson/multipart-parser';

let message = new Uint8Array(/* ... */);
let boundary = '----WebKitFormBoundary56eac3x';

for (let part of parseMultipart(message, { boundary })) {
  // ...
}

In addition, the parseMultipartStream function provides an async generator interface for multipart data in a ReadableStream:

import { parseMultipartStream } from '@mjackson/multipart-parser';

let message = new ReadableStream(/* ... */);
let boundary = '----WebKitFormBoundary56eac3x';

for await (let part of parseMultipartStream(message, { boundary })) {
  // ...
}

Examples

The examples directory contains a few working examples of how you can use this library:

Benchmark

multipart-parser is designed to be as efficient as possible, operating on streams of data and rarely buffering in common usage. This design yields exceptional performance when handling multipart payloads of any size. In benchmarks, multipart-parser is as fast or faster than busboy.

The results of running the benchmarks on my laptop:

> @mjackson/[email protected] bench:node /Users/michael/Projects/multipart-parser
> node --import tsimp/import ./bench/runner.ts

Platform: Darwin (23.5.0)
CPU: Apple M1 Pro
Date: 8/18/2024, 4:18:39 PM
Node.js v22.1.0
┌──────────────────┬──────────────────┬──────────────────┬──────────────────┬───────────────────┐
│ (index)          │ 1 small file     │ 1 large file     │ 100 small files  │ 5 large files     │
├──────────────────┼──────────────────┼──────────────────┼──────────────────┼───────────────────┤
│ multipart-parser │ '0.01 ms ± 0.03' │ '1.06 ms ± 0.04' │ '0.10 ms ± 0.03' │ '10.60 ms ± 0.22' │
│ multipasta       │ '0.01 ms ± 0.03' │ '1.06 ms ± 0.03' │ '0.15 ms ± 0.02' │ '10.70 ms ± 2.70' │
│ busboy           │ '0.03 ms ± 0.09' │ '3.01 ms ± 0.08' │ '0.22 ms ± 0.03' │ '29.91 ms ± 0.91' │
│ @fastify/busboy  │ '0.03 ms ± 0.07' │ '1.20 ms ± 0.08' │ '0.39 ms ± 0.07' │ '11.86 ms ± 0.17' │
└──────────────────┴──────────────────┴──────────────────┴──────────────────┴───────────────────┘

> @mjackson/[email protected] bench:bun /Users/michael/Projects/multipart-parser
> bun run ./bench/runner.ts

Platform: Darwin (23.5.0)
CPU: Apple M1 Pro
Date: 8/18/2024, 4:20:58 PM
Bun 1.1.21
┌──────────────────┬────────────────┬────────────────┬─────────────────┬─────────────────┐
│                  │ 1 small file   │ 1 large file   │ 100 small files │ 5 large files   │
├──────────────────┼────────────────┼────────────────┼─────────────────┼─────────────────┤
│ multipart-parser │ 0.01 ms ± 0.04 │ 0.91 ms ± 0.09 │ 0.11 ms ± 0.05  │ 8.23 ms ± 0.18  │
│       multipasta │ 0.01 ms ± 0.03 │ 0.87 ms ± 0.08 │ 0.22 ms ± 0.15  │ 8.09 ms ± 0.15  │
│           busboy │ 0.03 ms ± 0.07 │ 3.59 ms ± 0.13 │ 0.36 ms ± 0.17  │ 35.26 ms ± 0.39 │
│  @fastify/busboy │ 0.04 ms ± 0.11 │ 7.23 ms ± 0.15 │ 0.63 ms ± 0.15  │ 71.86 ms ± 0.53 │
└──────────────────┴────────────────┴────────────────┴─────────────────┴─────────────────┘

> @mjackson/[email protected] bench:deno /Users/michael/Projects/multipart-parser
> deno --unstable-byonm --unstable-sloppy-imports run --allow-sys ./bench/runner.ts

Platform: Darwin (23.5.0)
CPU: Apple M1 Pro
Date: 8/18/2024, 4:24:16 PM
Deno 1.45.5
┌──────────────────┬──────────────────┬───────────────────┬──────────────────┬────────────────────┐
│ (idx)            │ 1 small file     │ 1 large file      │ 100 small files  │ 5 large files      │
├──────────────────┼──────────────────┼───────────────────┼──────────────────┼────────────────────┤
│ multipart-parser │ "0.01 ms ± 0.15" │ "1.00 ms ± 1.00"  │ "0.08 ms ± 0.39" │ "10.08 ms ± 0.41"  │
│ multipasta       │ "0.01 ms ± 0.14" │ "1.02 ms ± 1.00"  │ "0.17 ms ± 0.56" │ "14.59 ms ± 0.92"  │
│ busboy           │ "0.04 ms ± 0.28" │ "3.04 ms ± 1.00"  │ "0.30 ms ± 0.71" │ "29.86 ms ± 0.83"  │
│ @fastify/busboy  │ "0.05 ms ± 0.31" │ "12.36 ms ± 0.78" │ "0.78 ms ± 0.98" │ "123.54 ms ± 5.04" │
└──────────────────┴──────────────────┴───────────────────┴──────────────────┴────────────────────┘

Related Packages

  • form-data-parser - Uses multipart-parser internally to parse multipart requests and generate FileUploads for storage
  • headers - Used internally to parse HTTP headers and get metadata (filename, content type) for each MultipartPart

Credits

Thanks to Jacob Ebey who gave me several code reviews on this project prior to publishing.

License

See LICENSE