Skip to content
URL Encode / Decode
Percent-encode query values, Unicode, and emoji. Component or full.
Blog

URL Encoding: Query Values, Whole URLs, and +

Use component for one value, full for an already-structured URL. Reproduce why + becomes a space in query parsing and how to preserve a literal plus.

Compare an example →
Three key takeaways

Corrected Sep 28: the earlier “+ is literal in a plain URL” line was wrong for URL query parsers.

  1. ①
    One value: component a=1&b=2 becomes a%3D1%26b%3D2. URLSearchParams.set can add the raw value without hand-building the query.
  2. ②
    A query + is ambiguous URLSearchParams("q=a+b").get("q") returns "a b". Encode a literal plus as %2B.
  3. ③
    Local input ≠ shared URL The converter processes pasted text locally; visiting or sharing a URL containing it can expose the query in requests and records.
A paper note titled 'Component or full' on a desk, illustrating the URL encoding scope decision.

A value containing & can split a search URL into two parameters. A value containing + can come back with a space instead. These are separate problems: what scope you encode and how a query is parsed. Here are reproducible examples using the site tool and the browser URL API.

Component or full: decide the scope first

JavaScript gives you two URL-encoding functions. The difference is whether they touch reserved characters.

encodeURIComponent (component mode) percent-encodes the reserved characters too, things like / ? # & =. Reach for it when you are handling one value or one path segment. encodeURI (full mode) leaves those delimiters intact, so it is for not-yet-percent-encoded URL text whose structure is already set. The MDN reference splits them the same way by purpose. Mixing the two up can change the boundaries of a query value.

A value with reserved characters needs component

Here is a reproducible failure: a & or = living inside a parameter value.

Say the value is a=1&b=2. Run it through the PiPi Worlds URL encoder in component mode and you get a%3D1%26b%3D2. The = and & become %3D and %26, so the whole thing rides along as a single value. Encode it with full mode instead and it stays a=1&b=2. Drop that into ?x=a=1&b=2 and the server reads &b=2 as a separate parameter, and your data is mangled. For values, component is the answer.

Full mode is for URL text before percent-encoding

The opposite case is URL text with its delimiters already in place but with spaces or Unicode not yet percent-encoded.

Take https://pipi-worlds.com/a b?q=café. In full mode it becomes https://pipi-worlds.com/a%20b?q=caf%C3%A9. The ://, /, ?, and = stay put, while the space and accented letter become percent sequences. Component mode would also escape the scheme delimiters. Do not re-encode a URL already containing %20 or %2B: encodeURI changes %20 to %2520, altering the value. Build new query values with URL.searchParams.set instead.

When a ’+’ quietly becomes a space

Decoding has its own trap, and it is the + sign. The same a+b decodes two different ways depending on where it came from.

A + is not determined by whether the text “looks like a URL.” A URL query parsed through URLSearchParams uses form-urlencoded rules, so a raw + becomes a space. This applies to query APIs, not only HTML form submissions.

decodeURIComponent("a+b")                 // "a+b"
new URLSearchParams("q=a+b").get("q")   // "a b"
new URLSearchParams("q=a%2Bb").get("q") // "a+b"
const url = new URL("https://example.com/search");
url.searchParams.set("q", "A+B & C");
url.searchParams.get("q")                // "A+B & C"
// Serialized q: literal + is %2B, space is +, & is %26

If you hand-build q=A+B but need a literal plus, write %2B instead. Better, pass the unencoded value to URL.searchParams.set and let it serialize the query. In this site’s decoder, “Treat + as space” works only in Component mode for one copied form/query value. Full URL mode preserves + everywhere to avoid changing paths; use URLSearchParams or copy just the query value into Component mode to interpret it.

Why is %2F kept?

An unchanged result is not always an error. In the English converter, select Decode, choose Full URL, and enter this harmless text—not a URL to visit:

%2F%3F%23%26

The output stays %2F%3F%23%26. Keep Decode selected and change Scope to Component (value): the output becomes /?#&. You changed the interpretation, not the input. The tool’s output count changes from 12 to 4 UTF-16 code units; it is not a count of requests or UTF-8 bytes.

Full URL uses decodeURI, which preserves escapes for reserved URL syntax. Component uses decodeURIComponent, which decodes those escapes too. Use the latter on the one value you intend to read—not blindly on a complete address whose boundaries must stay intact.

Compare three cases before deciding to decode again:

  • %2F: Full URL keeps %2F; Component returns /. This is the scope distinction above.
  • %252F: either scope returns %2F after one pass. A second Component pass would turn it into /, changing a literal percent sequence into a slash. Stop unless you know another encoding layer was intended.
  • %2: either scope reports an error. This is a truncated escape, not a reserved character waiting for a different scope.

Neither switching scope nor repeating Decode establishes that an address is trustworthy. Keep these examples in the converter; do not navigate to a decoded address merely to see whether it works.

The PiPi Worlds URL encoder is a manual converter for comparing component/full scope and plus handling. Full-URL encodeURI leaves delimiters such as &, # and ? intact; it does not safely assemble new query values. For a new link, use URL and searchParams.set as above. Conversion input stays in your browser, but a separate page analytics beacon may run; visiting a URL containing your value can put that address in requests and records. Truncated % sequences produce an error.

Frequently asked questions

What is the difference between encodeURIComponent and encodeURI?
encodeURIComponent escapes reserved characters such as `/ ? # & =`, so use it for a single query value or path segment. encodeURI preserves delimiters in URL text that has not yet been percent-encoded. Do not run it again on a URL already containing escapes such as `%20`.
Which one should I use for a query parameter value?
Use encodeURIComponent. If the value contains `&` or `=`, encodeURI leaves them as is and your parameter boundaries break. For example, the value `a=1&b=2` becomes `a%3D1%26b%3D2` with encodeURIComponent, so it travels safely as one value.
Why did a '+' turn into a space when I decoded?
Query strings parsed by URLSearchParams use form-urlencoded rules: q=a+b yields a b, while q=a%2Bb yields a+b. By contrast, decodeURIComponent("a+b") leaves the plus alone. Turn on this tool’s “Treat + as space” only when manually decoding a form/query component.
What happens to non-ASCII characters like emoji in a URL?
They encode to UTF-8 percent sequences. The string 'café' becomes `caf%C3%A9`, and decoding restores it exactly. Broken sequences, such as a truncated `%`, are reported as an error instead of returning garbage.
Is the value I paste sent to a server?
The converter does not send pasted input to a conversion endpoint. Cloudflare Web Analytics may process page-view/performance data separately. If you put a value into a URL and visit or share it, the query can appear in requests, logs and browser history. Do not use URL encoding to conceal secrets.

Sources

Review record: Codex AI technical source-and-code review against the WHATWG URL Standard, MDN and this site’s converter; not an independent browser-compatibility certification.

Scope of this review — October 15: FAQ text restoration and source-format verification only. The earlier technical/source checks retain their September 28 and October 14 dates. Not a new factual review of the article, a converter change or a full accessibility audit.

Recorded checks and limits

The September 28 review covered encoding and plus-sign behavior. On October 14, reopened MDN decodeURI and decodeURIComponent, entered %2F%3F%23%26 in the live English tool and observed 12 unchanged code units in Full URL versus /?#& (4) in Component. Added regression checks for reserved escapes, one-layer decoding and malformed input. The earlier source access dates remain their original dates. No example URL was visited or sent to a server; this is not a full browser/security audit. October 15 rendering-only repair: restored the complete original first FAQ answer by protecting its literal # from YAML comments. The article body, examples and source access dates are unchanged; no fresh source-fact or browser-compatibility review is claimed.

What this guide adds — Reproduces plus-sign behavior and an unchanged-looking Full URL decode result with exact inputs and outputs. Separates preserved reserved escapes from malformed input and double encoding, shows how to add a raw query value, and states the limits of local processing.

This records the stated checks; it is not an independent guarantee of accuracy.

Back to the tool →