URL Encoding Across Programming Languages: A Complete Guide

Early in my career, I built a search feature where the query parameter was ?q= followed by the user's search term. When a user searched for "C++ tutorial", the server returned zero results. The + in "C++" was being decoded as a space, making the query "C tutorial" (three spaces).

That was the day I learned that URL encoding is not the same in every language. The encoders have different defaults, different character sets, and different assumptions about what you are encoding.

JavaScript: Two Functions for Different Purposes

JavaScript has two URL encoding functions, and using the wrong one is my most frequently caught code review mistake.

const query = "C++ tutorial & reference";

// encodeURI: encodes the full URI, preserves URI-special characters
encodeURI(query);
// "C++%20tutorial%20&%20reference"
// Note: + is NOT encoded! & is NOT encoded!

// encodeURIComponent: encodes EVERYTHING for a query parameter
encodeURIComponent(query);
// "C%2B%2B%20tutorial%20%26%20reference"
// Everything is encoded — safe for query parameters

The difference on Stack Overflow has been viewed over 1.2 million times. The top answer (4,500+ upvotes) says: "Use encodeURIComponent() for query parameters. Always."

// Correct pattern for building URLs
function buildSearchUrl(base, query, page = 1) {
  const params = new URLSearchParams({
    q: query,
    page: page.toString()
  });
  return `${base}?${params.toString()}`;
}

buildSearchUrl("/api/search", "C++ & JavaScript", 1);
// "/api/search?q=C%2B%2B+%26+JavaScript&page=1"
// Note: URLSearchParams encodes spaces as + (application/x-www-form-urlencoded)

Python: quote() vs quote_plus()

Python adds another wrinkle — two functions that differ in space encoding:

from urllib.parse import quote, quote_plus, urlencode

text = "C++ tutorial & reference"

# quote(): spaces as %20
quote(text)
# 'C%2B%2B%20tutorial%20%26%20reference'

# quote_plus(): spaces as + (form-encoded)
quote_plus(text)
# 'C%2B%2B+tutorial+%26+reference'

# urlencode(): handles multiple params
params = {"q": "C++", "page": 1, "lang": "en"}
urlencode(params)
# 'q=C%2B%2B&page=1&lang=en'

On Stack Overflow, the question about quote vs quote_plus has 45,000 views. The rule: use quote_plus for form data (space → +) and quote for path segments (space → %20).

# The bug I introduced:
from urllib.parse import quote

# WRONG: Using quote for path segments is correct,
# but using quote for query parameters breaks if the path has special chars
def build_api_url(base, query):
    return f"{base}?query={quote(query)}"
    # Spaces become %20, which is fine
    # But + stays as + which may be decoded as space on the server

# RIGHT: Use quote_plus for query parameters
from urllib.parse import urlencode

def build_api_url(base, query):
    return f"{base}?{urlencode({'query': query})}"

Go: url.Values Is Your Friend

Go makes URL encoding explicit:

import "net/url"

func buildSearchURL(base, query string, page int) string {
    params := url.Values{}
    params.Add("q", query)
    params.Add("page", strconv.Itoa(page))

    result := base + "?" + params.Encode()
    // params.Encode() handles all encoding
    // Spaces become + (form-encoded)
    return result
}

Go also provides QueryEscape and PathEscape for individual components:

import "net/url"

// QueryEscape: for query parameters
safeQuery := url.QueryEscape("C++ & Go")
// "C%2B%2B+%26+Go"

// PathEscape: for path segments
safePath := url.PathEscape("my file.txt")
// "my%20file.txt"

A Reddit thread on r/golang compared Go's URL encoding to JavaScript's. The consensus: Go's explicit separation between QueryEscape and PathEscape is clearer than JavaScript's two-function API.

Java: URLEncoder and UriComponents

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

String query = "C++ tutorial & reference";
String encoded = URLEncoder.encode(query, StandardCharsets.UTF_8);
// "C%2B%2B+tutorial+%26+reference"
// Spaces become + (following application/x-www-form-urlencoded)

Java's URLEncoder always uses + for spaces, which is correct for form data but wrong for path segments. For paths, use Spring's UriUtils:

import org.springframework.web.util.UriUtils;

String pathSegment = "my file.txt";
String encoded = UriUtils.encodePathSegment(pathSegment, "UTF-8");
// "my%20file.txt"  (correct for path segments)

Cross-Language Reference Table

LanguageQuery ParamsForm DataPath Segments
JavaScriptencodeURIComponentURLSearchParamsencodeURIComponent
Pythonquote_plusurlencodequote
Gourl.QueryEscapeurl.Values.Encodeurl.PathEscape
JavaURLEncoder.encodeURLEncoder.encodeUriUtils.encodePath
Rusturl::form_urlencoded::Serializersamepercent_encoding::percent_encode

The Space Encoding Trap

Different encoders encode spaces differently:

EncoderSpace Encoding
encodeURIComponent (JS)%20
URLSearchParams (JS)+
quote (Python)%20
quote_plus (Python)+
QueryEscape (Go)+
URLEncoder (Java)+

Most servers accept both %20 and + as spaces, but the HTTP specification says + represents space only in application/x-www-form-urlencoded content. In URL query strings, %20 is the correct encoding for spaces.

In practice, both work in most web servers. But if you are sending the value in a non-form context (like a JSON body or header), always use %20.

Related Searches

  • url encoding javascript encodeuricomponent
  • python urllib quote vs quote_plus
  • go url queryescape
  • java urlencoder encode
  • url encoding space percent 20 vs plus
  • url encoding cross language comparison
  • encodeuri vs encodeuricomponent
  • url encoding best practices
  • url encoding special characters
  • percent encoding reference

Frequently Asked Questions

What is the difference between encodeURI and encodeURIComponent in JavaScript?

encodeURI encodes the full URI but preserves characters that have special meaning in URIs (like :, /, ?, &). encodeURIComponent encodes everything, including those characters. Always use encodeURIComponent for encoding individual query parameter values.

Why do different languages encode spaces differently?

Historical reasons. The + for space comes from the application/x-www-form-urlencoded MIME type. The %20 encoding is from RFC 3986 (URI syntax). Both are valid in different contexts. Use + for form data and %20 for URL path segments.

Should I use quote or quote_plus in Python?

Use quote_plus for query parameter values (spaces become +). Use quote for path segments (spaces become %20). Use urlencode for encoding entire parameter dictionaries.

How do I handle URL encoding in Go?

Use url.Values for building query strings, url.QueryEscape for individual query parameters, and url.PathEscape for path segments. Go's API is the most explicit about the difference between query and path encoding.

Can incorrect URL encoding cause security vulnerabilities?

Yes. Failing to encode user input in URLs can lead to CRLF injection, open redirects, and server-side request forgery. Always encode user-supplied values before inserting them into URLs.

Final Thoughts

URL encoding seems like a solved problem, but the differences between languages cause real bugs. The key is knowing three things: (1) your language's function for query parameters vs path segments, (2) how it encodes spaces, and (3) never build URLs by string concatenation — use the language's URL builder API.