FormData

While formdata-node ships with its own File and Blob implementations, these might eventually be removed in favour of Node.js' Blob (introduced in v14.18) and File (when it will be introduced). In order to help you smoothen that transition period, our own Blob and File , as well as FormData itself, provides support Blob objects created by Node.js' implementation.

Installation

You can install this package with npm:

npm install formdata-node 
yarn add formdata-node 
pnpm add formdata-node 

ESM/CJS support

This package is build for and bundled for both ESM and CommonJS, so you can use it in both environments.

Usage

  1. Let's take a look at minimal example with got:
import FormData> from "formdata-node" // I assume Got >= 12.x is used for this example import got from "got" const form = new FormData() form.set("greeting", "Hello, World!") const data = await got.post("https://httpbin.org/post", body: form>).json() console.log(data.form.greeting) // => Hello, World!
  1. If your HTTP client does not support spec-compliant FormData, you can use form-data-encoder to encode entries:
import Readable> from "stream" import FormDataEncoder> from "form-data-encoder" import FormData> from "formdata-node" // Note that `node-fetch` >= 3.x have builtin support for spec-compliant FormData, sou you'll only need the `form-data-encoder` if you use `node-fetch` import fetch from "node-fetch" const form = new FormData() form.set("field", "Some value") const encoder = new FormDataEncoder(form) const options =  method: "post", headers: encoder.headers, body: Readable.from(encoder) > await fetch("https://httpbin.org/post", options)
  1. Sending files over form-data:
import FormData, File> from "formdata-node" // You can use `File` from fetch-blob >= 3.x import fetch from "node-fetch" const form = new FormData() const file = new File(["My hovercraft is full of eels"], "file.txt") form.set("file", file) await fetch("https://httpbin.org/post", method: "post", body: form>)
  1. Blobs as field's values allowed too:
import FormData, Blob> from "formdata-node" // You can use `Blob` from fetch-blob const form = new FormData() const blob = new Blob(["Some content"], type: "text/plain">) form.set("blob", blob) // Will always be returned as `File` let file = form.get("blob") // The created file has "blob" as the name by default console.log(file.name) // -> blob // To change that, you need to set filename argument manually form.set("file", blob, "some-file.txt") file = form.get("file") console.log(file.name) // -> some-file.txt
  1. You can use 3rd party Blob as FormData value, as vell as for BlobParts in out Blob implementation:
import FormData, Blob> from "formdata-node" import Blob as FetchBlob> from "fetch-blob" const input = new FetchBlob(["a", "b", "c"]) const blob = new Blob([input]) // Accepts 3rd party blobs as BlobParts await blob.text() // -> abc const form = new FormData() form.set("file", input) const file = form.get("file") // -> File await file.text() // -> abc
  1. You can also use Node.js' Blob implementation in these scenarios:
import Blob as NodeBlob> from "node:buffer" import FormData, Blob> from "formdata-node" const input = new NodeBlob(["a", "b", "c"]) const blob = new Blob([input]) // Accepts Node.js' Blob implementation as BlobParts await blob.text() // -> abc const form = new FormData() form.set("file", input) const file = form.get("file") // -> File await file.text() // -> abc
  1. You can also append files using fileFromPath or fileFromPathSync helpers. It does the same thing as fetch-blob/from , but returns a File instead of Blob :
import fileFromPath> from "formdata-node/file-from-path" import FormData> from "formdata-node" import fetch from "node-fetch" const form = new FormData() form.set("file", await fileFromPath("/path/to/a/file")) await fetch("https://httpbin.org/post", method: "post", body: form>)
  1. You can still use files sourced from any stream, but unlike in v2 you'll need some extra work to achieve that:
import Readable> from "stream" import FormData> from "formdata-node" class BlobFromStream  #stream constructor(stream, size)  this.#stream = stream this.size = size > stream()  return this.#stream > get [Symbol.toStringTag]()  return "Blob" > > const content = Buffer.from("Stream content") const stream = new Readable( read()  this.push(content) this.push(null) > >) const form = new FormData() form.set("stream", new BlobFromStream(stream, content.length), "file.txt") await fetch("https://httpbin.org/post", method: "post", body: form>)
  1. Note that if you don't know the length of that stream, you'll also need to handle form-data encoding manually or use form-data-encoder package. This is necessary to control which headers will be sent with your HTTP request:
import Readable> from "stream" import Encoder> from "form-data-encoder" import FormData> from "formdata-node" const form = new FormData() // You can use file-shaped or blob-shaped objects as FormData value instead of creating separate class form.set("stream",  type: "text/plain", name: "file.txt", [Symbol.toStringTag]: "File", stream()  return getStreamFromSomewhere() > >) const encoder = new Encoder(form) const options =  method: "post", headers:  "content-type": encoder.contentType >, body: Readable.from(encoder) > await fetch("https://httpbin.org/post", method: "post", body: form>)

Comparison

formdata-node formdata-polyfill undici FormData form-data
.append() ✔️ ✔️ ✔️ ✔️ 1
.set() ✔️ ✔️ ✔️
.get() ✔️ ✔️ ✔️
.getAll() ✔️ ✔️ ✔️
.forEach() ✔️ ✔️ ✔️
.keys() ✔️ ✔️ ✔️
.values() ✔️ ✔️ ✔️
.entries() ✔️ ✔️ ✔️
Symbol.iterator ✔️ ✔️ ✔️
ESM ✔️ ✔️ ✔️ 2 ✔️ 2
Blob ✔️ 3 ✔️ 4 ✔️ 3
Browser polyfill ✔️ ✔️
Builtin encoder ✔️ ✔️ 5 ✔️

1 Does not support Blob and File in entry value, but allows streams and Buffer (which is not spec-compliant, however).

2 Can be imported in ESM, because Node.js support for CJS modules in ESM context, but it does not have ESM entry point.

3 Have builtin implementations of Blob and/or File, allows native Blob and File as entry value.

4 Support Blob and File via fetch-blob package, allows native Blob and File as entry value.

5 Have multipart/form-data encoder as part of their fetch implementation.

✔️ - For FormData methods, indicates that the method is present and spec-compliant. For features, shows its presence.

❌ - Indicates that method or feature is not implemented.

API

class FormData

constructor() ->

Creates a new FormData instance.

Instance methods

set(name, value[, filename]) ->

Set a new value for an existing key inside FormData, or add the new field if it does not already exist.

append(name, value[, filename]) ->

Appends a new value onto an existing key inside a FormData object, or adds the key if it does not already exist.

The difference between set() and append() is that if the specified key already exists, set() will overwrite all existing values with the new one, whereas append() will append the new value onto the end of the existing set of values.

get(name) ->

Returns the first value associated with a given key from within a FormData object. If you expect multiple values and want all of them, use the getAll() method instead.

getAll(name) -> >

Returns all the values associated with a given key from within a FormData object.

has(name) ->

Returns a boolean stating whether a FormData object contains a certain key.

delete(name) ->

Deletes a key and its value(s) from a FormData object.

forEach(callback[, thisArg]) ->

Executes a given callback for each field of the FormData instance