Last updated: Apr 4, 2024
Reading timeยท6 min

FormDataTo POST form data using the JavaScript fetch API:
submit event handler to the form element.FormData() constructor to create a FormData object.fetch() method to send the FormData object over the networking,
setting the HTTP method to POST.Here is the HTML for the example.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <h2>bobbyhadz.com</h2> <form id="form"> <input type="text" id="username" name="username" /> <br /> <br /> <input type="password" id="password" name="password" autocomplete="on" /> <br /> <br /> <button type="submit" id="submit-btn">Log in</button> </form> <script src="index.js"></script> </body> </html>
And here is the related JavaScript code.
const form = document.getElementById('form'); form.addEventListener('submit', async event => { event.preventDefault(); const data = new FormData(form); console.log(Array.from(data)); try { const res = await fetch( 'https://jsonplaceholder.typicode.com/users', { method: 'POST', body: data, }, ); const resData = await res.json(); console.log(resData); } catch (err) { console.log(err.message); } });

We used the document.getElementById()
method to select the form element and
added a submit event handler to it.
Notice that we marked the event handler function as
async to be able to use the
await keyword.
form.addEventListener('submit', async event => { // ... })
We called the event.preventDefault() method to prevent the browser from
refreshing the page.
event.preventDefault();
The next step is to use the FormData() constructor to create a FormData object.
The FormData object stores a set of key-value pairs representing form fields
and their values.
The set of key-value pairs can be sent over the network using fetch, axios,
XMLHttpRequest.send(), etc.
const data = new FormData(form); // [ // ["username", "ab"], // ["password", "cd"] // ] console.log(Array.from(data)); try { const res = await fetch( 'https://jsonplaceholder.typicode.com/users', { method: 'POST', body: data, }, ); const resData = await res.json(); console.log(resData); } catch (err) { console.log(err.message); }
Notice that we aren't using JSON.stringify() when sending over the request body.
The FormData object uses the same format a form would use if its encoding type
were set to multipart/form-data.
Notice that when the FormData object is converted to an array, it stores a
two-dimensional array.
const data = new FormData(form); // [ // ["username", "ab"], // ["password", "cd"] // ] console.log(Array.from(data));
The first element in each subarray is the key and the second is the value.
Make sure to set the method property in the options object to POST and the
body property to the FormData object.
const res = await fetch( 'https://jsonplaceholder.typicode.com/users', { method: 'POST', body: data, }, );
To view the request payload:
F12.
As shown in the screenshot the username field stores a value of ab and the
password field stores a value of cd at the time of making the request.
If you click on the Headers tab and scroll down to the Request Headers
section, you will see that fetch automatically sets the Content-Type header.

The header is automatically set to multipart/form-data; boundary=---....
If you've explicitly set the Content-Type header when calling fetch() make
sure to remove it, so it gets set automatically.
When sending text form data over the network, it is more efficient to send the
data as application/x-www-form-urlencoded by using the
URLSearchParams()
constructor.
The HTML for the example remains the same.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <h2>bobbyhadz.com</h2> <form id="form"> <input type="text" id="username" name="username" /> <br /> <br /> <input type="password" id="password" name="password" autocomplete="on" /> <br /> <br /> <button type="submit" id="submit-btn">Log in</button> </form> <script src="index.js"></script> </body> </html>
And here is the related JavaScript code.
const form = document.getElementById('form'); form.addEventListener('submit', async event => { event.preventDefault(); const formData = new FormData(form); // ๐๏ธ pass form data to URLSearchParams() constructor const searchParams = new URLSearchParams(formData); // ๐๏ธ username=ab&password=cd console.log(searchParams.toString()); try { const res = await fetch( 'https://jsonplaceholder.typicode.com/users', { method: 'POST', body: searchParams, }, ); const resData = await res.json(); console.log(resData); } catch (err) { console.log(err.message); } });

We used the FormData() constructor to create a FormData object and passed
the FormData object to the URLSearchParams() constructor.
const formData = new FormData(form); // ๐๏ธ pass form data to URLSearchParams() constructor const searchParams = new URLSearchParams(formData); // ๐๏ธ username=ab&password=cd console.log(searchParams.toString());
The URLSearchParams() constructor creates a URLSearchParams object.
URLSearchParams objects define utility methods that enable you to work with
the query string of a URL.
toString() method on the object returns a query string (without the leading question mark ?).If you click on the Payload tab for the specific request in the Network tab in your developer tools, you will see that the correct Form Data is sent over the network.

If you click on the Headers tab and scroll down to the Request Headers
section, you will see that the Content-Type is set to
application/x-www-form-urlencoded.

The Content-Type is set automatically by fetch, so we didn't have to
explicit set it.
const res = await fetch( 'https://jsonplaceholder.typicode.com/users', { method: 'POST', body: searchParams, }, );
The application/x-www-form-urlencoded content type is used to describe form
data that is sent in a single block in the HTTP body.
If the data is sent in the query parameters part of the URL, its size is restricted.
However, when you send the data in the request body as we did in the example, its size is unrestricted.
FormDataYou might also see examples online that manually build the FormData object.
The HTML for the example remains the same.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> </head> <body> <h2>bobbyhadz.com</h2> <form id="form"> <input type="text" id="username" name="username" /> <br /> <br /> <input type="password" id="password" name="password" autocomplete="on" /> <br /> <br /> <button type="submit" id="submit-btn">Log in</button> </form> <script src="index.js"></script> </body> </html>
And here is the updated JavaScript code.
const form = document.getElementById('form'); const username = document.getElementById('username'); const password = document.getElementById('password'); form.addEventListener('submit', async event => { event.preventDefault(); const formData = new FormData(); formData.append('username', username.value); formData.append('password', password.value); console.log(Array.from(formData)); try { const res = await fetch( 'https://jsonplaceholder.typicode.com/users', { method: 'POST', body: formData, }, ); const resData = await res.json(); console.log(resData); } catch (err) { console.log(err.message); } });

Notice that this time, we created an empty FormData object.
const formData = new FormData(); formData.append('username', username.value); formData.append('password', password.value); // [ // ["username", "ab"], // ["password", "cd"] // ] console.log(Array.from(formData));
The
FormData.append()
method can be used to append a new key-value pair to the FormData object.
The first parameter the append() method takes is the name of the key and the
second is the name of the value.
If the key already exists in the FormData object, its value gets updated,
otherwise, the new key-value pair gets added to the FormData object.
However, most of the time manually constructing the FormData object is not
necessary as it can be automatically done by passing the form element to the
FormData() constructor.
const data = new FormData(form); // [ // ["username", "ab"], // ["password", "cd"] // ] console.log(Array.from(data));
You should only build the FormData object manually if you need to overwrite
the values of specific keys.
You can learn more about the related topics by checking out the following tutorials: