Skip to content
NewKitApp

Search tools

Jump to any tool by name

June 4, 2026

URL Encoding Explained: Why Spaces Become %20

URL encoding (RFC 3986 percent-encoding) replaces unsafe characters with percent-prefixed byte values so reserved characters like ? and & don't break your URL — and most bugs come from picking the wrong encoder.

URL Encoding Explained: Why Spaces Become %20

If you have ever pasted a URL with a space into a browser and watched it turn into %20, or had a query parameter containing an ampersand silently break your request, you have run into URL encoding. It is the mechanism that lets arbitrary text — spaces, Unicode, ampersands, even other URLs — travel safely inside a URL, and understanding the few rules behind it turns a whole class of confusing bugs into something you can reason about at a glance.

Why URLs need encoding at all

A URL is not just a string — it is a structured identifier with reserved characters that carry syntactic meaning. The ? separates the path from the query string, & separates parameters, = separates a key from its value, # marks the start of a fragment, and / segments the path. If any of those characters appear in your actual data — say, a search query for a band called "rock & roll" — the parser cannot tell whether the & is a parameter separator or part of the value. URL encoding resolves that ambiguity by replacing unsafe characters with a percent sign followed by their byte values.

The encoding is defined by RFC 3986, and the rule is simple: any byte that isn't an unreserved character (letters, digits, and the symbols -, _, ., ~) gets represented as a percent sign plus two hexadecimal digits. A space is byte 0x20, so it becomes %20. An ampersand is 0x26, so it becomes %26. The decoding side reverses this, turning %20 back into a space.

// Encode a value for safe use inside a URL
encodeURIComponent("rock & roll");
// "rock%20%26%20roll"

// Decode it back
decodeURIComponent("rock%20%26%20roll");
// "rock & roll"

Try it: URL Encode / Decode

Percent-encode or decode a URL or query parameter value.

encodeURIComponent vs. encodeURI: pick the right one

This is the single most common source of URL-encoding bugs in JavaScript, because the two functions look interchangeable but do different things. The difference is which characters they consider safe to leave alone.

encodeURI leaves the URL's structural characters intact — things like :, /, ?, &, and =. It is designed for encoding a complete URL that already has structure, where you want to preserve that structure and only escape genuinely unsafe characters. You use it when you have a full URL with some problematic characters mixed in.

encodeURIComponent encodes everything that isn't a letter, digit, or one of -_.~, including all the structural characters. It is designed for encoding a single value that is about to be dropped into a URL — a query parameter, a path segment, a fragment. This is the one you want almost all the time, because most encoding bugs come from not escaping enough, not from escaping too much.

const q = "https://example.com&p=2";

encodeURI(q);
// "https://example.com&p=2"               <- structural chars preserved (unsafe here)
encodeURIComponent(q);
// "https%3A%2F%2Fexample.com%26p%3D2"     <- everything escaped

The practical rule: when in doubt, encode each value individually with encodeURIComponent and assemble the URL yourself, rather than encoding the whole thing at once.

Spaces: %20 vs. plus signs

A recurring point of confusion: spaces sometimes show up as %20 and sometimes as +. Both are valid, but in different contexts. RFC 3986 says a space in a URL is %20. The + convention comes from application/x-www-form-urlencoded, the default encoding for HTML form submissions, where spaces are encoded as + for historical reasons dating back to early web forms.

The practical consequence: in a URL path or a properly constructed query string, expect %20. In data coming out of an HTML form POST body, expect +. Most modern frameworks handle both on decode, but if you are hand-rolling a parser, you need to handle both — and if you are generating URLs, prefer %20 for anything outside form bodies, since that is the universally correct choice per the spec.

Try it: QR Code Generator

Turn any text or URL into a downloadable QR code — customizable colors and error correction.

Unicode and multi-byte sequences

Non-ASCII characters — accented letters, emoji, CJK text — get percent-encoded byte by byte using their UTF-8 representation, which means a single character can expand to several percent-escape sequences. The emoji in a string like "café 🚀" becomes a stretch of encoded bytes, which is why URLs containing emoji or other non-ASCII text look dramatically longer after encoding. This is correct and expected; the bytes are encoded faithfully and decode back to the exact original text.

One thing to be careful of: encoding is not idempotent in the naive sense. Encoding an already-encoded string a second time percent-encodes the percent signs themselves — %20 becomes %2520 (because % is byte 0x25), which will then decode back to %20 rather than to a space. Always encode raw values once, at the point where they enter the URL, and never re-encode a full URL that may already contain escapes.

When to reach for a tool

For one-off values, encodeURIComponent in the browser console works fine. For decoding a long URL someone pasted into a bug report, eyeballing a string of percent-escapes is error-prone — paste it into the URL Encode/Decode tool instead, which encodes and decodes both ways, handles the +-versus-%20 distinction, and runs entirely in your browser so request URLs with sensitive parameters never leave your machine. If you are generating a QR code from the resulting URL, the QR Generator expects a properly encoded URL as input — encoding first avoids the QR scanner misinterpreting an ambiguous character.