Β· By DevToolHub Team

URL Encoding & Percent-Encoding: Complete Guide with Examples

URL encoding (percent-encoding) is the mechanism that converts characters unsafe for use in URLs β€” such as spaces, ampersands, and non-ASCII letters β€” into a portable %XX hexadecimal format defined by RFC 3986. A space becomes %20, an & becomes %26, and the Cyrillic Π” becomes %D0%94. Every web developer encounters percent-encoding eventually, usually when a query parameter breaks or a redirect URL silently corrupts data.

This guide explains why URL encoding exists, which characters need encoding, the critical difference between encodeURI and encodeURIComponent, how to encode in JavaScript/Python/PHP/Go/Java, and the most common mistakes that cause double-encoding bugs and security vulnerabilities. Use our URL Encoder and URL Decoder to try it hands-on as you read.

Why URL Encoding Exists

URLs were designed to be transmitted using the ASCII character set. But the real world has spaces, accented characters, emoji, and special characters that have reserved meaning in URLs (like ?, &, =, #).

Percent-encoding solves this by replacing unsafe characters with % followed by two hexadecimal digits representing the character’s byte value:

CharacterEncodedReason
Space%20Not allowed in URLs
&%26Separates query parameters
=%3DSeparates key from value
?%3FStarts the query string
#%23Starts the fragment
/%2FPath separator
+%2BSometimes used for spaces
@%40Used in authority component
%%25The escape character itself

The encoding is defined in RFC 3986 Β§2.1, which is the authoritative specification for URI syntax.

Which Characters Need Encoding?

RFC 3986 defines these characters as unreserved (never need encoding):

A-Z  a-z  0-9  -  _  .  ~

Everything else should be percent-encoded when used in URL components. This includes:

  • Reserved characters: : / ? # [ ] @ ! $ & ' ( ) * + , ; =
  • Spaces and whitespace
  • Non-ASCII characters: accented letters, CJK characters, emoji
  • Control characters

Reserved characters can appear unencoded in the URL parts where they have their defined meaning (for example, ? in the query delimiter position). But if you want to use ? as data inside a query parameter value, it must be encoded as %3F.

encodeURI vs encodeURIComponent

JavaScript provides two encoding functions with different scopes:

encodeURI() β€” encodes a complete URI. Preserves characters that have meaning in the URL structure:

encodeURI('https://example.com/path?q=hello world&lang=en')
// "https://example.com/path?q=hello%20world&lang=en"
// Note: ://?&= are NOT encoded

encodeURIComponent() β€” encodes a single URI component (typically a query parameter value). Encodes everything except unreserved characters:

encodeURIComponent('hello world&lang=en')
// "hello%20world%26lang%3Den"
// Note: & and = ARE encoded

Rule of thumb: Use encodeURIComponent() for individual values. Use encodeURI() only when you have a complete URL that just needs non-ASCII characters encoded.

Building URLs Safely

The safest way to build URLs with query parameters in modern JavaScript is the URL and URLSearchParams APIs:

const url = new URL('https://example.com/search');
url.searchParams.set('q', 'hello world & more');
url.searchParams.set('page', '1');
url.toString()
// "https://example.com/search?q=hello+world+%26+more&page=1"

This handles all encoding automatically and correctly β€” no manual encodeURIComponent calls needed.

The + vs %20 Confusion

There are two ways to encode a space in URLs:

The + encoding comes from HTML forms. When a form is submitted with method="GET", spaces in form values are encoded as + in the query string. This is a separate standard from general URL encoding.

// Standard URL encoding
encodeURIComponent('hello world')  // "hello%20world"

// Form encoding
new URLSearchParams({q: 'hello world'}).toString()  // "q=hello+world"

Both are valid in query strings, but %20 is the universally safe choice. Some servers and APIs don’t correctly decode + as a space outside of form submissions.

Encoding Non-ASCII Characters (UTF-8)

Non-ASCII characters are first converted to their UTF-8 byte sequence, then each byte is percent-encoded:

CharacterUTF-8 BytesPercent-Encoded
Γ©0xC3 0xA9%C3%A9
ζ—₯0xE6 0x97 0xA5%E6%97%A5
πŸš€0xF0 0x9F 0x9A 0x80%F0%9F%9A%80

Modern browsers display non-ASCII characters natively in the address bar (a feature called IRI β€” Internationalized Resource Identifiers). But the actual HTTP request always uses the percent-encoded ASCII form.

encodeURIComponent('cafΓ©')  // "caf%C3%A9"
encodeURIComponent('ζ—₯本θͺž')  // "%E6%97%A5%E6%9C%AC%E8%AA%9E"

Encoding in Different Languages

Python:

from urllib.parse import quote, unquote, urlencode

quote('hello world')            # 'hello%20world'
quote('hello world', safe='')   # 'hello%20world' (encode everything)
unquote('hello%20world')        # 'hello world'
urlencode({'q': 'hello world'}) # 'q=hello+world'

PHP:

rawurlencode('hello world');  // "hello%20world"
urlencode('hello world');     // "hello+world"
rawurldecode('%E4%B8%AD');    // "δΈ­"

Go:

url.QueryEscape("hello world")  // "hello+world"
url.PathEscape("hello world")   // "hello%20world"

Java:

URLEncoder.encode("hello world", StandardCharsets.UTF_8)  // "hello+world"
// For %20 encoding, use URI class:
new URI("https", "example.com", "/path", "q=hello world", null).toASCIIString()

Bash (curl):

# curl encodes URLs with --data-urlencode
curl -G --data-urlencode "q=hello world" https://example.com/search

# Using printf + sed for manual encoding
printf '%s' "hello world" | jq -sRr @uri  # "hello%20world"

Common Mistakes

Double encoding. Encoding an already-encoded string produces %2520 instead of %20 (the % gets encoded to %25). Always encode raw values, never pre-encoded strings. If you’re unsure whether a string is already encoded, decode it first, then re-encode.

Not encoding path segments. File paths with spaces or special characters must be encoded: /files/my document.pdf should be /files/my%20document.pdf.

Using the wrong function. encodeURI on a query parameter value won’t encode & and =, breaking the query string. Always use encodeURIComponent for individual values.

Forgetting to decode on the server. Most web frameworks auto-decode URL parameters, but if you’re parsing raw URLs, remember to decode percent-encoded values before using them.

Encoding the entire URL with encodeURIComponent. This breaks the URL structure by encoding ://, /, ?, and &. Use encodeURIComponent only for individual values, not for complete URLs.

Not handling + correctly. Some backend frameworks decode + as a space only in query strings (form-encoded), but not in path segments. If your path contains a literal +, it must remain as %2B in the URL. Test your server’s behavior.

URL Encoding and Security

Improper URL encoding can lead to security vulnerabilities:

Open redirects. If your application takes a redirect_url parameter without validating it, an attacker could use encoded characters to bypass URL validation: %2F%2Fevil.com decodes to //evil.com, which some browsers interpret as a protocol-relative URL.

Path traversal. Encoded ../ sequences (%2E%2E%2F) might bypass naive path filters. Always decode URLs before checking for path traversal patterns.

Log injection. URL-encoded newlines (%0A, %0D) can inject fake log entries if URLs are logged without sanitization.

The defense is straightforward: always validate and sanitize after decoding, never before.

Percent-Encoding Quick Reference

Here are the most commonly searched percent-encoded characters and their decoded equivalents:

CharacterPercent-EncodedUnicode NameCommon Context
(space)%20 or +SpaceQuery strings, form data
!%21Exclamation markPasswords, expressions
#%23Hash / Number signFragment identifiers
$%24Dollar signFinancial values
%%25Percent signThe encoding character itself
&%26AmpersandQuery parameter separator
+%2BPlus signMath, phone numbers
,%2CCommaLists in parameters
/%2FForward slashPath separator
:%3AColonProtocols, ports
;%3BSemicolonParameter delimiters
=%3DEquals signKey-value pairs
?%3FQuestion markQuery string start
@%40At signEmail, authority
[%5BLeft bracketIPv6, arrays
]%5DRight bracketIPv6, arrays
{%7BLeft braceJSON in URLs
}%7DRight braceJSON in URLs
|%7CPipeDelimiters
(newline)%0ALine feedLog injection attacks
(tab)%09Horizontal tabData alignment

For non-ASCII characters, see the UTF-8 encoding section above. For a complete printable reference, see our URL Encoding Cheat Sheet.

Try It Yourself

Use our URL Encoder and URL Decoder to encode or decode text for URLs β€” processed entirely in your browser. For encoding HTML special characters, check out the HTML Entity Encoder.

For a compact printable reference of all percent-encoded characters, grab the URL Encoding Cheat Sheet.

You might also find our guide on URL slug best practices useful for creating SEO-friendly URLs.

Further Reading

FAQ

What is URL encoding?
URL encoding (percent-encoding) replaces unsafe characters in a URL with a percent sign followed by two hexadecimal digits representing the character's byte value. 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 is the difference between encodeURI and encodeURIComponent?
encodeURI() encodes a complete URL and preserves characters with structural meaning (like :, /, ?, &, =, #). encodeURIComponent() encodes a single value and encodes everything except unreserved characters (A-Z, a-z, 0-9, -, _, ., ~). Use encodeURIComponent() for query parameter values and encodeURI() only for complete URLs that need non-ASCII characters encoded.
Should I use %20 or + for spaces in URLs?
%20 is the standard percent-encoding for spaces defined in RFC 3986 and works everywhere. The + encoding comes from HTML form submission (application/x-www-form-urlencoded) and only works in query strings. When in doubt, use %20 β€” it is universally safe.
What is double encoding and how do I avoid it?
Double encoding happens when you encode an already-encoded string. The % character in %20 gets encoded to %25, producing %2520. To avoid this, always encode raw values, never pre-encoded strings. If you're unsure whether a string is already encoded, decode it first, then re-encode.
Do emoji and non-English characters work in URLs?
Yes, but they must be percent-encoded. A single emoji like πŸš€ becomes a long sequence like %F0%9F%9A%80 because it is encoded as UTF-8 bytes. Modern browsers display the original characters in the address bar, but the actual HTTP request uses the percent-encoded form.
Why does MDN recommend encodeURIComponent over encodeURI?
encodeURI preserves characters like &, =, and # that have structural meaning in a URL. If you use it on a query parameter value that contains an &, the browser interprets it as a parameter separator instead of literal data. encodeURIComponent encodes all reserved characters, making it safe for individual values. MDN recommends encodeURIComponent for any value that will be embedded inside a URL.
What is percent-encoding and how is it different from URL encoding?
Percent-encoding and URL encoding are the same thing β€” two names for the same mechanism. 'Percent-encoding' is the official name used in RFC 3986 because each encoded character starts with a percent sign (%). 'URL encoding' is the informal name most developers use. Both refer to converting unsafe characters into %XX hexadecimal sequences for use in URLs.
url encoding web http programming

Related Tools

Related Articles