encodeURI vs encodeURIComponent: When to Use Each
JavaScript provides two built-in URL encoding functions: encodeURI and encodeURIComponent. Confusing them leads to truncated query parameters, broken route parsing, or HTTP 400 Bad Request errors. This article breaks down RFC 3986 reserved characters and proper usage scenarios.
1. Problem: reserved character encoding differences
RFC 3986 defines reserved characters (e.g., :, /, ?, #, [, ], @, !, $, &, ', (, ), *, +, ,, ;, =). encodeURI encodes full URIs while preserving structural delimiters (https://, ?); encodeURIComponent encodes individual query keys or values, percent-encoding reserved delimiters (%XX).
2. Minimal reproduction: misusing encodeURI on query parameter values
When a parameter value contains & or = (such as a redirect target URL), using encodeURI leaves & unescaped, causing server parsers to misinterpret it as multiple query parameters.
const redirectTarget = "https://site.com/login?ref=123&lang=cn";
/* Wrong: using encodeURI on a query parameter value leaves & unescaped */
const wrongUrl = "https://api.example.com/redirect?target=" + encodeURI(redirectTarget);
// Result retains raw &: https://api.example.com/redirect?target=https://site.com/login?ref=123&lang=cn
/* Correct: using encodeURIComponent on the parameter value */
const correctUrl = "https://api.example.com/redirect?target=" + encodeURIComponent(redirectTarget);
// Result percent-encodes reserved characters: https://api.example.com/redirect?target=https%3A%2F%2Fsite.com%2Flogin%3Fref%3D123%26lang%3Dcn3. Root cause: URI structural parsing and character sets
URIs consist of Scheme, Authority, Path, Query, and Fragment. encodeURI assumes full URI inputs and preserves URI syntax delimiters. encodeURIComponent assumes component fragment inputs, percent-encoding any character that could disrupt URI syntax.
4. Recommendation: layer-by-layer encoding architecture
1. Full URL structure: use encodeURI or native new URL(). 2. Query parameter key/value: use encodeURIComponent or URLSearchParams. 3. Dynamic path segments: encode segments individually with encodeURIComponent before joining with /.
5. Complete code: layered safe URL builder function
This TypeScript function applies proper encoding strategies to full URL frameworks, path segments, and query parameters separately.
function safeBuildUrl(baseUrl: string, pathSegment: string, queryParams: Record<string, string>): string {
const encodedPath = pathSegment.split("/").map(encodeURIComponent).join("/");
const queryParts: string[] = [];
for (const [key, val] of Object.entries(queryParams)) {
const safeKey = encodeURIComponent(key);
const safeVal = encodeURIComponent(val);
queryParts.push(safeKey + "=" + safeVal);
}
const queryString = queryParts.join("&");
const cleanBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
const fullRawUrl = cleanBase + "/" + encodedPath + "?" + queryString;
return encodeURI(fullRawUrl);
}
console.log(safeBuildUrl("https://api.example.com", "v1/user info", { search: "a&b=c", redirect: "https://site.com?id=1" }));
// Space in path becomes %20, & and = in query are safely percent-encoded6. Incorrect approaches
Calling encodeURIComponent directly on a full URL string containing ?key=value (destroying https:// and ?). Using encodeURI on query parameter values (leaking delimiters).
7. Boundaries: single quotes, tildes, and Unicode characters
Neither encodeURI nor encodeURIComponent encodes ', !, (, ), *, or ~. Replace single quotes and parentheses manually if servers strictly validate RFC 3986.
8. Verification
Assert that new URL(url).searchParams.get(key) restores the original value. Cover &, =, ?, /, #, %, spaces, and Unicode, then verify a real client/server round trip uses the same encoding rules.
9. FAQ
Which has better performance, encodeURI or encodeURIComponent? Performance is identical; the difference lies in character set definitions.
Why prefer URLSearchParams over manual encodeURIComponent? URLSearchParams handles key/value encoding and space/+ rules automatically.
When should escape() be used? Never; escape() is a deprecated API that fails on Unicode characters.
10. Summary
Follow clear boundaries: use encodeURI or new URL() for full URL frameworks, and encodeURIComponent or URLSearchParams for individual query components.
Sources and further reading
Specifications and references for checking the article’s technical details.
- URL Living Standard
WHATWG
Related articles
URL Query Encoding: Plus Signs, Spaces and %2B
Analyze how traditional application/x-www-form-urlencoded specs convert spaces to + causing plus signs to parse as spaces, detailing %20 vs %2B.
Best practicesXSS Defense: URL vs HTML Encoding
Analyze HTML text, attribute, JS, and URL sink differences (<a href>), clarifying why URL encoding cannot replace XSS defense with multi-layered rules.
PitfallsModern JavaScript Minification: Syntax Compatibility
Distinguish Parser, Transpiler (Babel/SWC), Minifier (Terser/esbuild), and Runtime configurations, fixing Parse Errors for optional chaining ?. and top-level await.
Keep exploring
Use the related browser tool to test the workflow with your own sample data.
Open related tool