A plus sign does not always mean a space

Moyoutil’s URL tool converts URI components. Decoding uses decodeURIComponent, which leaves + unchanged. URLSearchParams instead parses queries using application/x-www-form-urlencoded rules: it replaces + in the original string with a space before percent-decoding. That order lets a plus sign encoded as %2B remain a plus sign.

WHATWG URL: Form-style parsing

ECMAScript: decodeURIComponent

Actual results for the same input in both paths

We ran the project’s urlComponent function and JavaScript URLSearchParams on October 5, 2026. Quotes in the table are JSON notation to make spaces visible; they are not part of the returned value. For query parsing, we prefixed each input with q=.

Component decoding versus query value parsing
InputMoyoutil decodingURLSearchParams
C++"C++""C "
C%2B%2B"C++""C++"
a+b"a+b""a b"
a%20b"a b""a b"
Two decoding paths for C++ and C%2B%2B. Parsing q=C++ as a query produces two spaces after C.
An original diagram of reproduced code outputs. 0x20 is the character code for a space; 0x2B is the code for a plus sign. This is not a screenshot.

Build a query from the original value to preserve the search term

This example creates strings without making any server requests. Passing the original value C++ guide to URLSearchParams serializes plus signs as %2B and the space as +. Encoding the individual value with encodeURIComponent uses %20 for that space. Both results return the original value when parsed as a query in this example.

const original = "C++ guide";
const query = new URLSearchParams({ q: original }).toString();
// q=C%2B%2B+guide
const component = encodeURIComponent(original);
// C%2B%2B%20guide
new URLSearchParams(query).get("q");
// C++ guide

WHATWG URL: URLSearchParams serialization

Moyoutil’s URL tool currently has no fields for assembling query names and values, and no form-style decoding mode. To inspect one value, encode C++ guide and then decode the result to check the original text. Do not put a whole URL into the value conversion field. For a real API, check the encoding rules that API requires.

Already encoded values cause the percent signs to be encoded again

Pass unencoded original values to the object form of URLSearchParams. If you pass a value that encodeURIComponent has already encoded, % becomes %25. Parsing the query below once returns C%2B%2B, not C++. Check the roles of the sending and receiving stages before trying repeated decoding.

const encoded = encodeURIComponent("C++");
// C%2B%2B
const query = new URLSearchParams({ q: encoded }).toString();
// q=C%252B%252B
new URLSearchParams(query).get("q");
// C%2B%2B

How to inspect a link with unexpected results

  1. Keep the original search term alongside the transmitted query string. Distinguish C++ from C%2B%2B.
  2. Check whether the receiving code uses decodeURIComponent or a form-style query parser. Moyoutil’s decoding result alone cannot establish what a server will return.
  3. Rebuild the query from original values and compare the parsed result. Distinguish this example’s rules from those of the real API.

Moyoutil rejects incomplete percent escapes such as % and %2. It also rejects %FF because it is not valid UTF-8 text. This does not mean other parsers handle errors the same way, and it does not automatically recover the original text.

Frequently Asked Questions

Should I use %20 or +?

When Moyoutil encodes an individual value, a space becomes %20. URLSearchParams serialization uses +. Check the receiver’s rules and verify that a round trip returns the original value.

Can I replace every original plus sign with a space?

No. That changes the meaning of values such as C++. Apply form parsing rules only to strings received in that format; do not arbitrarily change the unencoded original text.