URL encoding vs form encoding

Published: 2026-05-27

How percent-encoding works in URLs, when encodeURI differs from encodeURIComponent, and why application/x-www-form-urlencoded treats spaces as plus signs.

URL encoding (more precisely percent-encoding) turns bytes that are not allowed in a URL part into %HH sequences so links stay valid. Form encoding (application/x-www-form-urlencoded) reuses that idea for HTML forms and many HTTP APIs, but with extra conventions—most famously spaces as + instead of %20. Mixing the two rules is a common source of “it works in Postman but breaks in the browser” bugs.

Percent-encoding in one minute

Only a subset of ASCII characters can appear literally in every URL context. Everything else is encoded as % + two hexadecimal digits for the byte value (UTF-8 bytes for non-ASCII text).

Examples:

Character Encoded (UTF-8)
space %20
& %26
= %3D
é (U+00E9) %C3%A9

Decoding is the inverse: scan for %, read two hex digits, emit the byte, then interpret the byte sequence as UTF-8 (or the charset the application expects).

Reserved characters (:, /, ?, #, [, ], @, !, $, &, ', (, ), *, +, ,, ;, =) mean different things depending on where in the URL the value sits—path, query, or fragment—so encoders must know which part you are filling in.

Where encoding applies in a URL

A typical HTTPS URL has distinct zones:

https://user:[email protected]:8080/path/to/page?name=hello%20world&tag=a%2Bb#section-2
|-------|  |-------------------|  |----------| |------------------------| |---------|
 origin          authority           pathname            search (query)      hash

Practical rule of thumb:

  • Encode individual values (query parameter values, path segments, fragment identifiers) before you assemble them into the full string.
  • Do not percent-encode an entire URL after it is already valid—structural characters like :// and ? must stay unescaped or the link breaks.

encodeURI vs encodeURIComponent (JavaScript)

Browsers expose two related helpers (other languages have equivalents):

API Typical use Keeps unescaped (examples)
encodeURI A mostly complete URL string :, /, ?, # (structure)
encodeURIComponent A single component: query value, path segment, fragment Almost nothing except A–Z a–z 0–9 - _ . ! ~ * ' ( )

Examples with the string hello world/a?b:

  • encodeURIComponent('hello world/a?b')hello%20world%2Fa%3Fb (slashes and ? are escaped—correct for one value).
  • encodeURI('https://ex.com/a b')https://ex.com/a%20b (scheme and slashes stay readable).

Use encodeURIComponent (or your language’s “component” encoder) when building ?key=value pairs. Use encodeURI only when you need to escape a longer URL-like string but still preserve delimiters.

Form encoding (application/x-www-form-urlencoded)

HTML forms and many REST clients submit bodies (or sometimes queries) as key=value&key2=value2:

  • Keys and values are encoded like URI components (reserved characters become %HH).
  • Spaces are often written as + instead of %20. Both decode to space in this encoding—+ is not a literal plus sign unless it is percent-encoded as %2B.
  • The Content-Type header is application/x-www-form-urlencoded (often with charset=UTF-8).

The same “plus means space” rule appears in query strings on GET forms, which is why ?q=hello+world is common even though %20 is also valid.

When decoding, you usually:

  1. Split on & into pairs, then on the first = into key and value.
  2. Replace + with space if you are in form/query mode.
  3. Run percent-decoding on each key and value.

When encoding, pick one space style and stay consistent: APIs differ; some expect %20, some accept +.

Side-by-side: URL component vs form style

Topic URI component encoding Form / query (x-www-form-urlencoded)
Space in a value %20 (typical) + or %20 (both decode to space)
Literal + in a value %2B Must be %2B or it becomes space on decode
&, = in a value Must be %26, %3D Same—otherwise you break pair splitting
Non-ASCII UTF-8 bytes as %HH Same
Where it shows up Path segments, fragments, any isolated value HTML POST bodies, many OAuth/token endpoints, search ?q=

Neither encoding encrypts or signs data. Anyone can decode percent sequences; never put secrets in URLs assuming encoding hides them.

Common pitfalls

  • Double encoding: Running encodeURIComponent on text that already contains %20 turns % into %25, producing %2520. Decode once, encode once at the boundary.
  • Encoding the whole URL: Turning https:// into https%3A%2F%2F breaks navigation. Encode parts, then concatenate.
  • Decoding too early: Middleware that decodes query values before your app runs can change + and % semantics. Log the raw string when debugging.
  • Plus vs space: A password or base64 token that includes + must be sent as %2B in form contexts, or it may arrive as spaces.
  • Assuming decodeURI fixes form data: Use component decoding (decodeURIComponent) per value, and apply + → space only when the source is form-encoded.
  • Path vs query: A slash inside a single path segment must be %2F; a slash between segments is a delimiter and stays /.

JSON and APIs (brief)

JSON request bodies (application/json) do not use form encoding—strings are quoted in JSON, and HTTP libraries handle the body as UTF-8 text. You still URL-encode values when those same fields appear in query strings or path parameters on the same API. Mixed styles on one service are common (JSON body + form-encoded token endpoint).

Try it locally in your browser

Use the URL Encoder, Decoder & URL Parser to percent-encode or decode text with URIComponent vs URI rules, toggle treat + as space when decoding form-style values, and break a full URL into protocol, host, path, query, and hash—all without uploading your strings.

If you are escaping text for HTML—not for URLs—see the HTML Entity Escape & Unescape tool; entity encoding solves a different problem (markup safety, not URL structure).

Related reading

All learn articles