Toolmingo
Guides4 min read

How to URL Encode a String: Percent-Encoding Explained

Learn what URL encoding is, why spaces and special characters break URLs, and how to encode or decode a string in JavaScript, Python, Go, PHP, and online.

Type a space into a URL bar and your browser silently replaces it with %20. That's URL encoding — and understanding it is essential for anyone building web apps, working with APIs, or debugging network requests.

Why URLs need encoding

URLs are restricted to a small set of safe characters: letters (A–Z, a–z), digits (0–9), and a handful of punctuation marks (-, _, ., ~). Everything else — spaces, ampersands, question marks, Unicode characters, slashes that aren't path separators — needs to be encoded before it can appear safely in a URL.

Without encoding, characters like & would be misread as query parameter separators, ? would signal the start of a query string, and spaces would make the URL invalid entirely.

What is percent-encoding?

Percent-encoding (also called URL encoding) represents a character as %XX, where XX is the character's hexadecimal ASCII (or UTF-8) byte value.

Character Encoded
space %20
& %26
= %3D
# %23
+ %2B
/ %2F
? %3F
@ %40

Note on spaces: You'll see spaces encoded as either %20 or +. The + convention comes from HTML form encoding (application/x-www-form-urlencoded). In a query string, + and %20 both mean space. In a path segment, only %20 is correct — + is a literal plus sign.

encodeURI vs encodeURIComponent

JavaScript provides two encoding functions, and mixing them up is a common source of bugs.

encodeURI(url) encodes a complete URL. It does not encode characters that have structural meaning in URLs: :, /, ?, #, &, =, @. Use it when you already have a full URL and just want to make it safe.

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

encodeURIComponent(value) encodes a single component (a query parameter value, a path segment). It encodes everything that encodeURI leaves alone. Use it for individual values you're inserting into a URL.

encodeURIComponent("price=100&currency=€")
// "price%3D100%26currency%3D%E2%82%AC"

The rule: if you're building a URL from parts, use encodeURIComponent on each dynamic value, not on the whole URL.

URL encoding in code

JavaScript:

// Encode a query parameter value
const query = encodeURIComponent("café & more");
const url = `https://example.com/search?q=${query}`;

// Decode
const original = decodeURIComponent("caf%C3%A9%20%26%20more");
console.log(original); // "café & more"

Python:

from urllib.parse import quote, unquote, urlencode

# Encode a single value
encoded = quote("café & more")
print(encoded)  # caf%C3%A9%20%26%20more

# Encode query parameters (dict → query string)
params = {"q": "hello world", "lang": "en"}
qs = urlencode(params)
print(qs)  # q=hello+world&lang=en

# Decode
print(unquote("caf%C3%A9%20%26%20more"))  # café & more

Go:

import (
    "fmt"
    "net/url"
)

// Encode
encoded := url.QueryEscape("café & more")
fmt.Println(encoded) // caf%C3%A9+%26+more

// Build a URL with query params
params := url.Values{}
params.Set("q", "hello world")
params.Set("lang", "en")
fmt.Println(params.Encode()) // lang=en&q=hello+world

// Decode
decoded, _ := url.QueryUnescape("caf%C3%A9%20%26%20more")
fmt.Println(decoded) // café & more

PHP:

// Encode
$encoded = urlencode("café & more");
echo $encoded; // caf%C3%A9+%26+more

// Encode for path segments (spaces → %20, not +)
$encoded = rawurlencode("café & more");
echo $encoded; // caf%C3%A9%20%26%20more

// Decode
echo urldecode("caf%C3%A9+%26+more"); // café & more

Command line (curl):

curl -G "https://example.com/search" \
  --data-urlencode "q=café & more"

Unicode and multi-byte characters

Characters outside ASCII — like é (U+00E9) or (U+20AC) — are first encoded as UTF-8, then each byte is percent-encoded.

é in UTF-8 is bytes 0xC3 0xA9, so it becomes %C3%A9. in UTF-8 is bytes 0xE2 0x82 0xAC, so it becomes %E2%82%AC.

This means a single character can expand into 9 characters in the URL. Long Unicode strings can produce very long encoded URLs — something to keep in mind for URL length limits (typically 2,000–8,000 characters depending on the browser and server).

Common mistakes

Double-encoding. If you encode %20 again, you get %2520 (the % itself becomes %25). This happens when a URL is encoded twice — once by your code, once by a library. The symptom is %25 appearing unexpectedly in your URLs or decoded values.

Encoding the entire URL. encodeURIComponent("https://example.com/path") will encode the :// and destroy the URL structure. Always encode only the dynamic parts, not the full URL.

Not encoding form data. When constructing application/x-www-form-urlencoded bodies manually, remember to encode both keys and values, and join them with &, not raw spaces.

Encode a URL string online

If you need to quickly encode or decode a URL string without writing code, use the URL Encoder/Decoder tool. Paste in a string, get the encoded or decoded result instantly. Runs entirely in your browser — nothing is sent to a server.

FAQ

Q: What's the difference between URL encoding and Base64 encoding? URL encoding (%XX) is designed to make any string safe to appear in a URL. Base64 is a way to represent binary data using only printable ASCII characters — it's not URL-safe by default (it uses + and /). Use URL encoding for query parameters; use Base64 when you need to embed binary data (images, files) in text contexts.

Q: Should I encode slashes in path segments? It depends. A / in a path segment that's a literal slash (not a path separator) must be encoded as %2F. However, some servers treat %2F in paths the same as / and route them identically. If you're passing a value that contains slashes as a path parameter, prefer putting it in the query string instead.

Q: Why does my browser show the decoded URL in the address bar? Modern browsers decode URLs for display, since https://example.com/search?q=café is more readable than https://example.com/search?q=caf%C3%A9. The actual HTTP request still uses the encoded form.

Q: What characters are safe and don't need encoding? Per RFC 3986, the "unreserved" characters never need encoding: A-Z a-z 0-9 - _ . ~. All other characters should be encoded in most contexts.

Related tools

Keep reading

All Toolmingotools are free & run in your browser

No sign-up, no upload, no watermark. Your files never leave your device.

Browse all tools