JavaScript FormData
Learn the JavaScript FormData API: create FormData objects, read and modify fields with get, append, set and delete, and send data and files with fetch.
Handling form data efficiently is essential for building dynamic, interactive web pages. JavaScript provides the FormData API for exactly this: it lets you collect the fields of a form, build key/value sets programmatically, and send them to a server — including files. This guide covers what FormData is, how to create and read it, every method it exposes, how to send it with fetch, and the common gotchas.
Understanding FormData
FormData is a built-in JavaScript object that represents a set of key/value pairs, modeled on the way a browser submits an HTML form. It simplifies gathering information from HTML forms and sending it to a server asynchronously with the Fetch API.
Why use it instead of building a plain object?
- It reads existing form fields automatically — no manual
valueextraction per input. - It supports files and
Blobs, which plain objects and JSON cannot carry. - When passed to
fetch, the browser sets the correctContent-Type(multipart/form-data) with the right boundary for you.
Creating FormData Objects
Create a FormData object with the FormData() constructor. If you pass a <form> element, every named, enabled field in that form is captured up front. You can inspect the contents by iterating its entries() method, which returns an iterator of [key, value] pairs:
<script>
function onSubmit(event) {
event.preventDefault();
const form = document.getElementById('myForm');
const formData = new FormData(form);
let results = '';
for (const [key, value] of formData.entries()) {
results += `${key}: ${value}\n`;
}
alert(results)
}
</script>
<form id="myForm" onsubmit="onSubmit(event)">
<input type="text" name="username" value="John Doe" />
<input type="email" name="email" value="[email protected]" />
<input type="submit" />
</form>Accessing Form Data
Read a single field with get(), or iterate through all fields with entries() as shown above. get() returns the first value for a key (or null if it does not exist):
<form id="myForm" onsubmit="onSubmit(event)">
<input type="text" name="username" value="John Doe" />
<input type="email" name="email" value="[email protected]" />
<input type="submit" />
</form>
<script>
function onSubmit(event) {
const form = document.getElementById('myForm');
const formData = new FormData(form);
const username = formData.get('username');
const email = formData.get('email');
alert(`username: ${username}; email: ${email}`);
}
</script>FormData Methods
Beyond reading an existing form, FormData lets you build and modify the data set by hand. The following methods are available on every instance:
| Method | What it does |
|---|---|
append(name, value) | Adds a new value. If the key already exists, keeps the old one and adds another, so a key can have multiple values. |
set(name, value) | Sets the value for a key, replacing any existing values for that key. |
get(name) | Returns the first value for the key, or null. |
getAll(name) | Returns an array of all values for the key. |
has(name) | Returns true if the key exists. |
delete(name) | Removes all values for the key. |
entries() / keys() / values() | Iterators over the pairs, keys, or values. |
The difference between append and set is the most common source of bugs:
const fd = new FormData();
fd.append('tag', 'js');
fd.append('tag', 'web'); // append keeps both
console.log(fd.getAll('tag')); // [ 'js', 'web' ]
fd.set('tag', 'html'); // set replaces all
console.log(fd.getAll('tag')); // [ 'html' ]
console.log(fd.has('tag')); // true
fd.delete('tag');
console.log(fd.has('tag')); // falseYou can also build a FormData entirely in code — without any form — by appending fields directly. A third argument to append/set sets the filename when the value is a Blob or File.
Sending FormData with Fetch API
A common use case for FormData is sending form data to the server asynchronously. Pass the FormData instance as the body of a fetch request — the browser automatically sets the Content-Type to multipart/form-data with the correct boundary, so do not set that header yourself:
<form id="myForm" onsubmit="onSubmit(event)">
<input type="text" name="title" value="A title" />
<input type="text" name="body" value="A body" />
<input type="submit" value="Submit Post" />
</form>
<div>post id: <span id="response"></span></div>
<script>
function onSubmit(event) {
event.preventDefault();
const form = document.getElementById('myForm');
const formData = new FormData(form);
const responseSpan = document.getElementById('response');
fetch('https://jsonplaceholder.typicode.com/posts', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => { responseSpan.innerHTML = data.id; })
.catch(error => console.error('Error:', error));
}
</script>When you pass your form to the FormData constructor, it automatically includes all form fields in the HTML form, including hidden fields. This can lead to unexpected behavior if you're not careful, especially if there are sensitive or unnecessary fields in the form.
Handling File Uploads
FormData is the standard way to upload files, because it produces a multipart/form-data request that can carry binary content alongside text fields. When you build the FormData from a form that contains a <input type="file"> input, the selected file is already included — there is no need to read input.files and append it again:
<form id="fileUploadForm">
<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>
<script>
const form = document.getElementById('fileUploadForm');
form.addEventListener('submit', (event) => {
event.preventDefault();
// The file input is captured automatically from the form.
const formData = new FormData(form);
fetch('https://httpbin.org/post', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => console.log('Upload successful:', data))
.catch(error => console.error('Error:', error));
});
</script>To attach a file that is not part of a form — for example one selected programmatically — append it explicitly, optionally giving it a filename:
const formData = new FormData();
formData.append('avatar', fileObject, 'profile.png');FormData vs. URLSearchParams
Both wrap key/value pairs, but they serialize differently. Use FormData when you need to send files or multipart/form-data. Use URLSearchParams when you only have text and want a compact application/x-www-form-urlencoded body (or a query string). You can even construct one from the other when every value is a string:
const fd = new FormData();
fd.append('q', 'cats');
fd.append('page', '2');
const params = new URLSearchParams(fd);
console.log(params.toString()); // q=cats&page=2Conclusion
FormData is a versatile and powerful tool for managing form data in JavaScript applications. Whether you're handling simple text inputs or complex file uploads, FormData simplifies the process and provides a convenient interface for interacting with form data. By mastering FormData, you can enhance the interactivity and responsiveness of your web applications, delivering a seamless user experience.