Submission formats
URL-encoded form data
Understand the default application/x-www-form-urlencoded body and how names, values, spaces, and repeated keys are encoded.
When a POST form has no enctype, the browser uses application/x-www-form-urlencoded. That long name describes something simple: the body looks like the query string you already know from GET requests.
Take this form:
<form action="/profile" method="post">
<input name="displayName" value="Ada Lovelace">
<input name="topic" value="HTML & CSS">
<button type="submit">Save</button>
</form>
Submit it and the request body is one line:
displayName=Ada+Lovelace&topic=HTML+%26+CSS
Each pair is name=value. Pairs are joined with &. The space in “Ada Lovelace” became +. The & inside “HTML & CSS” became %26, because a raw & would look like the start of a new pair. That’s the whole point of the encoding: special characters get escaped so the structure survives.
The request also carries a header that tells the server how to read the body:
Content-Type: application/x-www-form-urlencoded
The server’s form parser sees that header, splits on & and =, and decodes each piece. You get back Ada Lovelace and HTML & CSS as plain strings.
Non-ASCII characters
Type Zoë and the body contains Zo%C3%AB. The browser encodes the UTF-8 bytes of the character, one %XX per byte. The parser reverses it. You never need to handle this yourself, but it’s good to recognize it when you read a raw request.
Repeated names
The same name can appear more than once. Two checked checkboxes named topic produce:
topic=html&topic=css
This is valid. The problem is on the parsing side. A parser that turns the body into a plain object keeps only one value per key, so css silently wins and html disappears. When your form allows repetition, read the values with an API that returns all of them. In Node, new URLSearchParams(body).getAll('topic') returns ['html', 'css'].
What this format can’t do
It carries text only. A file input contributes just the filename, not the bytes. Forms with uploads need multipart/form-data, which we cover in the next lesson.
Encoding is not validation
Be careful here. Decoding a value only gives you back the string the visitor typed. It’s still untrusted input. Validate it before storing it, and escape it for the context where you later display it. The encoding protected the request structure. It did nothing for your database or your HTML.
Try this: submit a value containing a space, an &, a + and a character like è. Open the Network panel, look at the raw payload, then compare it with what your server logs after decoding.
Lesson completed