Formidable
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.
Install / Use
/learn @node-formidable/FormidableREADME
formidable [![npm version][npmv-img]][npmv-url] [![MIT license][license-img]][license-url] [![Libera Manifesto][libera-manifesto-img]][libera-manifesto-url] [![Twitter][twitter-img]][twitter-url]
A Node.js module for parsing form data, especially file uploads.
[![Code style][codestyle-img]][codestyle-url] [![linux build status][linux-build-img]][build-url] [![macos build status][macos-build-img]][build-url]
<!-- [![codecoverage][codecov-img]][codecov-url] -->If you have any how-to kind of questions, please read the [Contributing Guide][contributing-url] and [Code of Conduct][code_of_conduct-url] documents.<br /> For bugs reports and feature requests, [please create an issue][open-issue-url] or ping [@wgw_eth / @wgw_lol][twitter-url] at Twitter.
[![Conventional Commits][ccommits-img]][ccommits-url] [![Minimum Required Nodejs][nodejs-img]][npmv-url] [![Buy me a Kofi][kofi-img]][kofi-url] [![Make A Pull Request][prs-welcome-img]][prs-welcome-url]
<!-- [![Tidelift Subscription][tidelift-img]][tidelift-url] --> <!-- [![Renovate App Status][renovateapp-img]][renovateapp-url] -->This project is semantically versioned and if you want support in migrating between versions you can schedule us for training or support us through donations, so we can prioritize.
[!CAUTION] As of April 2025, old versions like v1 and v2 are still the most used, while they are deprecated for years -- they are also vulnerable to attacks if you are not implementing it properly. Please upgrade! We are here to help, and AI Editors & Agents could help a lot in such codemod-like migrations.
<!-- This project is [semantically versioned](https://semver.org) and available as part of the [Tidelift Subscription][tidelift-url] for professional grade assurances, enhanced support and security. [Learn more.](https://tidelift.com/subscription/pkg/npm-formidable?utm_source=npm-formidable&utm_medium=referral&utm_campaign=enterprise) _The maintainers of `formidable` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the Open Source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use._ -->[!TIP] If you are starting a fresh project, you can check out the
formidable-miniwhich is a super minimal version of Formidable (not quite configurable yet, but when it does it could become the basis forformidable@v4), using web standards like FormData API and File API, and you can use it to stream uploads directly to S3 or other such services.
[![][npm-weekly-img]][npmv-url] [![][npm-monthly-img]][npmv-url] [![][npm-yearly-img]][npmv-url] [![][npm-alltime-img]][npmv-url]
Project Status: Maintained
[!NOTE] Check VERSION NOTES for more information on v1, v2, and v3 plans, NPM dist-tags and branches._
This module was initially developed by @felixge for Transloadit, a service focused on uploading and encoding images and videos. It has been battle-tested against hundreds of GBs of file uploads from a large variety of clients and is considered production-ready and is used in production for years.
Currently, we are few maintainers trying to deal with it. :) More contributors are always welcome! :heart: Jump on issue #412 which is closed, but if you are interested we can discuss it and add you after strict rules, like enabling Two-Factor Auth in your npm and GitHub accounts.
Highlights
- Fast (~900-2500 mb/sec) & streaming multipart parser
- Automatically writing file uploads to disk (optional, see
options.fileWriteStreamHandler) - Plugins API - allowing custom parsers and plugins
- Low memory footprint
- Graceful error handling
- Very high test coverage
Install
This package is a dual ESM/commonjs package.
[!NOTE] This project requires
Node.js >= 20. Install it using yarn or npm.<br /> We highly recommend to use Yarn when you think to contribute to this project.
This is a low-level package, and if you're using a high-level framework it may already be included. Check the examples below and the examples/ folder.
# v2
npm install formidable@v2
# v3
npm install formidable
npm install formidable@v3
Note: Future not ready releases will be published on *-next dist-tags for the corresponding version.
Examples
For more examples look at the examples/ directory.
with Node.js http module
Parse an incoming file upload, with the
Node.js's built-in http module.
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') {
// parse a file upload
const form = formidable({});
let fields;
let files;
try {
[fields, files] = await form.parse(req);
} catch (err) {
// example to check for a very specific error
if (err.code === formidableErrors.maxFieldsExceeded) {
}
console.error(err);
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;
}
// show a file upload form
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<h2>With Node.js <code>"http"</code> module</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="multipleFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
server.listen(8080, () => {
console.log('Server listening on http://localhost:8080/ ...');
});
with Express.js
There are multiple variants to do this, but Formidable just need Node.js Request stream, so something like the following example should work just fine, without any third-party Express.js middleware.
Or try the examples/with-express.js
import express from 'express';
import formidable from 'formidable';
const app = express();
app.get('/', (req, res) => {
res.send(`
<h2>With <code>"express"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`);
});
app.post('/api/upload', (req, res, next) => {
const form = formidable({});
form.parse(req, (err, fields, files) => {
if (err) {
next(err);
return;
}
res.json({ fields, files });
});
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
with Koa and Formidable
Of course, with Koa v1, v2 or future v3 the things
are very similar. You can use formidable manually as shown below or through
the koa-better-body package which is
using formidable under the hood and support more features and different
request bodies, check its documentation for more info.
Note: this example is assuming Koa v2. Be aware that you should pass ctx.req
which is Node.js's Request, and NOT the ctx.request which is Koa's Request
object - there is a difference.
import Koa from 'Koa';
import formidable from 'formidable';
const app = new Koa();
app.on('error', (err) => {
console.error('server error', err);
});
app.use(async (ctx, next) => {
if (ctx.url === '/api/upload' && ctx.method.toLowerCase() === 'post') {
const form = formidable({});
// not very elegant, but that's for now if you don't want to use `koa-better-body`
// or other middlewares.
await new Promise((resolve, reject) => {
form.parse(ctx.req, (err, fields, files) => {
if (err) {
reject(err);
return;
}
ctx.set('Content-Type', 'application/json');
ctx.status = 200;
ctx.state = { fields, files };
ctx.body = JSON.stringify(ctx.state, null, 2);
resolve();
});
});
await next();
return;
}
// show a file upload form
ctx.set('Content-Type', 'text/html');
ctx.status = 200;
ctx.body = `
<h2>With <code>"koa"</code> npm package</h2>
<form action="/api/upload" enctype="multipart/form-data" method="post">
<div>Text field title: <input type="text" name="title" /></div>
<div>File: <input type="file" name="koaFiles" multiple="multiple" /></div>
<input type="submit" value="Upload" />
</form>
`;
});
app.use((ctx) => {
console.log('The next middleware is called');
console.log('Results:', ctx.state);
});
app.listen(3000, () => {
console.log('Server listening on http://localhost:3000 ...');
});
Benchmarks
The benchmark is quite old, from the old codebase. But maybe quite true though. Previously the numbers was around ~500 mb/sec. Currently with moving to the new Node.js Streams API it's faster. You can clearly see the differences between the Node versions.
_No
Related Skills
tmux
333.3kRemote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.
claude-opus-4-5-migration
82.0kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
blogwatcher
333.3kMonitor blogs and RSS/Atom feeds for updates using the blogwatcher CLI.
prd
Raito Bitcoin ZK client web portal.
