Open-source project
node-formidable/formidable avatar
node-formidable/formidable

Formidable: the Node.js multipart parser behind file uploads

The most used, flexible, fast and streaming parser for multipart form data. Supports uploading to serverless environments, AWS S3, Azure, GCP or the filesystem. Used in production.

7,176 stars688 forksJavaScriptMIT

At a glance

What is it?
Formidable parses multipart/form-data in Node.js without buffering whole uploads in memory. It is a low-level library for people who already own the request stream, not a form builder.
Who is it for?
Adopt Formidable if you are writing the upload endpoint yourself and you want the request stream parsed as it arrives rather than held in memory. Do not adopt it if you expected a form builder, a WordPress plugin or an upload UI; it is a parser and nothing else.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 22 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Formidable solves: parsing multipart bodies without buffering them

Node's built-in http module hands you a readable request stream. It does not tell you where one uploaded file ends and the next begins. A multipart/form-data body is a sequence of parts separated by a boundary string the client chose, each part carrying its own headers, and a file part can be gigabytes long. Reading the whole body into a Buffer first is the obvious implementation and the wrong one for uploads.

Formidable takes that stream and emits fields and files as it goes. The README describes it as "a Node.js module for parsing form data, especially file uploads" and lists a low memory footprint among its highlights. The audience is narrow on purpose: backend engineers who already have a request object, either from node:http or from a framework that exposes one. If you are looking for a drag-and-drop upload widget, or the WordPress plugin that shares the name, you are in the wrong repository.

How the parser works: IncomingForm, plugins and the request stream

The central object is the form instance. You create one with an options object and call parse on the request. The promise resolves to a two-element array, fields first and files second, which is why the README example destructures it as [fields, files].

The package is dual ESM and CommonJS. The exports map in package.json points the import condition at ./src/index.js and the require condition at ./dist/index.cjs, so the same package name gives you a native ES module under import and a bundled CommonJS file under require. That matters if you are mixing module systems in one project.

Parsing is extensible through a plugins API, which the README lists as "allowing custom parsers and plugins". The repository also ships separate parsers under src/parsers, and package.json exposes ./src/parsers/*.js as a subpath export. File writes are optional. By default uploads are written to disk, and options.fileWriteStreamHandler lets you substitute your own writable stream, which is how the S3 example in examples/store-files-on-s3.js avoids touching the local filesystem. Errors carry an httpCode property and a code, and the README's example compares err.code against formidableErrors.maxFieldsExceeded, an exported error constant. The library gives you a status code to return; it does not decide your response body.

Installing Formidable and parsing a first upload

The README requires Node.js >= 20 and recommends yarn, though npm works. The package is published on the latest dist-tag as v3, while v2 is still installable by pinning the major. Prereleases go to *-next dist-tags.

bash
npm install formidable

That installs the current v3 line. If you need the older major for an existing codebase, the README gives the pinned form:

bash
npm install formidable@v2

The README warns that v1 and v2 remain the most used versions even though they have been deprecated for years, and that they are vulnerable when not implemented properly. Check what your lockfile already resolves before adding anything new; a framework may have pulled Formidable in as a transitive dependency.

A first real use, adapted from the README's node:http example, parses a POST to /api/upload and returns the fields and files as JSON. The form is created with an empty options object, and parse is awaited.

js
import http from "node:http";
import formidable, { errors as formidableErrors } from "formidable";

const server = http.createServer(async (req, res) => {
  if (req.url === "/api/upload" && req.method.toLowerCase() === "post") {
    const form = formidable({});
    let fields;
    let files;
    try {
      [fields, files] = await form.parse(req);
    } catch (err) {
      if (err.code === formidableErrors.maxFieldsExceeded) {
      }
      res.writeHead(err.httpCode || 400, { "Content-Type": "text/plain" });
      res.end(String(err));
      return;
    }
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify({ fields, files }, null, 2));
    return;
  }
});

server.listen(8080);

Point a browser at the server and submit a form with enctype="multipart/form-data". You should get a JSON body containing the text field and the uploaded file's metadata. The README's own example serves that HTML form from the same handler and listens on port 8080.

Express, Koa and the middleware you do not need

The README is explicit that Formidable needs only the Node.js request stream, so an Express route can call parse directly without any third-party middleware. The examples directory carries variants for Express, Koa 2 and the plain http module, plus narrower cases: urlencoded bodies with no enctype, forcing a buffer, multiple files, and logging file content to the console.

This is the part people get wrong. Because a middleware ecosystem exists around the name, it is easy to install a wrapper and then wonder why options do not apply. The library's own position is that the wrapper is unnecessary. If you are on Express and you add a body parser in front of Formidable, you have two parsers competing for the same stream, and the second one will see an exhausted request.

Where Formidable is the wrong tool

Formidable is a parser, and the boundary is worth stating plainly. It does not build forms, validate field semantics, resize images, or scan uploads. If your problem is rendering a form in WordPress, this package is unrelated to it despite the shared name.

The v1 and v2 situation is the real operational risk. The README's caution block says those versions are still the most used and have been deprecated for years, and that they are vulnerable to attacks when not implemented properly. A project that depends on Formidable transitively may be running a deprecated major without anyone having chosen it. That is a migration problem, not a bug in v3, and the README points at VERSION_NOTES.md and suggests codemod-style migrations with AI editors.

Resource limits are the other edge. The README example checks for a maxFieldsExceeded error, which tells you the library enforces limits you configure. It will not pick sensible ones for you. An endpoint that accepts uploads without setting file size and field count limits is exposed to whatever a client decides to send.

Finally, the serverless topic tag and the S3, Azure and GCP references describe where files can be written, not a managed upload service. You still own the bucket, the credentials and the cleanup.

Formidable compared with busboy

Busboy is the obvious alternative and the difference is architectural rather than cosmetic. Busboy is a pure streaming parser: you attach listeners for file and field events and pipe each file stream somewhere yourself. Nothing is written to disk unless you write it.

Formidable wraps that style of parsing in a form object with an options bag, resolves a promise with fields and files, and, by default, writes uploads to disk. Its fileWriteStreamHandler option is the escape hatch for sending the stream elsewhere, and examples/store-files-on-s3.js shows the S3 case. The trade-off is legibility against control. Formidable's promise-shaped API is easier to read in an async handler; Busboy's event API gives you the raw stream at the moment it appears, which some pipelines need. Formidable also carries a plugin system and separate parser modules, so the surface area is larger than a minimal multipart parser.

Maintenance, licensing and the cost of upgrading

The repository is not archived, and the last push was on 2026-09-08. The most recent release listed is v3.5.4 on 2026-04-15, following v3.5.3 on 2025-04-18 and v3.5.2 on 2024-11-03. The README labels the project status as Maintained and says a small number of maintainers handle it, with contributions welcome. Release cadence is irregular rather than scheduled, so plan upgrades around versions you can pin, not around a promise of frequent patches.

The package is MIT licensed, which permits commercial use and modification; the repository's LICENSE file is the authoritative text and this is not legal advice. The README states the project is semantically versioned. It also says that migration support between versions can be scheduled through training or donations, which is a candid way of saying that major-version migrations are not free and that help is a paid arrangement.

Upgrade cost concentrates in the v1 and v2 to v3 jump. The README's caution block treats that migration as the main outstanding problem in the ecosystem, and VERSION_NOTES.md is named as the place where the v1, v2 and v3 plans, dist-tags and branches are documented. Budget for reading it before you touch a dependency version.

Editorial conclusion

Adopt Formidable if you are writing the upload endpoint yourself and you want the request stream parsed as it arrives rather than held in memory. Do not adopt it if you expected a form builder, a WordPress plugin or an upload UI; it is a parser and nothing else. Before you commit, verify that your runtime is Node.js 20 or newer, confirm which major version your dependency tree already pulls in, and decide what you will set for maxFileSize and maxFields, because the library will otherwise accept whatever the client sends.

Frequently asked questions

What is Formidable in Node.js?

It is a Node.js module for parsing form data, especially file uploads, and it handles multipart/form-data as a stream rather than buffering the whole body. The README describes it as a low-level package that may already be included by a high-level framework.

How do I install Formidable in Node.js?

Run npm install formidable for the current v3 line, or npm install formidable@v2 if you need the older major. The package requires Node.js >= 20 according to the README.

How do I use Formidable to parse an upload?

Create a form with formidable({}) and await form.parse(req), which resolves to fields and files in that order. The README's http example then returns them as JSON and maps err.httpCode to the response status.

Official sources

  1. Issues
  2. License: MIT
  3. node-formidable/formidable on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/node-formidable-formidable.svg)](https://hysenlabs.com/projects/node-formidable-formidable)