'x-www-form-urlencoded' or 'form-data' 😵 ? Explained in 2 mins.
Tags: html, javascript, webdev, http
Published: 2019-09-01 15:46:44

# TL;DR

If you need file uploads, `form-data` is your only option here. Otherwise, they serve the same job. `form-data` is a fancier way of encoding data than `x-www-form-urlencoded`. You can think of `x-www-form-urlencoded` as `.txt` file and `form-data` as `.html` file. In the end of day they both deliver some http payload.

Try **🏀 getd.io playground links 🏀** below to see what the headers and body look like:
- [Send a request with x-www-form-urlencoded](https://getd.io/workspace?r=%7B%22requestMode%22%3A%22BROWSER%22%2C%22method%22%3A%22POST%22%2C%22url%22%3A%22https%3A%2F%2Fgetd.io%2Fplayground%2Frequest%22%2C%22params%22%3A%5B%5D%2C%22headers%22%3A%5B%5D%2C%22body%22%3A%22%22%2C%22formData%22%3A%5B%5D%2C%22formUrl%22%3A%5B%7B%22isEnabled%22%3Atrue%2C%22key%22%3A%22username%22%2C%22value%22%3A%22techbos%22%7D%2C%7B%22isEnabled%22%3Atrue%2C%22key%22%3A%22password%22%2C%22value%22%3A%22Pa%24%24w0rd%22%7D%5D%2C%22bodyEditorFormat%22%3A%22formUrl%22%7D)
- [Send a request with form-data](https://getd.io/workspace?r=%7B%22requestMode%22%3A%22BROWSER%22%2C%22method%22%3A%22POST%22%2C%22url%22%3A%22https%3A%2F%2Fgetd.io%2Fplayground%2Frequest%22%2C%22params%22%3A%5B%5D%2C%22headers%22%3A%5B%5D%2C%22body%22%3A%22%22%2C%22formData%22%3A%5B%7B%22type%22%3A%22KEY_VALUE%22%2C%22data%22%3A%7B%22isEnabled%22%3Atrue%2C%22key%22%3A%22username%22%2C%22value%22%3A%22techbos%22%7D%7D%2C%7B%22type%22%3A%22KEY_VALUE%22%2C%22data%22%3A%7B%22isEnabled%22%3Atrue%2C%22key%22%3A%22password%22%2C%22value%22%3A%22Pa%24%24w0rd%22%7D%7D%5D%2C%22formUrl%22%3A%5B%5D%2C%22bodyEditorFormat%22%3A%22formData%22%7D)

# Content Type

|           | **content-type** |
|-----------|--------------|
| x-www-form-urlencoded    | `application/x-www-form-urlencoded` |
| form-data | `multipart/form-data; boundary={boundary string}`|

A quick note for `form-data`: Usually the browser generates a random `{boundary string}`, e.g., `----WebKitFormBoundaryKGUmWkAsjo5nUBp2`, but you can specify your own if you want. See below for examples.

# Request Payload

Let's say you have a login form with fields below:

| **Fields**   | **Values**   |
|----------|----------|
| username | techbos  |
| password | Pa$$w0rd |

When you post the form, the payload for `x-www-form-urlencoded` looks like below. Note how strings are `encodeURIComponent()`'d.

```
username=techbos&password=Pa%24%24w0rd
```

For `form-data`, each (key, value) pair is encoded in its own section, with `{boundary string}` as separator. Here I also included a sample section in the end to show you what a file upload looks like:

```
--{boundary string}
Content-Disposition: form-data; name="username",

techbos
--{boundary string}
Content-Disposition: form-data; name="password",

Pa$$w0rd
--{boundary string}
Content-Disposition: form-data; name="file"; filename="image.jpg"
Content-Type: image/jpeg,

--{boundary string}--
```
Explained inline:

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/pzucwhmiybpy01w42z0q.png)

# API to send request

|   | x-www-form-urlencoded | form-data |
| ---| --- |--- |
| [fetch()](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)     | `body` as [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams)                   | `body` as [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData)                                                                                                                                                                                                                                                                           |
| [request()](https://github.com/request/request#forms)   |  [`form` option](https://github.com/request/request#applicationx-www-form-urlencoded-url-encoded-forms) | [`formData` option](https://github.com/request/request#multipartform-data-multipart-form-uploads) |
| [axios()](https://github.com/axios/axios) | `data` as [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) | `data` as [`FormData`](https://developer.mozilla.org/en-US/docs/Web/API/FormData) |

# API to handle response

For `x-www-form-urlencoded`, use [bodyParser](https://github.com/expressjs/body-parser), which will parse payload into `req.body` in the format of `{ key, value }`. 

```javascript
express.use(bodyParser.urlencoded({ extended: true }));
express.post('/my-form-endpoint', (req, res) => {
  console.log(req.body.username); // print 'techbos'
});
```
Same functionality also comes built-in with [Express v4.16.0+](https://expressjs.com/en/4x/api.html#express.urlencoded).

For parsing `form-data`, you can use packages such as [busboy](https://github.com/mscdex/busboy) or [formidable](https://github.com/node-formidable/node-formidable). See their doc for how-to.

**What's your favorite library for sending / handling forms? Leave a comment below to share your experience ❤️❤️❤️!**

**Check out [getd.io](https://getd.io) and leave some feedback on what features you'd like to see next ❤️❤️❤️!**