URL Encoding Guide: Everything Developers Need to Know

Complete guide to URL encoding for developers. Learn when to encode URLs, which characters need encoding, and how to handle query strings.

general November 23, 2025 5 min read

URL encoding (also called percent encoding) is essential for web development. It ensures that URLs are transmitted correctly by converting special characters into a format that can be safely used in URLs. This guide covers everything you need to know about URL encoding.

What is URL Encoding?

URL encoding is the process of converting characters into a format that can be transmitted over the Internet. URLs can only contain a limited set of characters from the ASCII character set. Any character outside this set must be encoded.

The encoding uses the percent sign (%) followed by two hexadecimal digits representing the character’s ASCII code. For example:

  • Space becomes %20
  • @ becomes %40
  • # becomes %23

Why URL Encoding is Necessary

URLs have a specific structure and certain characters have special meanings:

https://example.com/path?name=value&other=value#section
         └─────┬─────┘ └┬┘ └──┬──┘ └┬┘ └──┬──┘ └──┬──┘
              host    path query  &  query   fragment

Special characters like ?, &, =, and # are used to structure the URL. If your data contains these characters, they must be encoded to avoid confusion.

URL Encoder/Decoder

Encode and decode URLs instantly with our free online tool.

Try Tool →

Characters That Need Encoding

Reserved Characters

These characters have special meaning in URLs and must be encoded when used as data:

CharacterEncodedPurpose
:%3ASeparates protocol/port
/%2FPath separator
?%3FQuery string start
#%23Fragment identifier
[%5BIPv6 addresses
]%5DIPv6 addresses
@%40User info separator
!%21Sub-delimiters
$%24Sub-delimiters
&%26Parameter separator
'%27Sub-delimiters
(%28Sub-delimiters
)%29Sub-delimiters
*%2ASub-delimiters
+%2BSpace (in query)
,%2CSub-delimiters
;%3BSub-delimiters
=%3DKey-value separator

Unsafe Characters

These characters should always be encoded:

CharacterEncodedReason
Space%20 or +Not allowed in URLs
<%3CDelimiters
>%3EDelimiters
"%22Delimiters
{%7BUnwise
}%7DUnwise
|%7CUnwise
\\%5CUnwise
^%5EUnwise
`%60Unwise

Non-ASCII Characters

Any character outside the ASCII range (like émojis, Chinese characters, etc.) must be encoded:

Hello 世界 → Hello%20%E4%B8%96%E7%95%8C

URL Encoding in Different Parts

Different parts of a URL have different encoding rules:

1. Path Encoding

// Encode path segments
const path = encodeURIComponent('my file.pdf');
const url = `https://example.com/files/${path}`;
// Result: https://example.com/files/my%20file.pdf

2. Query String Encoding

// Encode query parameters
const search = encodeURIComponent('hello world');
const url = `https://example.com/search?q=${search}`;
// Result: https://example.com/search?q=hello%20world

3. Fragment Encoding

// Encode fragment identifiers
const section = encodeURIComponent('Section #1');
const url = `https://example.com/page#${section}`;
// Result: https://example.com/page#Section%20%231

Encoding vs Decoding

Encoding

Converting special characters to percent-encoded format:

Input:  Hello World!
Output: Hello%20World%21

Decoding

Converting percent-encoded characters back to original:

Input:  Hello%20World%21
Output: Hello World!

URL Encoding in Different Languages

JavaScript (Browser & Node.js)

// Encode individual components
const encoded = encodeURIComponent('hello world & more');
console.log(encoded); // hello%20world%20%26%20more

// Decode
const decoded = decodeURIComponent('hello%20world%20%26%20more');
console.log(decoded); // hello world & more

// Encode entire URL (preserves :, /, ?, etc.)
const fullUrl = encodeURI('https://example.com/path?q=hello world');
console.log(fullUrl); // https://example.com/path?q=hello%20world

Important: Use encodeURIComponent() for query parameters, not encodeURI()!

Python

from urllib.parse import quote, unquote

# Encode
encoded = quote('hello world & more')
print(encoded)  # hello%20world%20%26%20more

# Decode
decoded = unquote('hello%20world%20%26%20more')
print(decoded)  # hello world & more

# Encode with safe characters
encoded = quote('hello/world', safe='/')
print(encoded)  # hello/world

PHP

// Encode
$encoded = urlencode('hello world & more');
echo $encoded; // hello+world+%26+more

// Decode
$decoded = urldecode('hello+world+%26+more');
echo $decoded; // hello world & more

// Raw encoding (uses %20 instead of +)
$encoded = rawurlencode('hello world');
echo $encoded; // hello%20world

Java

import java.net.URLEncoder;
import java.net.URLDecoder;

// Encode
String encoded = URLEncoder.encode("hello world & more", "UTF-8");
System.out.println(encoded); // hello+world+%26+more

// Decode
String decoded = URLDecoder.decode("hello+world+%26+more", "UTF-8");
System.out.println(decoded); // hello world & more

Common Use Cases

1. Search Queries

const query = 'javascript & typescript';
const url = `https://example.com/search?q=${encodeURIComponent(query)}`;
// https://example.com/search?q=javascript%20%26%20typescript

2. API Parameters

const email = 'user@example.com';
const url = `https://api.example.com/users?email=${encodeURIComponent(email)}`;
// https://api.example.com/users?email=user%40example.com

3. Redirect URLs

const returnUrl = 'https://example.com/dashboard?tab=settings';
const loginUrl = `https://auth.example.com/login?redirect=${encodeURIComponent(returnUrl)}`;
// https://auth.example.com/login?redirect=https%3A%2F%2Fexample.com%2Fdashboard%3Ftab%3Dsettings

4. Form Data

const formData = new URLSearchParams();
formData.append('name', 'John Doe');
formData.append('email', 'john@example.com');
formData.append('message', 'Hello & welcome!');

fetch('/api/contact', {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: formData.toString()
});
// Body: name=John+Doe&email=john%40example.com&message=Hello+%26+welcome%21

Space Encoding: %20 vs +

There are two ways to encode spaces in URLs:

  • %20 - Standard percent encoding
  • + - Legacy encoding (only in query strings)
// Modern approach (use %20)
encodeURIComponent('hello world'); // hello%20world

// Legacy approach (+ in query strings)
'hello world'.replace(/ /g, '+'); // hello+world

Best practice: Use %20 everywhere for consistency.

Common Pitfalls

1. Double Encoding

// ❌ Wrong - encoding twice
const param = encodeURIComponent('hello world');
const url = `https://example.com?q=${encodeURIComponent(param)}`;
// Result: ?q=hello%2520world (wrong!)

// ✅ Correct - encode once
const param = 'hello world';
const url = `https://example.com?q=${encodeURIComponent(param)}`;
// Result: ?q=hello%20world

2. Using encodeURI() for Parameters

// ❌ Wrong - doesn't encode &, =, etc.
const param = 'a=1&b=2';
const url = `https://example.com?data=${encodeURI(param)}`;
// Result: ?data=a=1&b=2 (broken!)

// ✅ Correct - use encodeURIComponent
const param = 'a=1&b=2';
const url = `https://example.com?data=${encodeURIComponent(param)}`;
// Result: ?data=a%3D1%26b%3D2

3. Not Encoding at All

// ❌ Wrong - special characters break the URL
const search = 'hello & goodbye';
const url = `https://example.com?q=${search}`;
// Result: ?q=hello & goodbye (broken!)

// ✅ Correct
const search = 'hello & goodbye';
const url = `https://example.com?q=${encodeURIComponent(search)}`;
// Result: ?q=hello%20%26%20goodbye

Security Considerations

1. XSS Prevention

Always encode user input before putting it in URLs:

// ❌ Dangerous
const userInput = '<script>alert("xss")</script>';
window.location = `/search?q=${userInput}`;

// ✅ Safe
const userInput = '<script>alert("xss")</script>';
window.location = `/search?q=${encodeURIComponent(userInput)}`;

2. SQL Injection

URL encoding doesn’t protect against SQL injection. Always use parameterized queries:

// ❌ Still vulnerable
const id = encodeURIComponent("1' OR '1'='1");
const query = `SELECT * FROM users WHERE id = '${id}'`;

// ✅ Use parameterized queries
const id = "1' OR '1'='1";
db.query('SELECT * FROM users WHERE id = ?', [id]);

3. Open Redirects

Validate redirect URLs even if encoded:

// ❌ Dangerous
const redirect = decodeURIComponent(params.get('redirect'));
window.location = redirect; // Could redirect anywhere!

// ✅ Validate first
const redirect = decodeURIComponent(params.get('redirect'));
if (redirect.startsWith('/') || redirect.startsWith('https://yourdomain.com')) {
  window.location = redirect;
}

Best Practices

  1. Always encode user input in URLs
  2. Use encodeURIComponent() for query parameters
  3. Use encodeURI() only for full URLs
  4. Decode once when reading parameters
  5. Validate after decoding for security
  6. Use URLSearchParams for building query strings
  7. Test with special characters like &, =, #, +

Modern Approach: URLSearchParams

Instead of manual encoding, use the URLSearchParams API:

// Modern way
const params = new URLSearchParams();
params.append('name', 'John Doe');
params.append('email', 'john@example.com');
params.append('tags', 'javascript & typescript');

const url = `https://example.com/search?${params.toString()}`;
// https://example.com/search?name=John+Doe&email=john%40example.com&tags=javascript+%26+typescript

// Reading parameters
const urlParams = new URLSearchParams(window.location.search);
const name = urlParams.get('name'); // Automatically decoded

Frequently Asked Questions

What's the difference between encodeURI() and encodeURIComponent()?

encodeURI() is for encoding full URLs and preserves characters like :, /, ?, and &. encodeURIComponent() encodes everything except letters, numbers, and -_.~, making it perfect for query parameters. Always use encodeURIComponent() for user data.

Why do some URLs use + for spaces and others use %20?

Both are valid. The + is a legacy encoding used in query strings (application/x-www-form-urlencoded). %20 is the standard percent encoding. Modern code should use %20 for consistency, though browsers accept both.

Do I need to encode URLs in HTML attributes?

Yes! URLs in HTML attributes (like href or src) should be properly encoded. However, you also need to HTML-escape the URL itself. For example: <a href="/search?q=hello%20world&amp;lang=en">.

Can URL encoding prevent XSS attacks?

URL encoding helps but isn't sufficient alone. You must also HTML-escape output, validate input, use Content Security Policy, and follow other security best practices. URL encoding is just one layer of defense.

How do I handle international characters in URLs?

International characters are automatically converted to UTF-8 and then percent-encoded. For example, '世界' becomes '%E4%B8%96%E7%95%8C'. Use encodeURIComponent() and it handles this automatically.

Conclusion

URL encoding is a fundamental skill for web developers. It ensures that URLs work correctly regardless of the data they contain. Remember to:

  • Use encodeURIComponent() for query parameters and user data
  • Use encodeURI() only for full URLs
  • Never trust user input - always encode it
  • Use modern APIs like URLSearchParams when possible
  • Test with special characters

URL Encoder/Decoder

Try our free URL encoding tool to encode and decode URLs instantly.

Try Tool →

Related Resources