Which Characters Need URL Encoding?

URL encoding isn't all-or-nothing. Some characters are always safe, some always need encoding, and some depend on where in the URL they appear.

Always safe — never encode these

These characters are defined as "unreserved" in RFC 3986 and need no encoding anywhere in a URL:

A-Z  a-z  0-9  -  _  .  ~

Characters that must be encoded in query values

If you're building a query string value (the part after ?key=), everything except unreserved characters should be encoded. The most commonly missed ones:

CharacterEncodedReason
Space%20 or +Separates tokens
&%26Splits query parameters
=%3DSeparates key from value
+%2BDecoded as space in some parsers
#%23Starts a fragment
?%3FStarts the query string
/%2FPath separator
@%40Userinfo delimiter
:%3APort separator / scheme separator
%%25The encoding character itself

Characters that are safe in specific positions

Some characters have special meaning in one part of the URL but are fine in others:

  • / is a path separator but safe to leave unencoded within a path segment only if it separates segments. Inside a query value, encode it.
  • : is safe after the scheme (https:) but should be encoded inside a query value.
  • @ is safe in the host section (userinfo) but should be encoded in a query value.

The quick rule

When in doubt, encode it. Encoding a safe character (%41 for A) is harmless — all URL parsers decode it correctly. Not encoding an unsafe character can silently break your URL.

In JavaScript, encodeURIComponent is the right tool for encoding a query parameter value:

const value = "hello world & more";
const safe = encodeURIComponent(value);
// "hello%20world%20%26%20more"

Don't use encodeURI for values — it leaves &, =, and + unencoded. See encodeURIComponent vs encodeURI for the full comparison.

Try it

Paste any string into the URL encoder/decoder to instantly see the percent-encoded result. It handles the edge cases so you don't have to. For more background, see what is URL encoding.

Got a config file to check?

Open the config toolkit →