ToolzYard

Fast, practical, browser-based developer tools

Encoding Tool • Free Online • No Signup

Unicode Converter Online

Convert normal text into Unicode escape sequences and decode escaped Unicode back into readable text instantly. This browser-based Unicode converter is useful for debugging, encoding tests, APIs, source code, and text transformation workflows.

Ready to convert Unicode text.
Fast • Free • Browser-Based

Convert text to Unicode escapes and decode it back instantly

Unicode escapes are common in programming, APIs, configuration files, and data transport. This tool helps you quickly inspect, encode, and decode Unicode values without writing extra scripts or doing manual conversions.

✅ Text to Unicode
✅ Unicode to text
✅ Copy output
✅ Browser-based

Your text stays in the browser

This Unicode converter is designed to work directly in your browser during normal use. That makes it useful for quick local text transformations, debugging, and encoding checks.

For more details about site usage and analytics, read our Privacy Policy.

How to use this Unicode Converter

Paste or type text into the input box, then choose whether you want to encode it into Unicode escape sequences or decode escaped Unicode back into readable text.

  1. Enter text or Unicode escape sequences into the input box.
  2. Click Text to Unicode to encode text.
  3. Click Unicode to Text to decode Unicode escapes.
  4. Copy or download the output if needed.

Example conversion

Input: Hello
Output: \u0048\u0065\u006C\u006C\u006F

Common use cases

  • Debugging encoded strings
  • API payload inspection
  • Source code preparation
  • Unicode escape decoding
  • Text transformation workflows

Code point, code unit, and grapheme cluster

Almost every Unicode bug comes from blurring three different things that all get loosely called "a character." A code point is a Unicode scalar value — the abstract item the standard assigns, such as U+0041 for A or U+1F600 for 😀. A code unit is the fixed-size piece the chosen encoding stores data in: UTF-16 uses 16-bit units, UTF-8 uses 8-bit bytes. A grapheme cluster is what a human perceives as one character, which may be built from several code points — a base letter plus combining marks, or an emoji assembled from several scalars joined together.

These three rarely line up. One grapheme can be several code points, and one code point can be several code units. Keeping them distinct is what lets you predict why a length looks "wrong," why a slice cuts a character in half, or why two strings that look identical fail an equality check.

Why "😀".length is 2 in JavaScript

JavaScript's String.length counts UTF-16 code units, not characters and not code points. The grinning-face emoji sits at U+1F600, above U+FFFF, in what Unicode calls the supplementary (or astral) planes. Anything above U+FFFF cannot fit in a single 16-bit unit, so UTF-16 stores it as two units — a surrogate pair — and length dutifully reports 2.

If you iterate the string in a way that walks code points instead — a for...of loop, the spread [...str], or Array.from(str) — the emoji counts as one. That is why [..."😀"].length is 1 while "😀".length is 2. Neither, though, matches what a user counts as characters once combining marks and joined emoji enter the picture; for that you need grapheme segmentation via Intl.Segmenter with granularity 'grapheme'.

Surrogate pairs, and why slicing breaks emoji

Code points from U+10000 to U+10FFFF are encoded in UTF-16 as two special units: a high surrogate in the range U+D800–U+DBFF followed by a low surrogate in U+DC00–U+DFFF. Neither half is a valid character on its own; they only mean something as a pair.

This is exactly why naive string handling mangles emoji. Indexing or slicing by code-unit position — str[i], or a slice() that lands on an odd boundary — can cut a surrogate pair down the middle, leaving a lone surrogate that is invalid and renders as the replacement character (�). Truncating a user's text to "the first 20 characters" with a raw index is the canonical way to produce a trailing �. Splitting on code points (or graphemes) instead keeps every character whole.

NFC vs NFD: why identical-looking text compares unequal

The letter é has two legitimate Unicode spellings. It can be the single precomposed code point U+00E9 (normalization form NFC), or it can be a plain e followed by U+0301, the combining acute accent (form NFD). On screen they are indistinguishable, but they are different sequences of code units, so a naive === returns false and even .length differs — 1 versus 2.

This is a real, recurring production trap. Apple's HFS+ and APFS filesystems have historically stored filenames in NFD, while most other systems and web content use NFC, so text copied between them can silently fail equality checks, searches, and de-duplication. The fix is to normalize before you compare, store, hash, or generate a slug: call str.normalize('NFC') on both sides first so the same visible text is guaranteed to be the same bytes.

UTF-8 is variable-width: four numbers for one string

UTF-8 encodes each code point in one to four bytes. ASCII characters take 1 byte; most Latin, Greek, and Cyrillic letters take 2; the rest of the Basic Multilingual Plane, including most CJK characters, takes 3; and emoji and other astral characters take 4. That variability is UTF-8's great strength — plain ASCII stays one byte — but it means byte length is not something you can eyeball from the text.

Put it together and a single string has up to four different "lengths": its UTF-8 byte count, its UTF-16 code-unit count (JavaScript's .length), its code-point count, and the number of grapheme clusters a human would count. For "a😀" those are 5 bytes, 3 code units, 2 code points, and 2 graphemes. Whenever a length limit, a progress bar, or a database column feels off by a bit, it is almost always because two of these four numbers were assumed to be equal.

Frequently Asked Questions

Why does "😀".length return 2 in JavaScript?

Because String.length counts UTF-16 code units, not characters. The emoji is above U+FFFF, so UTF-16 stores it as a surrogate pair — two 16-bit units — and reports a length of 2. Walk the string with for...of, [...str], or Array.from(str) to count code points, where it is 1.

What is the difference between a code point and a grapheme cluster?

A code point is a single Unicode scalar value, like U+0301 (a combining accent). A grapheme cluster is what a person sees as one character, which can be several code points combined — e plus U+0301 renders as one é, and many emoji are several joined code points. Users count graphemes; code rarely does by default.

Why do two identical-looking strings compare as unequal?

Almost always Unicode normalization. The same visible text can be encoded as precomposed (NFC) or decomposed (NFD) code points — é as U+00E9 versus e + U+0301 — which are different byte sequences. Call str.normalize('NFC') on both sides before comparing, hashing, or de-duplicating.

How do I count characters the way a human sees them?

Use grapheme segmentation, not .length. In modern JavaScript, Intl.Segmenter with granularity 'grapheme' walks the string by user-perceived characters, so a flag or a combined emoji counts as one. Code-unit and code-point counts will both over-count such cases.

How many bytes does one character take in UTF-8?

One to four, depending on the character. ASCII is 1 byte, most Latin, Greek, and Cyrillic letters are 2, most of the Basic Multilingual Plane including common CJK is 3, and emoji and other astral characters are 4. That is why a string's byte length, code-unit count, and code-point count are often three different numbers.

What is a surrogate pair, and why does slicing break emoji?

Characters above U+FFFF are stored in UTF-16 as two units — a high surrogate (U+D800–U+DBFF) and a low surrogate (U+DC00–U+DFFF) — that are only valid together. Slicing or indexing by code-unit position can land between them, leaving a lone surrogate that is invalid and shows as �. Split by code point or grapheme to keep characters intact.