49 entries

URL Encoding Table

Percent encoding replaces a character with a percent sign and the hexadecimal value of its UTF-8 bytes, so a space becomes %20 and an accented e becomes %C3%A9. RFC 3986 splits the character set three ways: reserved characters that carry structural meaning, unreserved ones that must never be encoded, and everything else, which must be.

A URL is a structured string, and a small set of characters does the structural work — separating the scheme from the host, the path from the query, one parameter from the next. When one of those appears inside a value rather than between them, it has to be percent-encoded, or the server reads it as structure and the URL means something other than what you intended.

The tables below split the character set the way RFC 3986 does. The practical rule that falls out of them is worth stating first: encode each query value and path segment on its own, never the assembled URL, because encoding the whole thing escapes the separators that make it work.

Reserved characters

18 entries

These carry structural meaning. They are legal unencoded where they are doing that job, and must be encoded anywhere else — which in practice means anywhere inside a value.

Character Encoded What it does in a URL
: %3A Separates the scheme from the rest, and the host from the port.
/ %2F Separates path segments.
? %3F Starts the query string.
# %23 Starts the fragment. Never sent to the server.
[ %5B Wraps an IPv6 literal in the host.
] %5D Wraps an IPv6 literal in the host.
@ %40 Separates user information from the host.
! %21 Sub-delimiter. No fixed meaning, but reserved.
$ %24 Sub-delimiter.
& %26 Separates one query parameter from the next.
' %27 Sub-delimiter. Encoded by some libraries and left alone by others.
( %28 Sub-delimiter.
) %29 Sub-delimiter.
* %2A Sub-delimiter.
+ %2B Means a space in a query string. Encode it to pass a literal plus.
, %2C Sub-delimiter.
; %3B Sub-delimiter. Historically separated parameters instead of &.
= %3D Joins a parameter name to its value.

Characters that must always be encoded

14 entries

These are either illegal in a URL or unsafe in transit. Any correct implementation encodes every one of them.

Character Encoded Why
(space) %20 Illegal in a URL. Becomes a plus sign in a query string when form encoding is used.
" %22 Delimits URLs in HTML attributes, so an unencoded one breaks the markup.
< %3C Starts an HTML tag. Unencoded, it is an injection vector.
> %3E Ends an HTML tag.
% %25 Starts an escape sequence itself. Failing to encode it is what produces double encoding.
{ %7B Unsafe — historically altered in transit by gateways.
} %7D Unsafe.
| %7C Unsafe.
\ %5C Unsafe. Some clients silently convert it to a forward slash.
^ %5E Unsafe.
` %60 Unsafe.
(newline) %0A A raw newline in a URL enables response-splitting attacks.
(carriage return) %0D The same, and %0D%0A together are the classic header-injection payload.
(tab) %09 Stripped or mishandled inconsistently across clients.

Unreserved characters

7 entries

These never need encoding, and RFC 3986 says they should not be. Encoding them is harmless to a server but produces a technically different string, which breaks cache keys and signature checks.

Set Characters Notes
Uppercase letters A–Z Safe everywhere in a URL.
Lowercase letters a–z Safe everywhere. Host names are case-insensitive; paths usually are not.
Digits 0–9 Safe everywhere.
Hyphen - Safe. The preferred word separator in a path or a slug.
Underscore _ Safe, though hyphens read better in a URL.
Full stop . Safe, but a segment of exactly . or .. is special and gets resolved away.
Tilde ~ Safe. Older implementations encoded it as %7E, which is why both forms still appear.

Non-ASCII characters

10 entries

Anything above ASCII is encoded as its UTF-8 bytes, one escape per byte. That is why a single accented letter becomes two escapes and an emoji becomes four.

Character UTF-8 bytes Encoded
é C3 A9 %C3%A9
ü C3 BC %C3%BC
ñ C3 B1 %C3%B1
ß C3 9F %C3%9F
å C3 A5 %C3%A5
£ C2 A3 %C2%A3
E2 82 AC %E2%82%AC
E2 80 94 %E2%80%94
E4 B8 AD %E4%B8%AD
😀 F0 9F 98 80 %F0%9F%98%80

Notes

  • Encode each value on its own, never the assembled URL. Component encoding escapes the separators too, which is exactly right for a value going into a URL and catastrophic for a URL that already works.
  • A plus sign in a query string means a space, inherited from HTML form submission, and is decoded as one by essentially everything that reads a query. In a path segment it is a literal plus. Encode it as %2B whenever you mean the character itself.
  • The escape sequence is case-insensitive — %3A and %3a decode to the same character — but the uppercase form is what RFC 3986 recommends, and normalising to it keeps URLs comparable as plain strings.
  • If you see %2520 in a URL, a space became %20 and then the percent sign was itself encoded to %25. Something encoded an already-encoded value. Decode repeatedly until the string stops changing to recover the original.

Frequently asked questions

What is the percent encoding for a space?
%20, everywhere in a URL. In a query string a plus sign also decodes to a space, because HTML form submission has always encoded it that way, so both forms turn up in the wild. Use %20 when generating URLs — it is correct in every part of one, and the plus sign is not.
Which characters actually need encoding?
Everything except the unreserved set: letters, digits, hyphen, underscore, full stop and tilde. Anything else inside a value should be encoded. Reserved characters are legal unencoded only where they are doing their structural job, which is never the case inside a value somebody typed.
Why does one accented letter become two percent escapes?
Because percent encoding escapes bytes rather than characters, and most accented letters are two bytes in UTF-8 — so é encodes as %C3%A9. An emoji takes four bytes and becomes four escapes, which is also why a single emoji consumes a surprising amount of any URL length limit.
Should I encode the whole URL or just the value?
Just the value. Encoding a complete URL escapes the colons, slashes, question mark and ampersands that give it structure, leaving one long meaningless string instead of a working address. Encode each query value and path segment separately, then assemble the URL from the encoded pieces.
Is URL encoding a security control?
No. It makes a value safe to carry inside a URL and nothing more. It does not sanitise anything for HTML, SQL or a shell — each of those needs its own escaping, applied where the value is actually used. Treating percent encoding as sanitisation is a reliable way to build an injection bug.
Are %3A and %3a the same?
Yes. The hexadecimal digits are case-insensitive, so both decode to a colon. RFC 3986 recommends the uppercase form, and normalising to it matters whenever URLs are compared as strings — for cache keys, signature bases or deduplication, where two spellings would otherwise look like different URLs.

Related tools

All tools →
All references →

Last reviewed .