Skip to content

URL Encoder & Decoder

Encode or decode a URL and see both encodeURIComponent and encodeURI results at once, so you can tell which one you actually need. There is also an SVG mode for CSS, and it runs entirely in your browser with no upload.

Use for a single query value or path segment.

Use for a whole URL that is already assembled.

Runs in your browser. Nothing uploaded.

How to use it

  1. Pick a mode. Encode shows both encoding functions side by side. Decode turns percent-encoded text back. SVG for CSS produces a ready-to-paste declaration.
  2. Paste your value. Results update as you type.
  3. Read both encode results. The left is encodeURIComponent, the right is encodeURI. Which one you want depends on whether you’re encoding a piece of a URL or a whole one.
  4. Watch for the warning. If your input already looks encoded, a notice appears — encoding it again is the cause of most %2520 bugs.

What a URL encoder actually does

A URL has structure. The ? starts the query, & separates parameters, = splits a name from its value, # begins the fragment, and / divides path segments. Those characters carry meaning.

So what happens when your data contains one? If a search term is fish & chips and you drop it straight into a query string, the & gets read as a parameter separator and your value is silently cut in half.

Percent-encoding solves this. Each problematic character is replaced by % followed by its byte value in hex. A space becomes %20, an ampersand becomes %26, a question mark becomes %3F. The receiving end decodes them back, and the structure is never confused with the content.

Non-ASCII characters work the same way, one %XX per UTF-8 byte. é is two bytes, so it becomes %C3%A9. An emoji is four bytes and produces four escapes.

encodeURI vs encodeURIComponent

This is the question the tool exists to answer, and getting it wrong causes bugs that only appear with certain input.

encodeURIComponent escapes almost everything. It leaves alone only the unreserved characters — letters, digits, and - . _ ~. Everything else, including / ? # & = :, gets escaped. Use it for a single piece of a URL: one query value, one path segment.

encodeURI preserves URL structure. It leaves the reserved characters intact so a complete URL stays functional. Use it when you already have a whole URL assembled and just need to make it valid — typically when it contains spaces or non-ASCII characters.

Input encodeURIComponent encodeURI
a b a%20b a%20b
a&b a%26b a&b
a/b a%2Fb a/b
https://x.com/?q=1 https%3A%2F%2Fx.com%2F%3Fq%3D1 https://x.com/?q=1

Look at row two. If you use encodeURI on a query value containing an ampersand, that ampersand stays live and splits your query into two parameters. The bug only shows up when a user types an ampersand, which is why it survives testing and breaks in production.

The rule: building a URL from parts, encode each part with encodeURIComponent. Reach for encodeURI only when handed a finished URL.

Which characters need encoding

Class Characters Encoded by
Unreserved A–Z a–z 0–9 - . _ ~ Neither. Safe everywhere.
Reserved (structural) : / ? # [ ] @ ! $ & ' ( ) * + , ; = encodeURIComponent only
Space   Both, to %20
Non-ASCII é 日 🌍 Both, as UTF-8 bytes
Percent itself % Both, to %25

One wrinkle: JavaScript’s encodeURIComponent leaves ! ' ( ) * unescaped even though RFC 3986 lists them as reserved. Some servers care. This tool escapes them anyway, which is safe in every context we’re aware of.

Encoding SVG for CSS

Putting an SVG directly in a stylesheet avoids an HTTP request for small icons. The naive approach is to Base64 it, but that adds a third to the size and makes it unreadable. Percent-encoding the SVG as-is is smaller and stays editable.

Only a few characters actually break inside a CSS url():

  • < and > — must be escaped
  • # — critical, because it starts a fragment and truncates everything after it. An SVG with fill="#ff0000" silently disappears without this.
  • % — must become %25 first, or existing escapes get mangled
  • { and } — escaped to avoid confusing the CSS parser
  • Double quotes — converted to single quotes so the whole payload can sit inside url("…")

SVG mode handles all of that and hands you the complete declaration. The result is typically 30–40% smaller than the Base64 equivalent and you can still read the markup.

Worked examples

A search query. The term fish & chips becomes fish%20%26%20chips. Dropped into ?q=, it arrives intact. Encoded with encodeURI instead you’d get fish%20&%20chips, and the server would see a parameter q of fish plus a second empty parameter called chips.

A URL inside a URL. Redirect parameters are the classic case: ?return=https%3A%2F%2Fexample.com%2Fpage%3Fid%3D1. The inner URL must be fully component-encoded or its own ? and & will be read as belonging to the outer one. This is a frequent source of broken OAuth flows.

A path segment with a slash. A filename like reports/2026.pdf used as a single path segment must become reports%2F2026.pdf. Left alone it reads as two segments and produces a 404 that looks inexplicable.

Breaking a query string apart

Paste a full URL and a table appears underneath listing every query parameter with its value decoded. It’s the fastest way to read a URL that’s been through an analytics tool and come out 400 characters long.

Take this:

https://example.com/search?q=hello%20world&tags=a%2Cb&utm_source=news&ref=
Name Value, decoded
q hello world
tags a,b
utm_source news
ref (empty)

Three things the table tells you that reading the raw string doesn’t.

An empty value is not a missing parameter. ref= is present with an empty value; ref on its own has no value at all. Some backends treat those identically and some don’t, and the difference is invisible until something breaks.

Double encoding is flagged. If a value still contains a percent escape after being decoded once, it was encoded twice, and the table marks it. That’s the commonest cause of a link that works in testing and fails in production.

A malformed escape doesn’t take the page down. A truncated sequence like %E0%A4%A is shown as-is rather than throwing, which is what the browser’s own URL parser does. That matters here because a broken URL is exactly what you’d be pasting in to investigate.

The breakdown works on relative URLs and on URLs with no scheme, for the same reason.

Double encoding, and how to spot it

Encode a b once and you get a%20b. Encode that again and the % itself is escaped, giving a%2520b. Decode once and you get a%20b back — text, not a space. Decode twice for the original.

%25 in a URL is the fingerprint. It almost always means something encoded a value that was already encoded. Usual culprits: application code encoding a parameter that the framework then encodes again, a redirect that re-encodes its target, or a value pasted from a browser address bar — where it was already encoded — into code that encodes it once more.

This tool warns you when the input already contains percent escapes, before you make it worse.

Plus signs and spaces

You’ll see spaces as both %20 and +. Both are correct, in different places.

+ comes from application/x-www-form-urlencoded, the format HTML forms use, where it means a space. That convention applies to query strings and form bodies. In a path segment, + is a literal plus and nothing more.

So /search?q=a+b is a search for “a b”, while /files/a+b.txt is a file with a plus in its name. Decoders have to be told which convention applies, which is what the “treat + as space” option does here. Getting this wrong mostly bites people handling form data or parsing analytics URLs.

Common mistakes

Encoding the whole URL when you meant one parameter. The most common error, and it only breaks when a value contains a reserved character.

Encoding twice. Covered above. Check for %25.

Assuming + always means space. It doesn’t, outside query strings and form bodies.

Forgetting the # in an SVG. The image vanishes with no error, because everything after the hash is treated as a fragment identifier.

Encoding unreserved characters. Harmless but noisy — some encoders escape ~ or . unnecessarily, producing longer URLs that some caches treat as different from the unencoded form.

Encoding that happens without you asking

A lot of confusion here comes from encoding happening at layers you didn’t write, so the value you handed over isn’t the value that arrives.

The browser address bar. Type a URL with a space and the browser encodes it before sending. Copy a URL out of the address bar and you generally get the encoded form, already containing %20. Paste that into code that encodes again and you have created double encoding without touching anything.

The URL and URLSearchParams APIs. URLSearchParams encodes values automatically when you call set or append, and it uses form encoding — so a space becomes +, not %20. Encoding a value yourself and then passing it to URLSearchParams double-encodes it. Pick one layer and let it do the work.

HTML form submission. A GET form encodes its fields as application/x-www-form-urlencoded without being asked. That’s where the +-for-space convention originates.

Server-side frameworks. Most decode query parameters before your handler sees them. If you decode again, a value that legitimately contains %20 as text turns into a space. This is the mirror image of double encoding and it’s harder to spot, because it only breaks for users whose data happens to contain a percent sign.

Redirects and proxies. Some re-encode the Location header. If a redirect chain mangles a parameter, this is usually why.

The practical rule: decide which layer owns encoding and make every other layer leave it alone. Most double-encoding bugs are two layers both being helpful.

Query, path and fragment behave differently

The same character can be fine in one part of a URL and a problem in another.

In the path, / is a separator and must be encoded inside a segment. + is a literal plus. Spaces must be %20, never +.

In the query, / is usually safe unencoded, & and = are separators and must be encoded inside values, and + means a space by convention.

In the fragment — everything after # — the rules are loosest, and crucially the fragment is never sent to the server at all. It exists only in the browser. That surprises people debugging why a value isn’t arriving.

The character that behaves the same everywhere is %: always encode it as %25, in every position, or you’ve started an escape sequence you didn’t intend.

Encoding in other languages

Language Component encoding Note
JavaScript encodeURIComponent(v) Leaves ! ' ( ) * alone
Python urllib.parse.quote(v, safe='') quote_plus for form values
Java URLEncoder.encode(v, UTF_8) Form encoding — space becomes +
PHP rawurlencode($v) urlencode gives + for space
C# Uri.EscapeDataString(v) EscapeUriString is deprecated
Go url.QueryEscape(v) PathEscape for path segments

The trap in that table is the + column. Java’s URLEncoder and PHP’s urlencode both produce form encoding, so a space becomes + rather than %20. That’s correct for a query string and wrong for a path segment. Java developers hit this regularly when building REST paths — use UriComponentsBuilder or replace + with %20 afterwards.

Python’s quote defaults to safe='/', meaning it will not encode slashes unless you tell it to. For a single path segment containing a slash, pass safe='' explicitly or the value silently splits into two segments.

Related tools

Percent-encoding and Base64 solve different problems and are regularly mixed up — the Base64 encoder is for binary data, this tool is for URL syntax. JWTs use Base64url, a URL-safe variant, which the JWT decoder handles. If a value is arriving mangled and you need to confirm it survived transit unchanged, the hash generator will tell you.

Frequently asked questions

What is URL encoding?

URL encoding, or percent-encoding, replaces characters that have a special meaning in a URL with a percent sign and their hex byte value. A space becomes %20, an ampersand becomes %26. It exists so that data can be carried inside a URL without being mistaken for URL structure.

What is the difference between encodeURI and encodeURIComponent?

encodeURIComponent escapes everything that is not an unreserved character, including : / ? # & = so it is correct for a single query value or path segment. encodeURI leaves those structural characters alone, so it is correct for encoding a whole URL that is already assembled. Using encodeURI on a query value is the most common mistake, because an ampersand inside the value stays live and splits the query.

How do I encode an SVG for CSS?

Switch to SVG mode and paste the markup. Only the characters that actually break CSS are escaped — angle brackets, the hash, curly braces — and double quotes become single quotes so the whole thing can sit inside url("..."). Full encodeURIComponent also works but roughly doubles the payload for no benefit.

Why do I see %2520 in my URL?

That is double encoding. A space became %20, then the %20 was encoded again, turning the percent sign into %25. It usually means a value was encoded once by your code and again by a framework or a redirect. This tool warns you when the input already looks encoded.

Is + the same as %20?

Only inside a query string. The application/x-www-form-urlencoded format used by HTML forms encodes a space as +, so both appear in the wild. In a path segment, + is a literal plus sign and means nothing special. Use the "treat + as space" option when decoding form data.

How do I URL encode in JavaScript, Python or Java?

JavaScript has encodeURIComponent and encodeURI built in. Python uses urllib.parse.quote for path segments and quote_plus for form values. Java uses URLEncoder.encode(value, StandardCharsets.UTF_8), which produces form encoding, so a space becomes + rather than %20.

Last updated: August 9, 2026