busboy

A fast, streaming parser for multipart/form-data and URL-encoded HTTP request bodies in Node.js.

Library
npm
v1.6.0
2,999stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
40/100Fair
Development Activity0
Maintenance0
Community60
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
68/100Good
Architecture78
Code Quality72
Innovation65
Learning Curve55

Busboy is a low-level Node.js library for parsing incoming HTTP request bodies encoded as multipart/form-data or application/x-www-form-urlencoded. Rather than buffering an entire upload into memory, it processes the raw request stream incrementally, emitting file and field events as soon as each part’s boundary and headers are parsed, so large file uploads can be piped straight to disk, cloud storage, or another stream without ever holding the whole payload in RAM.

It ships with a single runtime dependency (streamsearch, for boundary detection) and implements the multipart parsing state machine by hand, including configurable limits for field/file sizes, counts, and header sizes. Because it exposes a plain Writable stream with a small, well-known event API, busboy has become the parsing engine underneath many popular upload middlewares, including Express’s multer and Fastify’s @fastify/multipart, rather than something most applications reach for directly.

What You Get

  • Streaming multipart/form-data parsing that emits Readable file streams instead of buffering uploads in memory
  • Built-in URL-encoded (application/x-www-form-urlencoded) body parsing alongside multipart support
  • Configurable limits for field size, file size, field/file/part counts, and header size to guard against abusive uploads
  • Character-set aware field and filename decoding, including RFC 5987 extended parameter values
  • A minimal event API (file, field, close, partsLimit, filesLimit, fieldsLimit) with a single runtime dependency

Common Use Cases

  • Parsing file uploads in a raw Node.js HTTP server without pulling in a full web framework
  • Powering higher-level upload middleware such as Express’s multer or Fastify’s @fastify/multipart
  • Streaming large file uploads directly to disk, S3, or another destination as they arrive, instead of buffering them
  • Extracting form field values from multipart or URL-encoded POST bodies in custom API servers

Under The Hood

Architecture lib/index.js dispatches based on the request’s Content-Type header to one of two Writable stream subclasses under lib/types/ (multipart.js, urlencoded.js), selected through a small static-detect()-based registry. Multipart.js implements a hand-written incremental state machine: a HeaderParser class parses each part’s header block byte-by-byte with an explicit state enum (name / pre-OWS / value), while a StreamSearch instance (from the streamsearch dependency) locates MIME boundaries and drives a callback that threads a matchPostBoundary state through boundary, header, and body transitions without ever buffering a whole part. Each detected file part gets its own FileStream (a Readable) whose backpressure is wired directly into the outer Writable’s _write callback, and the parser tracks how many file streams are still open so the final callback only fires once every file has finished. Data flow is single-pass and event-driven: one incoming Writable stream fans out into per-field and per-file emissions plus child Readable streams. Because boundary detection, header parsing, and backpressure all share mutable counters (parts, fields, files, matchPostBoundary), changing the core parsing loop would require re-verifying the whole state machine rather than one isolated layer.

Tech Stack package.json declares exactly one runtime dependency, streamsearch (^1.1.0), with no transpilation step — pure CommonJS targeting Node >=10.16.0. Dev dependencies are limited to @mscdex/eslint-config and eslint@7 for a lint / lint:fix script pair. There is no build step (main points straight at ./lib/index.js), no TypeScript, and no bundler. Tests run through a hand-rolled runner (test/test.js) that spawns each test-*.js file as a child process via Node’s built-in child_process.spawnSync and asserts with Node’s core assert module rather than a framework like Mocha or Jest. Benchmark scripts live under bench/ as standalone files. This is close to the minimum possible dependency footprint for a Node library — a deliberate choice for a low-level module that sits underneath many other packages.

Code Quality Tests exist and are substantial (test-types-multipart.js alone runs over a thousand lines, alongside dedicated files for URL-encoded bodies, multipart charsets, and stream-pause behavior), all using Node’s built-in assert module through the custom sequential runner — no coverage tooling or CI configuration was visible in the shallow clone, though. Error handling is explicit throughout the parser: malformed headers, missing content types, missing boundaries, and truncated streams all produce named Error objects (e.g. ‘Malformed part header’, ‘Unexpected end of form’) rather than failing silently. There is no TypeScript and no type annotations, but the code substitutes careful, defensive bounds and state checking (explicit byte-code comparisons such as code !== 58 for a colon) for type safety. ESLint is configured via @mscdex/eslint-config, and naming is terse but internally consistent (hparser, bparser, ssCb) with the low-level, performance-oriented style used throughout.

API Design The public API is a single default export function, busboy(config), returning a Node.js Writable stream — instantly familiar to any developer already comfortable with req.pipe(…): req.pipe(busboy({ headers: req.headers })). Event names (file, field, close, partsLimit, filesLimit, fieldsLimit) are self-descriptive, and every field/file callback receives a consistent info object carrying encoding and mimeType metadata. Configuration is a flat, well-documented limits object with sensible defaults (Infinity for counts, 1MB for field size) rather than an options-builder or subclassing requirement, and zero configuration is needed beyond passing headers to get a working parser. This low-ceremony surface is likely why busboy underlies form-data parsing in Express’s multer, Fastify’s @fastify/multipart, and other higher-level libraries rather than being reimplemented by each. It isn’t conceptually novel — it implements the well-known multipart/form-data spec (RFC 7578) — but its zero-dependency, backpressure-aware streaming implementation is more careful about memory than many alternatives that buffer entire files before exposing them.

Used by 9 apps in this directory

TypeScript
92%
GPL 3.0

Blinko

Knowledge Management · Note Taking

10,992

A self-hosted, AI-powered card note-taking tool that lets you capture fleeting thoughts instantly and retrieve them with natural language search.

View details
80
Repo Health
69
Technical
63
Dependency
Built with
TypeScript92%
Updated 1 weeks ago
TypeScript
81%
Other

Directus

CMS · Low Code Platforms

37,783

Connect any SQL database and get instant REST and GraphQL APIs, a visual management Studio, and a native MCP server for AI agents — free for most organizations.

View details
92
Repo Health
82
Technical
76
Dependency
Built with
TypeScript81%
Vue18%
Updated 3 days ago
JavaScript
47%
MIT

Ghost

CMS · Blogging

55,191

Open source headless Node.js CMS for professional publishing, paid memberships, and newsletters with a fully owned audience.

View details
96
Repo Health
85
Technical
67
Dependency
Built with
JavaScript47%
TypeScript47%
Updated yesterday
TypeScript
92%
Other

GitNexus

Developer Tools · AI Code Assistants

47,086

Index any codebase into an interactive knowledge graph and give your AI agents deep architectural context via MCP — with zero servers required.

View details
88
Repo Health
86
Technical
73
Dependency
Built with
TypeScript92%
Updated yesterday
TypeScript
94%
AGPL 3.0

Papra

Bookmarks Archiving

5,296

Self-hosted document archiving with email ingestion, OCR full-text search, and pluggable storage — store once, find anything.

View details
86
Repo Health
82
Technical
69
Dependency
Built with
TypeScript94%
Updated yesterday
TypeScript
96%
MIT

Payload CMS

Developer Tools · Blogging · CMS

44,600

The open-source, Next.js-native headless CMS that lives inside your /app folder and gives you a full TypeScript backend instantly.

View details
91
Repo Health
88
Technical
65
Dependency
Built with
TypeScript96%
Updated 3 days ago
TypeScript
58%
AGPL 3.0

Puter

File Storage · Developer Tools

43,424

A self-hostable, web-based internet OS with desktop GUI, cloud storage, AI drivers, and a developer SDK — all running in your browser.

View details
88
Repo Health
88
Technical
70
Dependency
Built with
TypeScript58%
JavaScript38%
Updated yesterday
TypeScript
97%
Other

Rocket.Chat

Team Chat

46,089

The secure, self-hosted team communications platform for organizations that cannot compromise on data sovereignty.

View details
96
Repo Health
79
Technical
66
Dependency
Built with
TypeScript97%
Updated yesterday
TypeScript
98%
Apache 2.0

TinaCMS

CMS

13,780

An open-source, Git-backed headless CMS that gives editors a live visual editing UI over Markdown, MDX, JSON, and YAML content while developers keep everything in version control.

View details
92
Repo Health
74
Technical
59
Dependency
Built with
TypeScript98%
Updated today

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search