The right function to use, with a working example, for each major language and runtime. Plus the gotchas — like Java’s URLEncoder using + for spaces or PHP having two near-identical encoding functions with different behaviours.
Every major programming language has built-in URL encoding and decoding — but the function names, default behaviours, and gotchas differ. Below is the reference for each language, with the function to use for query-parameter values (the most common case).
// Encode
encodeURIComponent('Hello, World!')
// → 'Hello%2C%20World!'
// Decode
decodeURIComponent('Hello%2C%20World!')
// → 'Hello, World!'
// Building query strings — preferred
const params = new URLSearchParams();
params.append('q', 'Hello, World!');
params.toString(); // → 'q=Hello%2C+World%21'
Gotcha: encodeURI() exists too, but encodes much less — only spaces and a few other characters. Use encodeURIComponent() for values you’re injecting into URLs. Use URLSearchParams for building query strings.
from urllib.parse import quote, unquote, urlencode
# Encode a single value
quote('Hello, World!')
# → 'Hello%2C%20World%21'
# Decode
unquote('Hello%2C%20World%21')
# → 'Hello, World!'
# Build a query string from a dict
urlencode({'q': 'Hello, World!', 'lang': 'en'})
# → 'q=Hello%2C+World%21&lang=en'
Gotcha: quote() leaves / unencoded by default. Pass safe='' to encode everything: quote('a/b', safe='') → a%2Fb. For form encoding (space → +), use quote_plus().
// Encode (RFC 3986 compliant — what you usually want)
rawurlencode('Hello, World!');
// → 'Hello%2C%20World%21'
// Encode (form-encoded variant — space becomes +)
urlencode('Hello, World!');
// → 'Hello%2C+World%21'
// Decode
rawurldecode('Hello%2C%20World%21');
// → 'Hello, World!'
// Build a query string
http_build_query(['q' => 'Hello, World!', 'lang' => 'en']);
// → 'q=Hello%2C+World%21&lang=en'
Gotcha: PHP has both urlencode and rawurlencode. The non-raw version uses + for spaces (legacy form-encoded). Use rawurlencode if you want standard RFC 3986 behaviour.
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
// Encode
URLEncoder.encode("Hello, World!", StandardCharsets.UTF_8);
// → "Hello%2C+World%21"
// Decode
URLDecoder.decode("Hello%2C+World%21", StandardCharsets.UTF_8);
// → "Hello, World!"
Gotcha: Java’s URLEncoder uses form-encoding (space → +), not the RFC 3986 path-component encoding. If you need RFC 3986, replace + with %20 in the output: encoded.replace("+", "%20"). Or use the URI class for full URL construction.
import "net/url"
// Encode a query value
url.QueryEscape("Hello, World!")
// → "Hello%2C+World%21"
// Encode a path segment (no + substitution)
url.PathEscape("Hello, World!")
// → "Hello%2C%20World%21"
// Decode
url.QueryUnescape("Hello%2C+World%21")
// → "Hello, World!", nil
// Build a query string
v := url.Values{}
v.Set("q", "Hello, World!")
v.Encode()
// → "q=Hello%2C+World%21"
Gotcha: Go gives you separate functions for query values (QueryEscape, +-for-space) and path segments (PathEscape, %20-for-space). Pick the right one for context.
using System;
// Encode (RFC 3986)
Uri.EscapeDataString("Hello, World!")
// → "Hello%2C%20World%21"
// Decode
Uri.UnescapeDataString("Hello%2C%20World%21")
// → "Hello, World!"
// Older legacy approach (form-encoded)
System.Web.HttpUtility.UrlEncode("Hello, World!")
// → "Hello%2c+World!"
Gotcha: Prefer Uri.EscapeDataString over the older HttpUtility.UrlEncode for new code — it’s RFC-3986 compliant and doesn’t require referencing System.Web.
require 'uri'
require 'cgi'
# Encode (RFC 3986 — what you want for URLs)
URI.encode_www_form_component('Hello, World!')
# → 'Hello%2C+World%21'
# Decode
URI.decode_www_form_component('Hello%2C+World%21')
# → 'Hello, World!'
# Build query string
URI.encode_www_form(q: 'Hello, World!', lang: 'en')
# → 'q=Hello%2C+World%21&lang=en'
use urlencoding::{encode, decode};
// Encode
let encoded = encode("Hello, World!");
// → "Hello%2C%20World%21"
// Decode
let decoded = decode("Hello%2C%20World%21").unwrap();
// → "Hello, World!"
Gotcha: Requires the urlencoding crate. The standard library has std::ascii helpers but no batteries-included URL encoding.
# Encode using jq (clean)
echo -n "Hello, World!" | jq -sRr @uri
# → Hello%2C%20World%21
# Encode using python
python3 -c "import urllib.parse; print(urllib.parse.quote('Hello, World!'))"
# Encode using curl
curl --data-urlencode "q=Hello, World!" -G http://example.com/search
-- PostgreSQL
SELECT replace(replace(replace(text, '%', '%25'), ' ', '%20'), '&', '%26');
-- MySQL/MariaDB — no built-in URL encode; use the application layer.
-- SQL Server
SELECT REPLACE(REPLACE(text, ' ', '%20'), '&', '%26');
Recommendation: don’t URL-encode in SQL. Handle encoding in the application layer where the standard library is correct and complete.
| Language & function | Space becomes | Style |
|---|---|---|
JS encodeURIComponent | %20 | RFC 3986 |
JS URLSearchParams | + | Form-encoded |
Python quote | %20 | RFC 3986 |
Python quote_plus | + | Form-encoded |
PHP rawurlencode | %20 | RFC 3986 |
PHP urlencode | + | Form-encoded |
Java URLEncoder | + | Form-encoded |
Go QueryEscape | + | Form-encoded |
Go PathEscape | %20 | RFC 3986 |
C# EscapeDataString | %20 | RFC 3986 |
The split is consistent: query-encoding functions use + for spaces (legacy form convention), path-encoding functions use %20 (strict RFC 3986). Both are valid URL encodings — pick the variant your destination expects.
Modern JavaScript (URLSearchParams + URL constructor), Python (urllib.parse), and Go (net/url) all have excellent built-ins. Java and PHP have historical quirks — function names and default space-handling vary. For new code, prefer the high-level builders (URLSearchParams, urlencode, url.Values) over manually concatenating encoded strings.
Java's URLEncoder follows the form-encoded standard (application/x-www-form-urlencoded), which uses + for spaces. This is intended for query strings, where browsers also use +. If you need RFC 3986 path encoding instead, replace + with %20 in the output: encoded.replace("+", "%20").
Use jq: echo -n 'your text' | jq -sRr @uri. Or python: python3 -c "import urllib.parse; print(urllib.parse.quote('your text'))". Both produce RFC-3986-compliant output (%20 for spaces).
Generally no. Handle URL encoding in the application layer where the standard library is correct and complete. SQL string functions can encode the obvious characters but miss edge cases like UTF-8 multibyte sequences.
Use [System.Web.HttpUtility]::UrlEncode('your text') (requires loading System.Web) or [uri]::EscapeDataString('your text') for the modern RFC-3986 version. The latter is preferred for new scripts.