Question
JavaScript URL Encoding: escape() vs encodeURI() vs encodeURIComponent()
Question
When encoding a query string to send to a web server in JavaScript, when should you use escape() instead of encodeURI() or encodeURIComponent()?
For example:
escape("% +&=");
Or:
encodeURI("http://www.google.com?var1=value1&var2=value2");
encodeURIComponent("var1=value1&var2=value2");
Which function is appropriate for a complete URL, a query-string value, or individual query parameters?
Short Answer
JavaScript provides encodeURI() and encodeURIComponent() for different parts of a URL. In modern code, do not use escape() because it is deprecated and does not follow modern URL encoding rules. Use encodeURI() for an already structured complete URL, and use encodeURIComponent() for individual parameter names or values. For most query strings, URLSearchParams is the clearest and safest choice.
Concept
A URL contains both data and syntax.
In this URL:
https://example.com/search?q=red shoes&page=2
Characters such as :, /, ?, &, and = have structural meanings:
?begins the query string.&separates parameters.=separates a parameter name from its value.
If user data itself contains these characters, it must be encoded so it is treated as data rather than URL syntax.
encodeURI() is designed for a complete URI/URL. It leaves URL separator characters intact because they are needed for the URL to keep its structure.
encodeURIComponent() is designed for one URL component, such as a query parameter name or value. It encodes characters like &, =, /, and ?, preventing them from changing the URL structure.
Mental Model
Think of a URL as a form with labeled fields:
?q=...&page=...
The labels and dividers (?, &, =) are part of the form itself. They tell the server where each field starts and ends.
A user’s search text is the content written inside a field. If that content includes an ampersand, such as tea & coffee, it must be wrapped safely so the server does not mistake it for a new field.
encodeURI()protects a mostly finished address while preserving the address punctuation.encodeURIComponent()seals the contents of one field so its punctuation cannot escape.escape()is an obsolete sealing tool; leave it in old code only until it can be replaced.
Syntax and Examples
Use encodeURI() when you have a complete URL whose separators are already correct:
const url = "https://example.com/search?q=red shoes&page=2";
console.log(encodeURI(url));
// https://example.com/search?q=red%20shoes&page=2
Notice that ?, =, and & remain unchanged. They are URL syntax.
Use encodeURIComponent() for a single parameter name or value:
const query = "tea & coffee";
const url = "https://example.com/search?q=" + encodeURIComponent(query);
console.log(url);
// https://example.com/search?q=tea%20%26%20coffee
Here, the & in the search text becomes %26. The server can now recognize it as part of the q value rather than a parameter separator.
For several parameters, use URLSearchParams:
Step by Step Execution
Consider this code:
const term = "C++ & JavaScript";
const encodedTerm = encodeURIComponent(term);
const url = `https://api.example.com/search?q=${encodedTerm}&limit=10`;
console.log(url);
Step by step:
termcontains text supplied by a user:C++ & JavaScript.encodeURIComponent(term)converts characters that could affect URL parsing:- spaces become
%20 +becomes%2B&becomes%26
- spaces become
encodedTermisC%2B%2B%20%26%20JavaScript.- The template literal builds the final URL. Its
?,=, and&are intentionally left as URL separators. - The result is:
Real World Use Cases
- Search pages: Encode a search phrase before adding it to
?q=. - API requests: Encode filters such as a customer name, email address, or product category before including them in a GET request.
- Redirect links: Encode a destination URL when it is the value of another URL’s parameter, such as
?next=. - Sharing links: Build links containing selected filters, sort options, and pagination values.
- Client-side routing: Encode dynamic path or query values that may contain spaces, slashes, punctuation, or non-ASCII characters.
Example: a URL stored inside another URL must be encoded as a component:
const nextPage = "https://example.com/account?tab=billing";
const loginUrl = `https://example.com/login?next=${encodeURIComponent(nextPage)}`;
console.log(loginUrl);
// https://example.com/login?next=https%3A%2F%2Fexample.com%2Faccount%3Ftab%3Dbilling
Real Codebase Usage
In production code, developers usually avoid manually concatenating query strings when possible.
Build query strings with URL and URLSearchParams
const apiUrl = new URL("https://api.example.com/products");
apiUrl.search = new URLSearchParams({
category: "home & garden",
sort: "price ascending",
inStock: "true"
});
fetch(apiUrl);
This makes it clear which text is data and prevents missing or incorrectly placed separators.
Omit optional values with a guard
const params = new URLSearchParams();
if (searchTerm.trim() !== "") {
params.set("q", searchTerm);
}
if (page > 1) {
params.set("page", String(page));
}
Decode only data received from a URL
When reading a single encoded component manually, use :
Common Mistakes
Using escape() in new code
// Avoid: deprecated and not appropriate for modern URL encoding
const value = escape("café & tea");
Use encodeURIComponent() for a parameter value instead:
const value = encodeURIComponent("café & tea");
Encoding an entire query string with encodeURIComponent()
// Incorrect when this is intended to be a complete query string
encodeURIComponent("q=tea&sort=price");
// q%3Dtea%26sort%3Dprice
The separators were encoded, so this is now one data value, not two parameters. Encode the values individually, or use URLSearchParams.
const query = new URLSearchParams({ q: "tea", sort: "price" }).toString();
// q=tea&sort=price
Comparisons
| Tool | Intended input | Keeps URL separators such as ?, &, =? | Modern recommendation |
|---|---|---|---|
escape() | Legacy JavaScript text escaping | Not reliably suitable for URL rules | Do not use |
encodeURI() | A complete URI/URL | Yes | Use only when encoding an already structured full URL |
encodeURIComponent() | One URI component: parameter name, value, path segment | No | Use for individual dynamic values |
URLSearchParams | A collection of query parameter names and values | Adds separators correctly |
Cheat Sheet
// Deprecated: do not use for URL encoding
escape(text);
// Complete URL with deliberate URL syntax
encodeURI("https://example.com/search?q=red shoes&page=2");
// One dynamic query parameter value
encodeURIComponent("tea & coffee");
// Recommended way to create a query string
const params = new URLSearchParams({
q: "tea & coffee",
page: "2"
});
const url = `https://example.com/search?${params}`;
Rules:
- Use
encodeURIComponent()for each dynamic parameter name or value. - Use
encodeURI()only for a complete URL that already has correct separators. - Do not use
escape()in new code. - Do not run
encodeURIComponent()on an entirea=value&b=valuequery string. - Avoid encoding the same value more than once.
- Prefer
URLandURLSearchParamsfor reliable URL construction. URLSearchParamsrepresents spaces as in its query-string output; this is expected.
FAQ
Should I ever use escape() instead of encodeURIComponent()?
No. escape() is deprecated. Use encodeURIComponent() for individual URL data values, or use URLSearchParams for query strings.
When should I use encodeURI()?
Use it when you have a complete URI or URL and want to encode characters such as spaces without encoding its structural characters like :, /, ?, &, and =.
Why does encodeURIComponent() encode & and =?
Those characters split query parameters. Encoding them ensures they remain part of one parameter name or value.
Can I pass a whole query string to encodeURIComponent()?
Not if you want the server to parse it as multiple parameters. It encodes = and &. Encode individual values instead, or use .
Mini Project
Description
Build a small function that creates a product-search API URL from user-provided filters. The project demonstrates why query values must be encoded independently and how URLSearchParams avoids manual URL encoding mistakes.
Goal
Create a valid search URL that supports optional search text, category, page number, and a boolean in-stock filter.
Requirements
Create a function named buildProductSearchUrl.
Accept query, category, page, and inStock as inputs.
Include q only when the query is not empty after trimming.
Include category only when it has a value.
Include page only when it is greater than 1.
Return a URL beginning with https://api.example.com/products.
Keep learning
Related questions
Abort Ajax Requests with jQuery jqXHR.abort()
Learn how to cancel an in-progress jQuery Ajax request with jqXHR.abort(), handle abort status safely, and avoid stale UI updates.
Access the Correct this Inside a JavaScript Callback
Learn why JavaScript this changes in callbacks and how to preserve an object context using bind, arrow functions, and event handler patterns.
Add Key-Value Pairs to JavaScript Objects
Learn how to add key-value pairs to JavaScript objects with dot and bracket notation, dynamic keys, examples, and common mistakes.