URL Encoder Decoder: A Complete Developer's Guide

📅 April 12, 2026 ⏱️ 10 min read 📝 Developer Tools

Every time you submit a form, click a link with query parameters, or make an API call, URL encoding is working behind the scenes. It's one of the most fundamental mechanisms in web development—yet it's also one of the most misunderstood. Double-encoding bugs, incorrect character handling, and confusion between encoding functions cause countless hours of debugging.

This guide covers URL encoding from first principles to advanced edge cases. Whether you're a beginner building your first API or a senior developer debugging encoding issues in a production system, you'll find practical answers here.

Need to quickly encode or decode a URL? Try our client-side tool.

Try Risetop URL Encoder/Decoder →

What Is URL Encoding?

URL encoding (also called percent-encoding) is a mechanism for encoding arbitrary data in a URI using only the limited US-ASCII character set that is legal in URIs. Defined in RFC 3986, it replaces unsafe characters with a percent sign (%) followed by two hexadecimal digits representing the character's byte value.

For example:

Original:  hello world & foo=bar
Encoded:   hello%20world%20%26%20foo%3Dbar

Why URLs Need Encoding

URLs were designed in the early 1990s for a simple internet. They can only contain a subset of ASCII characters. But modern web applications need to pass all kinds of data in URLs—Chinese characters, emoji, spaces, ampersands, and more. URL encoding bridges this gap by converting any byte sequence into URL-safe ASCII.

There are two categories of characters in a URL:

The RFC 3986 Character Map

Understanding which characters get encoded and how is crucial. Here's the complete reference:

CharacterEncodedCategory
Space%20Must encode
!%21Sub-delim (reserved)
#%23Fragment delimiter
$%24Sub-delim
&%26Query separator
'%27Sub-delim
(%28Sub-delim
)%29Sub-delim
+%2BSub-delim (note: + means space in query strings)
,%2CSub-delim
/%2FPath separator
:%3AScheme/authority separator
;%3BSub-delim
=%3DQuery key-value separator
?%3FQuery start delimiter
@%40Authority delimiter
[%5BIPv6 literal delimiter
]%5DIPv6 literal delimiter

URL Structure and Encoding Context

The key insight that many developers miss is that encoding depends on which part of the URL you're in. A character that's safe in one component may be dangerous in another.

https://example.com/path?query=value#fragment
        \___/   \________/ \_________/ \______/
         scheme    host       query    fragment
                  \__________/
                    authority

JavaScript Encoding Functions

JavaScript provides three built-in encoding functions, and choosing the wrong one is a common source of bugs:

encodeURIComponent()

Encodes all characters except: A-Z a-z 0-9 - _ . ! ~ * ' ( )

encodeURIComponent("hello world&foo=bar")
// "hello%20world%26foo%3Dbar"
encodeURIComponent("search?q=javascript tutorial")
// "search%3Fq%3Djavascript%20tutorial"

Use for: Query parameter values, individual path segments, form data.

encodeURI()

Encodes all characters except: A-Z a-z 0-9 ; / ? : @ & = + $ , # - _ . ! ~ * ' ( )

encodeURI("https://example.com/path with spaces")
// "https://example.com/path%20with%20spaces"
encodeURI("https://example.com/search?q=hello world")
// "https://example.com/search?q=hello%20world"

Use for: Full URLs where you want to preserve the structure (scheme, host, delimiters).

The Critical Difference

const url = "https://example.com/api?key=hello world";

encodeURI(url);
// "https://example.com/api?key=hello%20world" ✅ Preserves ? and =

encodeURIComponent(url);
// "https%3A%2F%2Fexample.com%2Fapi%3Fkey%3Dhello%20world" ❌ Breaks the URL

The rule is simple: encodeURI for full URLs, encodeURIComponent for values that go inside URLs.

Common Pitfalls and Bugs

Double Encoding

The most frequent encoding bug. When data gets encoded twice:

// First encoding: space → %20
encodeURIComponent("hello world") → "hello%20world"

// Second encoding: % → %25, so %20 → %2520
encodeURIComponent("hello%20world") → "hello%2520world"

This results in the user seeing literal %20 instead of a space. Always check whether your input is already encoded before encoding again.

The + vs %20 Confusion

The application/x-www-form-urlencoded format (used by HTML forms) encodes spaces as +. The URI standard uses %20. This mismatch causes subtle bugs:

// Server receives: search?q=hello+world
// Is the user searching for "hello world" or "hello+world"?
// In application/x-www-form-urlencoded: it's "hello world"
// In a raw URL: it depends on the server implementation

Most modern frameworks handle both, but don't rely on it. Be explicit in your encoding and decoding.

Encoding Unicode Characters

JavaScript's encoding functions use UTF-8 encoding for non-ASCII characters:

encodeURIComponent("你好")
// "%E4%BD%A0%E5%A5%BD"
// 你 → U+4F60 → UTF-8: E4 BD A0
// 好 → U+597D → UTF-8: E5 A5 BD

Each Unicode character is encoded as its UTF-8 byte sequence, then each byte is percent-encoded. This is why a single Chinese character becomes 9 characters in a URL.

Server-Side Encoding

Python

from urllib.parse import quote, quote_plus, unquote

quote("hello world&foo=bar")
# 'hello%20world%26foo%3Dbar'

quote_plus("hello world&foo=bar")
# 'hello+world%26foo%3Dbar'  # Spaces become +

unquote("hello%20world")
# 'hello world'

Note the difference: quote() uses %20 for spaces (URI standard), while quote_plus() uses + (form encoding).

Node.js

encodeURIComponent("hello world")  // Same as browser
// "hello%20world"

// Node.js also provides:
const querystring = require('querystring');
querystring.stringify({q: "hello world"});
// 'q=hello+world'  // Note: uses + for spaces

// Use URLSearchParams for modern code:
const params = new URLSearchParams({q: "hello world"});
params.toString();  // 'q=hello+world'

Practical Encoding Workflow

Here's a reliable workflow for handling URLs in web applications:

  1. Receiving user input: Don't encode yet. Store raw values.
  2. Building URLs: Encode each value with encodeURIComponent() when inserting into query parameters.
  3. Reading URL parameters: Use your framework's built-in parser (it handles decoding automatically).
  4. Displaying decoded values: Always sanitize for XSS after decoding.
  5. Logging URLs: Log the decoded version for readability, the encoded version for debugging.

When to Use an Online Tool

While you should always use proper encoding functions in code, online URL encoder/decoder tools are invaluable for:

An online tool like Risetop's URL Encoder/Decoder lets you paste a URL or string, instantly see the encoded/decoded version, and copy the result. Since it runs entirely in your browser, your data stays private.

Frequently Asked Questions

What is URL encoding (percent-encoding)?

URL encoding converts unsafe characters in a URL into a percent sign (%) followed by two hexadecimal digits. For example, a space becomes %20 and an ampersand becomes %26. This ensures URLs only contain ASCII characters that are safe for transmission over the internet.

What's the difference between encodeURI and encodeURIComponent?

encodeURI() is designed to encode full URLs and preserves characters like :/?#&= that have special meaning in URL structure. encodeURIComponent() encodes ALL non-alphanumeric characters including those structural characters, making it suitable for encoding query parameter values and path segments.

Should I use %20 or + for spaces in URLs?

In the path portion of a URL, use %20 (this is what encodeURI produces). In query strings, both + and %20 are commonly used—the + convention comes from application/x-www-form-urlencoded encoding. Modern frameworks like encodeURIComponent use %20 for spaces. Most servers accept both, but %20 is more universally correct.

Can URL encoding break my application?

Double encoding is the most common issue—when encoded text gets encoded again, producing values like %2520 instead of %20. This happens when you encode a string that's already encoded. Always decode first if you're unsure whether input is already encoded, and encode exactly once before sending data.

Do I need to encode the entire URL or just certain parts?

Only encode the specific components that may contain unsafe characters—typically query parameter values, path segments with user input, and fragment identifiers. Never encode the entire URL at once, as this would encode structural characters like :// and / that define the URL's meaning.