Should I encode spaces as %20 or + in URLs?

Both %20 and + can represent spaces, but they're used in different contexts.

The Short Answer:

  • Use %20 everywhere (modern standard)
  • Use + only in legacy query strings (older form submissions)

The Details:

%20 (Percent-20):

  • Works everywhere in URLs (path, query, fragment)
  • Modern standard for all URL encoding
  • Produced by encodeURIComponent() and encodeURI()
  • Safe and unambiguous

+ (Plus Sign):

  • Only valid in query strings (after the ?)
  • Legacy from application/x-www-form-urlencoded format
  • Used by HTML forms with GET method
  • Can be ambiguous (is it a plus or a space?)

Examples:

URL Paths - Use %20:

Good: /files/my%20document.pdf
Bad:  /files/my+document.pdf (treated as literal plus)

Query Strings - Both work:

Modern:  ?name=John%20Doe
Legacy:  ?name=John+Doe (still works)

Fragments - Use %20:

Good: #section%20one
Bad:  #section+one (treated as literal plus)

Which Should You Use?

Always use %20 if you're:

  • Writing modern code
  • Building APIs
  • Working with RESTful URLs
  • Want consistency
  • Encoding entire URLs
  • Encoding URL paths

Use + only if:

  • Maintaining legacy systems
  • Mimicking HTML form encoding
  • Specifically need application/x-www-form-urlencoded format

JavaScript Functions:

// Use these - they produce %20
encodeURIComponent("Hello World")  // "Hello%20World"
encodeURI("Hello World")           // "Hello%20World"

// Don't use this - deprecated
escape("Hello World")              // "Hello%20World" (but deprecated)

// Form encoding uses +
new URLSearchParams({q: "Hello World"}).toString() // "q=Hello+World"

The Problem with +:

In query strings, + is ambiguous:

?math=1+1      // Is this "1 1" or "1+1"?
?math=1%2B1    // Clearly "1+1"
?math=1%201    // Clearly "1 1"

Best Practice:

Use %20 everywhere for consistency:

// Good
const url = `/search?q=${encodeURIComponent(query)}`;

// Also good (for query params)
const params = new URLSearchParams({ q: query });
const url = `/search?${params}`; // Will use +, but that's okay

Decoding:

Both decode correctly:

decodeURIComponent("Hello%20World")  // "Hello World"
decodeURIComponent("Hello+World")    // "Hello+World" (literal plus!)

// For query strings with +, use:
"Hello+World".replace(/+/g, " ")    // "Hello World"
// Or URLSearchParams handles it automatically

Summary:

  • Modern code: Always use %20
  • Legacy systems: + in query strings is okay
  • When in doubt: %20 is always correct
  • Never use + in URL paths or fragments

Related Questions