JavaScriptBeginner

JavaScript FormData: Collect Form Data for APIs

Learn how to collect form values with FormData, read entries, build request data and send forms to APIs.

All JavaScript lessons

What you will learn

Reading every form field manually works for small forms, but it becomes repetitive when a form has many fields.

FormData gives you a simple way to collect the fields of a form into one object-like structure. In this lesson you will learn how to create FormData, read its entries, work with checkboxes and files, and convert form data into JSON when an API needs JSON.

The concept

Suppose you have this form:

<form id="profile-form">
  <input name="name" type="text">
  <input name="email" type="email">
  <input name="age" type="number">
  <button type="submit">Save</button>
</form>

You can collect the form with:

const form = document.getElementById("profile-form");
const formData = new FormData(form);

Now formData contains the successful form controls that have names.

Tip: A form control normally needs a name attribute to be included when FormData is created from a form.

Why name matters

This will be included:

<input name="email" type="email">

This will not provide a named field:

<input id="email" type="email">

The id is useful for JavaScript and labels, but FormData uses the control’s name.

Reading FormData

You can read a value with .get():

const formData = new FormData(form);

console.log(formData.get("name"));
console.log(formData.get("email"));

For example, if the user enters:

Name: Riya
Email: riya@example.com

then:

console.log(formData.get("name"));  // Riya
console.log(formData.get("email")); // riya@example.com

If the field does not exist, .get() returns null.

Loop through all form data

Use entries():

for (const [key, value] of formData.entries()) {
  console.log(key, value);
}

You can also use:

for (const [key, value] of formData) {
  console.log(key, value);
}

This is useful for debugging or when you do not know all the fields in advance.

Convert FormData to an object

A very useful pattern is:

const data = Object.fromEntries(formData.entries());

console.log(data);

For this form:

<input name="name" value="Riya">
<input name="email" value="riya@example.com">

you get an object similar to:

{
  name: "Riya",
  email: "riya@example.com"
}

Converting to JSON

If an API expects JSON:

const data = Object.fromEntries(formData.entries());

const json = JSON.stringify(data);

console.log(json);

You can send it with fetch():

fetch("/api/users", {
  method: "POST",
  headers: {
    "Content-Type": "application/json"
  },
  body: JSON.stringify(data)
});

Tip: FormData itself is not JSON. Convert it to an object and then use JSON.stringify() when your API expects JSON.

Sending FormData directly with fetch

If the server accepts multipart/form-data, you can send FormData directly:

const formData = new FormData(form);

fetch("/api/users", {
  method: "POST",
  body: formData
});

Do not manually set:

headers: {
  "Content-Type": "multipart/form-data"
}

when sending FormData directly from the browser. The browser needs to add the correct boundary automatically.

FormData is useful for file uploads

Suppose your form contains:

<form id="upload-form">
  <input name="username" type="text">
  <input name="avatar" type="file">
  <button type="submit">Upload</button>
</form>

Then:

const form = document.getElementById("upload-form");
const formData = new FormData(form);

console.log(formData.get("username"));
console.log(formData.get("avatar"));

The avatar value can be a File object.

You can send the complete form:

fetch("/api/profile", {
  method: "POST",
  body: formData
});

This is one of the most common real-world uses of FormData.

append() and set()

You can add data manually.

const formData = new FormData();

formData.append("name", "Riya");
formData.append("course", "JavaScript");

Read it:

console.log(formData.get("name"));
console.log(formData.get("course"));

append() can create multiple values

formData.append("skill", "HTML");
formData.append("skill", "CSS");
formData.append("skill", "JavaScript");

Now there are multiple skill entries.

console.log(formData.getAll("skill"));

Result:

["HTML", "CSS", "JavaScript"]

set() replaces the existing value

formData.set("name", "Karan");

If name already exists, set() replaces its value.

A simple difference:

Method What it does
append() Adds another value
set() Sets/replaces the value

Check whether a field exists

Use .has():

if (formData.has("email")) {
  console.log("Email exists");
}

Delete a field

formData.delete("age");

This can be useful when you want to remove optional data before sending a request.

Checkboxes and FormData

Consider:

<label>
  <input name="newsletter" type="checkbox" value="yes">
  Subscribe to newsletter
</label>

If the checkbox is checked, it can appear in FormData:

const formData = new FormData(form);

console.log(formData.get("newsletter"));

If it is not checked, there may be no newsletter entry.

That means this:

formData.get("newsletter")

can return:

null

when the checkbox was not selected.

If you want a reliable boolean for application logic, you can read the checkbox itself:

const newsletter = document.querySelector(
  'input[name="newsletter"]'
).checked;

Select and textarea

FormData also works with common form controls.

<select name="country">
  <option value="in">India</option>
  <option value="jp">Japan</option>
</select>

<textarea name="message"></textarea>

Then:

const formData = new FormData(form);

console.log(formData.get("country"));
console.log(formData.get("message"));

A complete API example

HTML:

<form id="contact-form">
  <input name="name" type="text" placeholder="Name">
  <input name="email" type="email" placeholder="Email">
  <textarea name="message" placeholder="Message"></textarea>
  <button type="submit">Send</button>
</form>

JavaScript:

const form = document.getElementById("contact-form");

form.addEventListener("submit", async function (event) {
  event.preventDefault();

  const formData = new FormData(form);

  const data = Object.fromEntries(formData.entries());

  console.log(data);

  const response = await fetch("/api/contact", {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(data)
  });

  if (response.ok) {
    console.log("Message sent.");
  } else {
    console.log("Something went wrong.");
  }
});

This pattern is useful when your backend expects JSON.

When should you use FormData?

Use FormData when:

  • You want to collect many form controls easily.
  • You are submitting a normal HTML form to JavaScript.
  • You need to upload files.
  • Your API accepts multipart/form-data.
  • You want to avoid manually reading every field.

If your API only accepts JSON, convert the collected data into an object and then JSON.

Common mistakes

  • Forgetting name attributes. Form controls without names are not included as named form fields.
  • Thinking FormData is a normal JavaScript object. It is a special browser object with methods such as .get(), .append() and .entries().
  • Trying JSON.stringify(formData) directly. Convert it first when you need JSON.
  • Manually setting Content-Type: multipart/form-data. Let the browser set the boundary when sending FormData.
  • Expecting unchecked checkboxes to appear. An unchecked checkbox may have no entry.
  • Forgetting that values can be strings. Convert numeric strings when your application needs actual numbers.
  • Sending invalid data because “FormData collected it.” Collection and validation are separate jobs. Validate before sending.

Practice

  1. Create a form with name, email, age and city and print all FormData entries.
  2. Use .get() to print only the name and email.
  3. Convert FormData into a plain object using Object.fromEntries().
  4. Convert that object into JSON using JSON.stringify().
  5. Add a checkbox and observe what happens when it is checked and unchecked.
  6. Challenge: Create a profile form with a name, email, skills and profile image, then send it with fetch() as FormData.
  7. Challenge: Create a contact form and convert its FormData to JSON before sending it to a mock API.

Recap

  • FormData collects form controls into a browser-friendly data structure.
  • Use .get() to read one value.
  • Use .entries() to loop through fields.
  • Use .append() to add values and .set() to replace them.
  • Use Object.fromEntries() when you need a plain object.
  • Use JSON.stringify() when an API expects JSON.
  • Send FormData directly when the server accepts multipart/form-data, especially for file uploads.
  • Do not manually set the multipart Content-Type boundary when sending FormData from the browser.