URL Encoding Guide: When & Why to Encode URLs
What Is URL Encoding and Why Does It Exist?
URL encoding, formally called percent-encoding, is the mechanism defined by RFC 3986 for representing arbitrary data inside the components of a Uniform Resource Identifier. URLs can only contain a limited set of ASCII characters. When you need to include characters outside that safe set -- spaces, Unicode letters, ampersands, question marks used as literal data rather than delimiters -- they must be converted to a percent-encoded representation.
The encoding works by replacing each unsafe byte with a percent sign (%) followed by two hexadecimal digits representing the byte value. For example, a space (ASCII 32, hex 20) becomes %20, and an ampersand (ASCII 38, hex 26) becomes %26.
Without URL encoding, a query string like ?search=rock & roll would be ambiguous. Is the & a parameter separator or part of the search term? Percent-encoding removes all ambiguity: ?search=rock%20%26%20roll. If you need to encode or decode a URL right now, try our URL Encode/Decode tool -- it runs entirely in your browser.
The Anatomy of a URL
Before diving into encoding rules, it helps to understand the structure of a URL. Each component has different encoding requirements because different characters serve as delimiters in different parts.
scheme://authority/path?query#fragment
https://api.example.com:8080/users/john%20doe?role=admin&active=true#section-2
├─────┤ ├──────────────────┤├──────────────┤├──────────────────────┤├────────┤
scheme authority path query fragmentThe path uses / as a segment separator, so slashes must not be encoded in the path (but must be encoded inside a path segment if they are literal data). The query uses & and = as delimiters, so those characters must be encoded when they appear as data within parameter values. The fragment uses # as its prefix, so hash signs must be encoded everywhere else.
Reserved vs Unreserved Characters
RFC 3986 divides characters into two categories. Understanding this distinction is fundamental to knowing when encoding is required.
| Category | Characters | Encoding Rule |
|---|---|---|
| Unreserved | A-Z a-z 0-9 - _ . ~ | Never encode these |
| Reserved (gen-delims) | : / ? # [ ] @ | Encode when used as data, not as delimiters |
| Reserved (sub-delims) | ! $ & ' ( ) * + , ; = | Encode when used as data, not as delimiters |
Everything else -- spaces, Unicode characters, control characters, and any byte outside the ASCII printable range -- must always be percent-encoded. For multi-byte UTF-8 characters, each byte is encoded separately. For example, the euro sign (U+20AC) is encoded as %E2%82%AC (three bytes in UTF-8).
Common Percent-Encoded Characters Reference
| Character | Encoded | Common Use Case |
|---|---|---|
| Space | %20 or + | Search queries, file names |
| & | %26 | Value containing ampersand |
| = | %3D | Value containing equals sign |
| ? | %3F | Question mark in path/value |
| # | %23 | Hash in query parameters |
| / | %2F | Slash inside a path segment |
| @ | %40 | Email addresses in URLs |
| + | %2B | Plus sign in query values |
| % | %25 | Literal percent sign |
Bookmark our URL Encode/Decode for quick lookups. Paste any string and see the encoded output instantly.
JavaScript: encodeURI vs encodeURIComponent
JavaScript provides two built-in functions for URL encoding, and using the wrong one is one of the most common bugs in web development. Understanding the difference is essential for building correct URLs programmatically.
encodeURIComponent (Use This for Values)
This function encodes everything except unreserved characters. Use it when encoding individual components such as query parameter values, path segments, or fragment identifiers.
// Encoding a query parameter value
const searchTerm = 'rock & roll';
const url = `https://api.example.com/search?q=${encodeURIComponent(searchTerm)}`;
// Result: https://api.example.com/search?q=rock%20%26%20roll
// Encoding a path segment
const fileName = 'my report (final).pdf';
const downloadUrl = `/files/${encodeURIComponent(fileName)}`;
// Result: /files/my%20report%20(final).pdf
// Encoding a value that contains special URL characters
const callback = 'https://mysite.com/callback?token=abc';
const redirect = `/login?redirect=${encodeURIComponent(callback)}`;
// Result: /login?redirect=https%3A%2F%2Fmysite.com%2Fcallback%3Ftoken%3DabcencodeURI (Use This for Full URIs)
This function preserves characters that have structural meaning in a complete URI (: / ? # & =). Use it only when encoding an entire URI that already has the correct structure but may contain unsafe characters in its components.
// Encoding a full URI with spaces
const uri = 'https://example.com/my path/file name.html';
const encoded = encodeURI(uri);
// Result: https://example.com/my%20path/file%20name.html
// Note: slashes and colons are preserved
// WRONG: Using encodeURIComponent on a full URL
const broken = encodeURIComponent(uri);
// Result: https%3A%2F%2Fexample.com%2Fmy%20path%2Ffile%20name.html
// This is NOT a valid URL anymore!Decoding Functions
// Decode a component
decodeURIComponent('rock%20%26%20roll'); // 'rock & roll'
// Decode a full URI
decodeURI('https://example.com/my%20path/'); // 'https://example.com/my path/'
// Handle double-encoded strings (common bug)
const doubleEncoded = 'rock%2520%2526%2520roll';
decodeURIComponent(doubleEncoded); // 'rock%20%26%20roll'
decodeURIComponent(decodeURIComponent(doubleEncoded)); // 'rock & roll'URL Encoding in Other Languages
Python
from urllib.parse import quote, quote_plus, unquote, urlencode
# Encode a path segment (spaces become %20)
quote('rock & roll') # 'rock%20%26%20roll'
# Encode for form data (spaces become +)
quote_plus('rock & roll') # 'rock+%26+roll'
# Build a complete query string
params = {'q': 'rock & roll', 'page': '1'}
urlencode(params) # 'q=rock+%26+roll&page=1'
# Decode
unquote('rock%20%26%20roll') # 'rock & roll'Go
import "net/url"
// Encode a query parameter
encoded := url.QueryEscape("rock & roll") // "rock+%26+roll"
// Encode a path segment
pathEncoded := url.PathEscape("rock & roll") // "rock%20&%20roll"
// Build a URL with query parameters
params := url.Values{}
params.Set("q", "rock & roll")
params.Set("page", "1")
queryString := params.Encode() // "page=1&q=rock+%26+roll"PHP
// Encode for query strings (spaces become +)
urlencode('rock & roll'); // "rock+%26+roll"
// Encode per RFC 3986 (spaces become %20)
rawurlencode('rock & roll'); // "rock%20%26%20roll"
// Build query string from array
http_build_query(['q' => 'rock & roll', 'page' => 1]);
// "q=rock+%26+roll&page=1"Spaces: %20 vs + (The Eternal Confusion)
One of the most confusing aspects of URL encoding is that spaces can be represented as either %20 or +. The difference comes from two different standards.
| Standard | Space Encoding | Used In |
|---|---|---|
| RFC 3986 (percent-encoding) | %20 | URL paths, fragments, general URIs |
| application/x-www-form-urlencoded | + | HTML form submissions, query strings |
In practice, most web servers and frameworks accept both %20 and + in query strings. However, in URL paths, only %20 is correct -- a literal + in a path is interpreted as a plus sign, not a space. This distinction has caused countless bugs in REST APIs.
Common URL Encoding Pitfalls
1. Double Encoding
The most common bug is encoding a string that has already been encoded. This turns %20 into %2520 (the percent sign gets encoded again). Always check whether your input has already been encoded before applying encoding functions.
// BUG: Double encoding
const alreadyEncoded = 'hello%20world';
encodeURIComponent(alreadyEncoded);
// 'hello%2520world' -- WRONG! The % got encoded to %25
// FIX: Decode first, then re-encode if needed
encodeURIComponent(decodeURIComponent(alreadyEncoded));
// 'hello%20world' -- Correct2. Encoding the Entire URL Instead of Components
// WRONG: Encoding the full URL with encodeURIComponent
const url = 'https://api.example.com/search?q=hello world';
encodeURIComponent(url);
// 'https%3A%2F%2Fapi.example.com%2Fsearch%3Fq%3Dhello%20world'
// This is NOT a valid URL!
// CORRECT: Only encode the parameter value
const baseUrl = 'https://api.example.com/search';
const query = 'hello world';
`${baseUrl}?q=${encodeURIComponent(query)}`;
// 'https://api.example.com/search?q=hello%20world'3. Forgetting to Encode Hash and Ampersand
If a parameter value contains # or &, failure to encode truncates the URL. The browser interprets # as a fragment start and & as a parameter separator, silently dropping the rest of your value.
4. Not Encoding Unicode Characters
// Unicode characters MUST be encoded
const city = 'Sao Paulo';
encodeURIComponent(city); // 'Sao%20Paulo'
const japanese = 'Tokyo';
encodeURIComponent(japanese); // 'Tokyo' (ASCII, no encoding needed)
const kanji = '東京';
encodeURIComponent(kanji); // '%E6%9D%B1%E4%BA%AC'URL Encoding for REST APIs
When building REST APIs, URL encoding is critical for constructing correct requests. Different parts of the URL have different encoding requirements. Here is how encoding interacts with common API patterns.
// Building API URLs with the URL constructor (recommended)
const url = new URL('https://api.example.com/v2/users');
// Query parameters are automatically encoded
url.searchParams.set('name', 'John & Jane');
url.searchParams.set('role', 'admin/manager');
url.searchParams.set('q', 'status=active');
console.log(url.toString());
// https://api.example.com/v2/users?name=John+%26+Jane&role=admin%2Fmanager&q=status%3Dactive
// Path segments need manual encoding
const userId = '[email protected]';
const apiUrl = `https://api.example.com/v2/users/${encodeURIComponent(userId)}/profile`;
// https://api.example.com/v2/users/user%40example.com/profileThe URL constructor and URLSearchParams API handle query parameter encoding automatically, making them the safest approach for building URLs in JavaScript. For more on REST API conventions, see our guide on API Response Codes Best Practices, and test your API status codes with our HTTP Status Codes reference tool.
URL Encoding and Base64: When to Use Each
Developers sometimes confuse URL encoding with Base64 encoding. They serve different purposes. URL encoding makes strings safe for URLs by encoding individual unsafe characters. Base64 encoding converts arbitrary binary data into an ASCII string representation. When you need to pass binary data (like an image or encrypted token) in a URL, you typically Base64-encode it first, then URL-encode the result (or use URL-safe Base64).
// Standard Base64 contains + and / which need URL encoding
const base64Token = 'eyJhbGci+OiJI/UzI1NiJ9';
encodeURIComponent(base64Token);
// 'eyJhbGci%2BOiJI%2FUzI1NiJ9'
// URL-safe Base64 replaces + with - and / with _
// No additional URL encoding needed!
const urlSafeBase64 = 'eyJhbGci-OiJI_UzI1NiJ9';You can convert between standard and URL-safe Base64 using our Base64 Encoder/Decoder. For JWT tokens, which use URL-safe Base64, check out our JWT Decoder to inspect the header and payload without any encoding headaches.
URL Encoding Best Practices
- Always use encodeURIComponent for parameter values -- Never concatenate raw user input into URLs. Always encode individual values, not the full URL.
- Use the URL/URLSearchParams API -- Let the browser handle encoding for query strings. It is more reliable than manual string concatenation.
- Decode on the server, not the client -- Most web frameworks automatically decode URL parameters. Avoid manually decoding on the client side unless you have a specific reason.
- Watch for double encoding -- If you see
%25in your URLs, something is being encoded twice. Trace the encoding pipeline to find the duplicate step. - Use URL-safe Base64 for tokens -- When passing JWT tokens or other Base64-encoded data in URLs, use the URL-safe variant to avoid extra encoding.
- Test with edge cases -- Always test URLs containing
&,#,%,+, Unicode characters, and empty strings. Use our URL Encoder to verify encoding is correct. - Validate and sanitize inputs -- URL encoding prevents parsing errors but does not prevent injection attacks. Always validate that decoded values match expected patterns using regex validation.
Frequently Asked Questions
What is the difference between encodeURI and encodeURIComponent?
encodeURI encodes a full URI but preserves characters like :, /, ?, #, and & that have structural meaning in URLs. encodeURIComponent encodes everything except unreserved characters (letters, digits, -, _, ., ~), making it the correct choice for encoding individual query parameter values, path segments, or fragment identifiers.
Why do spaces become %20 or + in URLs?
Spaces are not allowed in URLs per RFC 3986. In percent-encoding, a space becomes %20. However, the application/x-www-form-urlencoded format (used in HTML form submissions) encodes spaces as + instead. Both represent a space, but %20 is the standard for URL paths while + is specific to form data in query strings.
Which characters need to be URL encoded?
All characters outside the unreserved set (A-Z, a-z, 0-9, -, _, ., ~) should be percent-encoded when used as data in URLs. Reserved characters like : / ? # & = must be encoded when they appear inside a query parameter value or path segment rather than serving their delimiter purpose.
Encode & Decode URLs Instantly
Stop guessing which characters need encoding. Paste any string into our free URL Encode/Decode and get correct percent-encoded output instantly. Supports full Unicode, runs entirely in your browser, no data sent to any server.
Open URL Encode/DecodeRelated Articles
Base64 Encoding Explained
When and why to use Base64 encoding in your projects.
HTTP Status Codes Guide
Every HTTP status code explained with real-world context.
JWT Tokens Explained
Deep dive into JSON Web Token structure and security.
Hash Functions Explained
MD5, SHA-256, bcrypt and when to use each one.