Copynix
Dev Tools7 min read

URL Encoding Explained: Percent-Encoding for Web Developers

A practical guide to URL encoding (percent-encoding) — why it exists, what characters need encoding, the difference between encodeURI and encodeURIComponent, and how to handle query strings safely in JavaScript, Python, and curl.

T

Nguyễn Văn Thương

Founder, Copynix

URL encodingpercent encodingquery string

What Is URL Encoding?

URL encoding, formally called percent-encoding, is the process of replacing characters that are not allowed in a URL with a percent sign (%) followed by the character's two-digit hexadecimal byte value. For example, a space becomes %20, an ampersand becomes %26, and a forward slash becomes %2F.

This encoding is required by RFC 3986 (Uniform Resource Identifiers) to ensure URLs are transmitted correctly across all HTTP clients, servers, proxies, and network intermediaries. Different components in a URL have different character rules — what is allowed in a path segment is different from what is allowed in a query string value.

Why Some Characters Need Encoding

A URL has a defined structure: scheme://host/path?query#fragment. Characters like ?, &, =, #, and / are structural delimiters — they separate parts of the URL. If these characters appear in a URL component's value (a query parameter value, for example), they must be encoded to prevent them from being interpreted as structure.

// Problem: ampersand in a value breaks the query string
https://example.com/search?q=fish & chips&lang=en
// The server sees: q="fish ", lang="en", and an unrecognized "chips" parameter

// Correct: encode the ampersand in the value
https://example.com/search?q=fish%20%26%20chips&lang=en
// The server sees: q="fish & chips", lang="en"

Which Characters Must Be Encoded?

RFC 3986 defines two classes of characters:

CharacterEncodedCommon context
Space%20 (or + in forms)Query values, path segments
&%26Values containing ampersands
=%3DValues containing equals signs
+%2BWhen + must not mean "space" (in form encoding)
/%2FPath values, base64url strings
@%40Email addresses in query strings
#%23Values that should not be treated as fragments

encodeURI vs. encodeURIComponent in JavaScript

JavaScript provides two built-in functions for URL encoding, and choosing the wrong one is a very common mistake:

// encodeURI — encodes a complete URL; preserves structural characters
encodeURI("https://example.com/search?q=hello world")
// → "https://example.com/search?q=hello%20world"
// Note: &, =, ?, / are NOT encoded — they're treated as structure

// encodeURIComponent — encodes a URL component; encodes structural chars too
encodeURIComponent("hello world & more")
// → "hello%20world%20%26%20more"
// Note: &, =, ?, / ARE encoded — they're treated as data

// The correct pattern for building query strings:
const params = new URLSearchParams({
  q: "fish & chips",
  category: "food/seafood",
  redirect: "https://example.com/page?ref=home"
});
const url = `https://example.com/search?${params}`;
// URLSearchParams handles encoding correctly for each value

Rule of thumb: Use encodeURIComponent when encoding a query parameter value or a path segment. Use encodeURI only when encoding a complete URL that has already been properly assembled. Better yet, use URLSearchParams to build query strings — it handles encoding automatically.

Form Encoding vs. Percent-Encoding

HTML forms use a related but different encoding scheme called application/x-www-form-urlencoded, where spaces are encoded as + (not %20) and newlines become %0D%0A. This is what browsers send when you submit a form with method="POST".

# HTML form submission body (application/x-www-form-urlencoded)
name=John+Doe&message=Hello+World

# Percent-encoding (RFC 3986)
name=John%20Doe&message=Hello%20World

When receiving form data in your backend, ensure your framework's form parser handles both + and %20 for spaces. Most do, but the distinction matters when you are manually parsing form bodies.

URL Encoding in Practice

curl

# Let curl handle encoding with --data-urlencode
curl -G https://api.example.com/search   --data-urlencode "q=fish & chips"   --data-urlencode "page=1"

# Or encode manually
curl "https://api.example.com/search?q=fish%20%26%20chips&page=1"

Python

from urllib.parse import urlencode, quote, unquote

# Encoding a single value
quote("fish & chips")          # 'fish%20%26%20chips'
quote("fish & chips", safe='') # same — safe='' encodes / too

# Building a query string
params = {"q": "fish & chips", "page": 1}
urlencode(params)  # 'q=fish+%26+chips&page=1'

# Decoding
unquote("fish%20%26%20chips")  # 'fish & chips'

Go

import "net/url"

// Encoding a value
url.QueryEscape("fish & chips")  // "fish+%26+chips"
url.PathEscape("path/segment")   // "path%2Fsegment"

// Building a URL with encoded parameters
params := url.Values{"q": {"fish & chips"}, "page": {"1"}}
u := "https://api.example.com/search?" + params.Encode()

Decoding: The Reverse Operation

When your server receives a URL or form submission, the framework automatically decodes percent-encoded values before passing them to your route handler. You should never manually decode values that your framework has already decoded — double-decoding is a security risk (a technique used in some path traversal attacks).

Only manually decode when you are processing raw URL strings directly, such as when parsing redirect URIs, constructing next-hop URLs from query parameters, or reading raw request bodies without a framework.

Use the Copynix URL Encoder

When you need to quickly encode or decode a URL value during development — checking what a server receives, constructing a query string manually, or debugging a 400 Bad Request — use the Copynix URL Encoder/Decoder. It handles full UTF-8 multibyte characters, supports both standard percent-encoding and form encoding, and runs entirely in your browser without sending your data anywhere.

Summary

URL encoding exists to keep structural URL characters (?, &, =, /, #) unambiguous when they appear as part of a value. Always encode individual query parameter values with encodeURIComponent (or the equivalent in your language), never encode the full URL as a whole. Use URLSearchParams in JavaScript and the equivalent query-building utilities in other languages to handle encoding automatically and correctly.

Free tool

Try it yourself — URL Encoder / Decoder

Runs entirely in your browser. No signup, no data sent to servers.

Open URL Encoder / Decoder
T

Nguyễn Văn Thương

Founder & Developer · Copynix

Software developer focused on web security and developer tooling. Built Copynix to provide privacy-respecting browser tools that never send your data to a server.

More about the author →

Keep Reading

All articles →
All articlesBrowse tools →