Form URL encoding 2026-11-05
Form URL encoding is the
application/x-www-form-urlencoded format for serializing an ordered list of name/value pairs. It is used by URLSearchParams and common form-processing conventions. Repeated names are allowed; the data model need not be a dictionary with one value per name.[ref]URL Standard by WHATWG. §5, format; §6.2, URLSearchParams
For example, the three pairs
Here the space becomes
("q", "a b+c"), ("tag", "x") and ("tag", "y") serialize as q=a+b%2Bc&tag=x&tag=y.Here the space becomes
+, while the literal plus in the value becomes %2B. Parsing the result recovers a b+c and both tag values. Replacing every plus with a space before deciding which encoding convention applies would misread data from other URL contexts.Structural separators must also be distinguished from value data. The encoded pair
q=a%26b has one value, a&b, rather than two pairs. The form parser first recognizes pair boundaries and then decodes their component data. Percent-encoding inside a component is consequently not an instruction to reinterpret the resulting characters as new separators.[ref]URL Standard by WHATWG. §5.1, split, plus replacement and percent-decoding steps
For modern serialization, text is encoded as UTF-8 bytes before the relevant bytes are percent-encoded. The name/value pair
("word", "café") therefore produces word=caf%C3%A9. This connects a text character with its byte representation rather than assigning one arbitrary percent code to the whole character.[ref] Percent-encoding 2026-11-05
Percent-encoding represents a byte using a percent sign followed by two hexadecimal digits. For example, byte value 32 is written
%20. Non-ASCII text is first encoded as bytes: in UTF-8, é becomes the two bytes hexadecimal C3 A9, represented as %C3%A9.[ref]Uniform Resource Identifier (URI): Generic Syntax. Section2.1: percent-encoded octets
A useful example distinguishes data from delimiters. The path in
https://example.org/a/b has two segments; the path in https://example.org/a%2Fb retains the encoded slash within one segment in the parsed URL record. A server may apply additional decoding, but the two spellings must not be assumed interchangeable at every processing stage.Percent-encoding is neither encryption nor a universal instruction to decode repeatedly. The string
%252F decodes once to the text %2F; a second decoding changes it again. Likewise, the plus sign is not universally a space: that convention belongs to form-style query string processing, including URLSearchParams, rather than all URL components.[ref]URL Standard by WHATWG. Section1.3; Section5: form-urlencoded processing
Query string 2026-11-05
A query string is the component following
? and preceding #, or the end, in a URL. It carries data whose interpretation is defined by the resource or application. The generic syntax does not require a dictionary of names and values.[ref]Uniform Resource Identifier (URI): Generic Syntax. Section3.4: query component
For example,
https://example.org/search?q=red&tag=a&tag=b#results has query q=red&tag=a&tag=b. An application using form-style conventions can interpret repeated tag entries as a list. URLSearchParams preserves repeated entries: getAll('tag') returns both a and b. Converting that list directly into a dictionary with one value per name can lose information.Encoding conventions also matter. Under URLSearchParams parsing,
q=a+b gives the value a b, while q=a%2Bb gives a+b. That distinction comes from the specified form parser, rather than a general law that every plus in every URL means a space.[ref]A useful test records both the original query string and the parsing convention. A changed spelling, changed list of values and changed server response are three different observations.
URLSearchParams 2026-11-05
URLSearchParams is an API for representing and manipulating an ordered list of name/value pairs, commonly obtained from a URL's query string. Repeated names are permitted. It uses form URL encoding, rather than imposing its interpretation on every conceivable query syntax.[ref]
URL API in the Node.js documentation. Class URLSearchParams, constructors and iteration
For
new URLSearchParams('tag=a&tag=b&q=a+b'), getAll('tag') returns both a and b, while get('q') returns a b. Calling set('tag','c') replaces the repeated entries with one: toString() then returns tag=c&q=a+b. An associative array holding just one value for each name would discard the original repeated-field information.A literal plus needs a different spelling. Appending the pair
q and a+b to a URL's searchParams produces query ?q=a%2Bb. The plus in the data is represented by percent-encoding, whereas the plus in q=a+b represents a space under this parser. These examples distinguish a character in a value from a character used by the encoding convention.[ref]URL API in the Node.js documentation. URLSearchParams.getAll, set, append and toString
URL serialization 2026-11-05
URL serialization produces the textual spelling of a structured URL record. It is the output side of processing that begins with a URL parser. The WHATWG serializer returns an ASCII string and can optionally omit the fragment identifier.[ref]
A worked example separates the stages. Constructing
new URL('https://EXAMPLE.org:443/a/../b?q=hello%20world~#top') gives href equal to https://example.org/b?q=hello%20world~#top. Lowercasing the host, removing the default port and resolving the parent-directory segment happen during parsing; the serializer exposes the resulting record.Now call
u.searchParams.sort() on that object. Even though there is only one query pair to sort, href becomes https://example.org/b?q=hello+world%7E#top. The decoded query value is unchanged, but URLSearchParams has rewritten its spelling using form URL encoding. Thus changing the query through an API can alter its percent-encoding without changing the value returned by that API.[ref]URL API in the Node.js documentation. url.searchParams: query-update and encoding caveat; URLSearchParams.sort