Javascript is required
TroubleshootingPublished 2026-07-28Updated 2026-08-085 min read

URL Query Encoding: Plus Signs, Spaces and %2B

Sending text containing plus signs + (such as Base64 signatures a+b/c== or phone numbers +86) in URL query parameters often causes servers to decode them as spaces ' '. This article explains form-encoding history and %2B percent-encoding defenses.

By: Tiny
URL EncodePlus SignSpaceQuery Parameter

1. Problem: plus signs silently turning into spaces in URL queries

When transmitting data with + characters (like Base64 string eyJ+...), sending ?token=eyJ+... unencoded results in servers decoding the parameter as eyJ ... (replacing + with a space). This stems from the legacy application/x-www-form-urlencoded spec.

2. Minimal reproduction: raw plus sign vs %2B encoded parsing comparison

The comparison below illustrates how plus signs behave differently during server-side decoding:

/* Scenario 1: sending raw plus sign */
// URL: https://api.example.com/auth?phone=+8613800000000
// Server decodeURIComponent("+8613800000000") -> " 8613800000000" (plus sign becomes space!)

/* Scenario 2: explicitly encoding plus sign as %2B */
// URL: https://api.example.com/auth?phone=%2B8613800000000
// Server decodeURIComponent("%2B8613800000000") -> "+8613800000000" (plus sign preserved!)

3. Root cause: conflict between HTML form encoding and RFC 3986

Under traditional HTML form encoding (application/x-www-form-urlencoded), spaces are encoded as +. When server decoders process query strings under form rules, they automatically replace + with spaces. In standard RFC 3986, spaces encode as %20 and + is a reserved character that requires percent-encoding as %2B to be read literally.

4. Recommendation: use %2B escaping and modern URLSearchParams APIs

1. After calling encodeURIComponent, append .replace(/+/g, '%2B') to force plus sign percent-encoding. 2. Use the modern JavaScript URLSearchParams API, which manages plus sign and space encoding automatically. 3. Adopt URL-Safe Base64 encoding for payload strings.

5. Complete code: safe plus sign encoder and form-compatible decoder

This TypeScript snippet demonstrates proper + handling for query parameters, preventing server-side space misinterpretation.

function safeEncodeQueryParam(paramValue: string, useFormUrlEncodedMode = false): string {
  if (useFormUrlEncodedMode) {
    return paramValue.replace(/%/g, "%25").replace(/\+/g, "%2B").replace(/ /g, "+");
  }
  return encodeURIComponent(paramValue).replace(/\+/g, "%2B");
}

function decodeQueryParam(encodedValue: string, isFormUrlEncoded = false): string {
  if (isFormUrlEncoded) {
    return decodeURIComponent(encodedValue.replace(/\+/g, " "));
  }
  return decodeURIComponent(encodedValue);
}

const base64Data = "data+key==";
const encoded = safeEncodeQueryParam(base64Data, true);
console.log(encoded); // "data%2Bkey%3D%3D"
console.log(decodeQueryParam(encoded, true)); // "data+key==" (plus sign successfully restored)

6. Incorrect approaches

Appending raw Base64 strings to query parameters without encoding. Writing naive str.replace(' ', '+') server workarounds that mistakenly corrupt legitimate spaces.

7. Boundaries: POST Body vs Query parameter decoder differences

Backend frameworks (like Java Spring or Express body-parser) may handle + and %20 differently between POST Bodies and URL Query parameters.

8. Verification

Run end-to-end API tests with Base64 values containing +, %, &, =, spaces, and missing padding. Assert strict equality after server decoding, including repeated and empty parameters.

9. FAQ

Why does encodeURIComponent('+') return + instead of %2B? Per RFC 3986, + is a reserved character allowed in URIs, so encodeURIComponent leaves it unescaped by default.

Should spaces in URLs use %20 or +? Standard URL queries prefer %20; form submissions use +.

What is the safest way to pass Base64 strings in URLs? Use URL-Safe Base64 (replacing + with -, / with _, and stripping = padding).

10. Summary

Plus signs in URL queries easily turn into spaces during server decoding. Explicitly encoding + as %2B or using URL-Safe Base64 provides a foolproof defense.

Sources and further reading

Specifications and references for checking the article’s technical details.

Related articles

Keep exploring

Use the related browser tool to test the workflow with your own sample data.

Open related tool