TidyURLs
Go to Tools
BLOG
The TidyURLsJournal

Practical guides, tutorials, and insights about URLs, SEO, web development, and online marketing. Learn, troubleshoot, and get the most of the web.

Back to the Journal
TidyURLs Journal

How to Encode Unicode Characters in a URL

Practical insights, clear explanations, and useful ideas for understanding the web.

October 28, 20266 min read5 topics
How to Encode Unicode Characters in a URL
Explore the details
#URL encoding#Unicode#JavaScript#URLSearchParams#Internationalization
October 28, 20266 min read

URLs often contain names, search terms, and other text written with accented or non-Latin characters. To make a URL value work reliably, encode the value in the context where it will appear—without encoding the URL’s structural characters.

This tutorial shows how percent-encoding represents Unicode text, how to build query strings safely in JavaScript, and how to verify the result in a browser.

Key Takeaways

  • Percent-encoding represents bytes, not Unicode characters directly. Web URLs typically percent-encode the UTF-8 bytes of characters that cannot appear literally in that URL component.
  • Encode a query value, path segment, or other component—not the complete URL.
  • For query parameters in JavaScript, URLSearchParams handles delimiters and spaces for you. Its form-style serialization represents spaces as +.
  • encodeURIComponent() is useful for an individual component and represents spaces as %20; it is not a substitute for building a URL with a URL API.

What percent-encoding does

A Unicode character may be represented by one or more bytes when encoded as UTF-8. Percent-encoding writes each byte as % followed by two hexadecimal digits. For example, é is UTF-8 bytes C3 A9, so its percent-encoded representation is %C3%A9.

An internationalized resource identifier (IRI) can contain a wider range of Unicode characters than a URI. When a browser serializes a URL, characters in a component that cannot be used literally are represented in a URL-compatible form, commonly by percent-encoding their UTF-8 bytes. A browser may display readable Unicode in an address bar while the URL’s serialized form contains percent escapes.

Examples of UTF-8 percent-encoding include:

TextUTF-8 bytesPercent-encoded form
éC3 A9%C3%A9
MünchenM C3 BC n c h e nM%C3%BCnchen
東京E6 9D B1 E4 BA AC%E6%9D%B1%E4%BA%AC

The encoded form is transport representation, not a change to the underlying text. A correctly processed parameter can be decoded back to the original Unicode value.

Encode a query value, not the whole URL

A URL contains structural characters such as :, /, ?, &, and =. Those characters separate the scheme, host, path, and query parameters. Encoding the entire URL can turn those separators into data and make the link unusable.

For example, do not encode this complete URL as one value:

https://example.com/search?q=José

Instead, preserve the URL structure and encode the value of q. In JavaScript, use URL and URLSearchParams:

const url = new URL("https://example.com/search");
url.searchParams.set("q", "José & Zoë");

console.log(url.href);
// https://example.com/search?q=Jos%C3%A9+%26+Zo%C3%AB

The & in the search term becomes %26, so it cannot be mistaken for a separator between query parameters. The accented characters are represented using their UTF-8 bytes. The URL’s actual query delimiters remain intact.

To read the value back in browser JavaScript:

const url = new URL("https://example.com/search?q=Jos%C3%A9+%26+Zo%C3%AB");

console.log(url.searchParams.get("q"));
// José & Zoë

URLSearchParams applies form-style query serialization: spaces are written as +, and a literal plus sign in a value is encoded as %2B. This is appropriate for ordinary query parameters; use the serialization rules expected by the system consuming your URL.

Use encodeURIComponent() for an individual component

When you need to encode a single value yourself, encodeURIComponent() encodes characters that could otherwise interfere with a URI component:

const value = "München 東京 & tea + cake";
const encoded = encodeURIComponent(value);

console.log(encoded);
// M%C3%BCnchen%20%E6%9D%B1%E4%BA%AC%20%26%20tea%20%2B%20cake

This is useful when an API or a particular URL format requires %20 for spaces. It is not the same serialization as URLSearchParams, which uses + for spaces in query parameters.

For ordinary query construction, prefer the URL API rather than concatenating encoded values into a URL string. It reduces mistakes involving &, =, #, and other characters with meaning in a URL. If you do use encodeURIComponent(), apply it only to the component value—not to the URL around it.

Verify the resulting link in a browser

You can check both the serialized URL and the recovered value in a browser’s developer console. Open DevTools, select the Console, and run:

const url = new URL("https://example.com/search");
url.searchParams.set("q", "München 東京 & café");

console.log(url.href);
console.log(url.searchParams.get("q"));

The first result should be a URL with the Unicode text percent-encoded and the ampersand escaped as %26, similar to:

https://example.com/search?q=M%C3%BCnchen+%E6%9D%B1%E4%BA%AC+%26+caf%C3%A9

The second result should be the original value:

München 東京 & café

You can also open the generated url.href in a new tab and inspect the address bar. Browser display and serialization are not always identical, so use the URL API’s href value when checking the serialized form. A URL Encoder Decoder can help inspect a value, but it does not replace checking how the complete URL is constructed or how the receiving application parses it.

Common Mistakes

Encoding the complete URL

Applying encodeURIComponent() to https://example.com/search?q=José encodes structural characters along with the value. Build the URL first, then set or encode individual components.

Double encoding

Encoding an already encoded value changes the percent signs. For example, %C3%A9 becomes %25C3%25A9 if encoded again, because % itself becomes %25. Keep track of whether a value is raw text or already encoded, and encode it once at the boundary where it enters the URL.

Assuming spaces always use the same representation

URLSearchParams writes spaces as + in its query serialization. encodeURIComponent() writes them as %20. Both can appear in URLs, but a literal + in a form-style query value represents a space unless it is encoded as %2B. Choose the representation expected by the relevant URL format or receiving system.

Forgetting that delimiters can occur in values

An unescaped & in a query value may be interpreted as the start of another parameter. Likewise, # starts a fragment in a URL. Use a URL API or encode the individual value rather than inserting arbitrary text directly into the URL.

Treating an encoded display as proof of correct parsing

A URL can look percent-encoded and still be interpreted differently by a server, proxy, or application. Test the value at the receiving end when possible, especially when multiple systems parse or transform the query string.

Best Practices

  • Use new URL() and url.searchParams.set() to construct query parameters in browser JavaScript.
  • Keep URL structure separate from user-provided values; encode each value in its proper component context.
  • Know whether the consumer expects form-style query serialization (+ for spaces) or percent-encoded spaces (%20).
  • Verify both the serialized URL and the decoded value with a representative example containing non-Latin text and reserved characters such as & or +.
  • Avoid encoding a value repeatedly. Store or pass raw text where possible, then serialize it once when building the URL.

Conclusion

To encode Unicode characters in a URL, preserve the URL’s structure and serialize the relevant value in its component context. For JavaScript query strings, URLSearchParams is a practical default; use encodeURIComponent() when you specifically need to encode one component value. Check the generated URL and confirm that the original text can be recovered.

References