Reading `FormData` in a Server Action

How to read submitted fields from the FormData argument of a Server Action: get, getAll, Object.fromEntries, and the $ACTION_ caveat.

5 min read

Reading FormData in a Server Action means working with the object the browser builds when a form submits. Every form action begins the same way: pull the fields out by name, convert their values, and validate them before writing anything.

The simplest method is get, which returns the first value for a name or null when the field is missing. Convert the result to a string before using it, because get can also return a File for an uploaded input.

typescripttypescript
// app/actions.ts
'use server'
 
export async function updateName(formData: FormData) {
  const name = String(formData.get('name') ?? '')
  const email = String(formData.get('email') ?? '')
  return { name, email }
}

Here get reads the name and email fields. The String conversion with a fallback keeps the result a string even when a field is absent, which makes the values safe to store or return.

get versus getAll

get returns only the first value, which breaks for fields that can hold several values at once. A group of checkboxes or a multi-select both submit more than one value under the same name, and getAll returns all of them as an array.

typescripttypescript
// app/actions.ts
'use server'
 
export async function saveTopics(formData: FormData) {
  const topics = formData.getAll('topics')
  return { topics: topics.map(String) }
}

If the visitor checks three boxes, getAll returns three strings. Using get here would return only the first checked box and silently drop the rest.

The rule is simple. Use get for single-value fields like a text input, and getAll for anything the visitor can repeat, such as checkboxes, multi-selects, or file inputs that allow multiple files. When nothing matches the name, get returns null and getAll returns an empty array.

Building an object from all fields

Object.fromEntries turns any iterable of key-value pairs into a plain object, and FormData is exactly that. It is the quickest way to move every submitted field into one object.

typescripttypescript
// app/actions.ts
'use server'
 
export async function signUp(formData: FormData) {
  const fields = Object.fromEntries(formData)
  const name = String(fields.name ?? '')
  return { name }
}

One caveat: with Server Actions, the object also contains internal keys that start with $ACTION_. Pick the fields you need by name instead of iterating over the whole object, so those internal entries never leak into your data.

The conversion also flattens repeated names. A form that submits topics twice produces a single key, and only the last value survives:

texttext
{"topics":"nextjs","name":"Ada"}

Both checked topics went in, but one came out. Fields that can repeat still need getAll, so treat Object.fromEntries as a shortcut for simple forms rather than a general reader.

Where the form data actually comes from

The browser builds FormData from the form controls, not from your component code. Each control needs a name attribute, because that name is the key you read later in the action. A control without a name is ignored.

That is also why the same action can serve a plain form element and the Form component from next/form without changes, since both submit the same named fields.

With the fields extracted, validation is the next step. See server-side form validation with Zod for schema-based checking, and how to mutate data with a Server Action for the write and refresh that follow.

Rune AI

Rune AI

Key Insights

  • The action receives a FormData object as its argument.
  • get returns the first value or null.
  • getAll returns every value for a repeated field name.
  • Object.fromEntries converts the fields into a plain object.
  • Pick fields by name so $ACTION_ keys never leak into your data.
RunePowered by Rune AI

Frequently Asked Questions

What type is the FormData argument?

It is the standard Web FormData object. The browser builds it from the form's named fields and passes it to the Server Action.

Does formData.get return a string?

Not always. It can return a string, a File, or null. Convert the value with String or check its type before using it.

Why does my object have $ACTION_ keys?

Server Actions add internal metadata keys to the FormData. Read fields by name with get instead of iterating over the whole object.

Conclusion

Reading a Server Action's FormData argument means pulling fields out by name with get or getAll, converting their values, and being careful about the internal $ACTION_ keys when you build an object from the whole form.