URL Encoding for International Characters Explained

May 28, 20266 min read

URLs and the ASCII Limitation

URLs were originally designed to carry only ASCII characters — letters, digits, and a limited set of symbols. RFC 3986 defines the allowed character set, and anything outside it must be percent-encoded.

This limitation becomes obvious when you work with international content. A Chinese character, an Arabic letter, or an accented Latin character cannot appear in a URL without encoding. The браузер (browser) handles this transparently most of the time, but understanding the mechanics helps you debug broken links and build correct URLs programmatically.

How UTF-8 Percent Encoding Works

The Two-Step Process

Encoding an international character for URLs involves two steps:

  1. Convert to UTF-8 bytes — Each Unicode character becomes 1 to 4 bytes
  2. Percent-encode each byte — Each byte becomes %XX where XX is the hexadecimal value
// Manual encoding example for the Chinese character 中
const char = '中';
const utf8Bytes = new TextEncoder().encode(char); // [0xE4, 0xB8, 0xAD]
const encoded = Array.from(utf8Bytes)
  .map(b => '%' + b.toString(16).toUpperCase().padStart(2, '0'))
  .join('');
// Result: %E4%B8%AD

Examples by Language

CharacterLanguageUTF-8 BytesEncoded URL
caféFrench63 61 66 C3 A9caf%C3%A9
ChineseE4 B8 AD%E4%B8%AD
مرحباArabicD9 85 D8 B1 D8 AD D8 A8 D8 A7%D9%85%D8%B1%D8%AD%D8%A8%D8%A7
MünchenGerman4D C3 BC 6E 63 68 65 6EM%C3%BCnchen
東京JapaneseE6 9D B1 E4 BA AC%E6%9D%B1%E4%BA%AC

Internationalized Domain Names (IDNs)

Domain names with international characters use a separate encoding called Punycode rather than percent-encoding. The browser displays the Unicode form but resolves the domain using its ASCII representation.

Unicode:    пример.рф
Punycode:   xn--e1afmkfd.xn--p1acf

This distinction matters: percent-encoding applies to the path and query portions of a URL, while Punycode applies to the hostname. Mixing them up causes resolution failures.

Query Parameters with International Text

When sending international text in query parameters, always encode the value, not the entire URL. The = and & delimiters must remain unencoded:

// Correct: encode only the value
const query = 'q=' + encodeURIComponent('München');
// "q=M%C3%BCnchen"

// Wrong: encoding the entire URL breaks the structure
const broken = encodeURI('https://example.com/search?q=München');
// This works but is fragile — encodeURI won't encode ?, #, &, =

encodeURIComponent vs encodeURI

FunctionEncodesLeaves Unencoded
encodeURIInternational chars, spaces: / ? # [ ] @ ! $ & ' ( ) * + , ; =
encodeURIComponentInternational chars, spaces, and all special chars~ ! ' ( ) *

Use encodeURIComponent for query parameter values. Use encodeURI only when you need to encode a full URL while preserving its structure.

Server-Side Decoding

Most web frameworks automatically decode percent-encoded URL components. In Node.js:

// Express automatically decodes route parameters
app.get('/search/:query', (req, res) => {
  const decoded = req.params.query; // Already decoded from %C3%BC to ü
});

// Manual decoding when needed
const decoded = decodeURIComponent('M%C3%BCnchen'); // "München"

Be cautious with double-encoding. If you encode a value that is already encoded, the % signs themselves get encoded, producing broken output:

// Double encoding problem
const once = encodeURIComponent('café');  // "caf%C3%A9"
const twice = encodeURIComponent(once);    // "caf%25C3%25A9" — broken

SEO Considerations for International URLs

Google recommends using UTF-8 encoded URLs for non-ASCII characters rather than converting to ASCII approximations. The search engine displays the decoded Unicode characters in results, making the URL more readable for users.

Preferred: https://example.com/caf%C3%A9
Avoid:     https://example.com/cafe

Slug-based URLs often transliterate international characters to ASCII for simplicity. This approach works but sacrifices readability for non-Latin scripts.

Key Takeaways

  • URL encoding for international characters converts Unicode to UTF-8 bytes, then percent-encodes each byte
  • Domain names use Punycode, not percent-encoding — the two systems are separate
  • Use encodeURIComponent for query values, encodeURI for full URLs
  • Double-encoding breaks URLs — decode before re-encoding
  • Google handles UTF-8 encoded URLs well and displays Unicode in search results

Try It Yourself

Need to encode international characters in URLs? Use our free URL Encoder to percent-encode any text instantly. Supports Unicode, Chinese, Arabic, and all international character sets — all processing happens locally in your browser.

Try the URL Encoder →