Free tool

Unicode converter

Convert text to Unicode code points, UTF-8 and UTF-16 bytes, or escapes for HTML, JavaScript, JSON, CSS, Python and URLs, and decode any of them back to text. Each character gets its own row with its name or category, and invisible or lookalike characters are flagged.

Free · no sign-up · runs in your browser, nothing is uploaded

😀 as Code points: U+1F600

Text
Code points

Code points appear here as you type.

Code points, UTF-8 and UTF-16

Unicode gives every character a number, its code point, written U+ and at least four hex digits. There are 1,114,112 of them, from U+0000 to U+10FFFF. Encodings decide how those numbers become bytes. Here are the same four characters in each:

CharacterCode pointUTF-8 bytesUTF-16 unitsUTF-32
AU+004141004100000041
éU+00E9C3 A900E9000000E9
€U+20ACE2 82 AC20AC000020AC
😀U+1F600F0 9F 98 80D83D DE000001F600

UTF-8 uses 1 to 4 bytes per character and is the same as ASCII for the first 128, which is why it is the default for the web, JSON and most files. UTF-16 uses one 16-bit unit for characters up to U+FFFF and two (a surrogate pair from the range D800-DFFF) for the rest. JavaScript, Java, C# and Windows store strings as UTF-16, which is where escapes like \uD83D\uDE00 for 😀 come from.

How UTF-8 encodes a code point

The first byte says how many bytes follow; each following byte starts with the bits 10 and carries 6 bits of the code point.

Code pointsBytes (x = bits of the code point)Count
U+0000 - U+007F0xxxxxxx1
U+0080 - U+07FF110xxxxx 10xxxxxx2
U+0800 - U+FFFF1110xxxx 10xxxxxx 10xxxxxx3
U+10000 - U+10FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx4

Example: é is U+00E9, binary 00011 101001. Into the 2-byte pattern that gives 11000011 10101001, or C3 A9. When that pair is read as Latin-1 or Windows-1252 instead of UTF-8, you see é, the classic mojibake. The bytes C0, C1 and F5-FF never appear in valid UTF-8, and surrogates (U+D800-DFFF) may not be encoded at all. The decoder above reports each of these with its byte position.

Unicode escapes by language

Whereé (U+00E9)😀 (U+1F600)
HTML / XMLé é é😀 😀
CSS\E9 (or \0000E9)\1F600
JavaScript (ES2015+)\u00E9 or \u{E9}\u{1F600}
JSON, Java, C#\u00E9\uD83D\uDE00
Python\u00e9 or \xe9\U0001F600
Rust, Swift\u{E9}\u{1F600}
URL%C3%A9%F0%9F%98%80

A CSS escape takes up to six hex digits and ends at the first character that is not hex. If the next character is a hex digit or a space, add a space after the escape: \E9 b. The converter does this for you. The Unicode → text mode reads all of these, mixed into ordinary text, and joins surrogate pairs.

// JavaScript
'😀'.codePointAt(0).toString(16)        // '1f600'
String.fromCodePoint(0x1F600)            // '😀'
[...new TextEncoder().encode('é')]       // [195, 169]

# Python
hex(ord('😀'))                           # '0x1f600'
'é'.encode('utf-8')                       # b'\xc3\xa9'
b'\xf0\x9f\x98\x80'.decode('utf-8')         # '😀'

# Terminal
printf '😀' | xxd -p                      # f09f9880
printf '\xf0\x9f\x98\x80\n'              # 😀

Invisible, unusual and lookalike characters

Some characters take no space on screen but still change the string, so ===, searches and database lookups fail for no visible reason. The usual suspects:

Code pointNameWhere it comes from
U+200BZERO WIDTH SPACECopied from web pages, chat apps and docs
U+FEFFZERO WIDTH NO-BREAK SPACE (BOM)Start of files saved by some Windows editors (EF BB BF in UTF-8)
U+00A0NO-BREAK SPACE  in HTML, Word, macOS Option+Space
U+00ADSOFT HYPHENHyphenation in copied text
U+200E, U+200FLEFT-TO-RIGHT / RIGHT-TO-LEFT MARKMixed-direction text
U+202A-202E, U+2066-2069Bidirectional embeddings, overrides and isolatesRight-to-left text, and the Trojan Source attack
U+2028, U+2029LINE / PARAGRAPH SEPARATORCopied text; break old JavaScript parsers

Bidirectional overrides can make source code display in a different order from how the compiler reads it (CVE-2021-42574, "Trojan Source"). Lookalikes are the other trap: pаypal.com with a Cyrillic а is a different domain. Unicode's UTS #39 lists thousands of confusable pairs; the tool flags the common Cyrillic and Greek ones plus styled letters (fullwidth, bold or script math letters) that NFKC normalization turns back into ASCII.

Counting characters: graphemes, code points, units, bytes

"How long is this string" has four answers, and each language picks a different default:

CountFor "👋🏽 é"How to get it
Characters you see (grapheme clusters)3Intl.Segmenter in JS, the regex module's \X in Python
Code points4[...s].length in JS, len(s) in Python, utf8.RuneCountInString in Go
UTF-16 units6s.length in JavaScript, Java and C#
UTF-8 bytes11Buffer.byteLength(s) in Node, len(s.encode()) in Python, len(s) in Go

Database column limits, API size limits and token counts each use one of these, so check which before you truncate text. The same letter can also be stored two ways: é as one code point (U+00E9, NFC) or as e plus a combining accent (U+0065 U+0301, NFD). They look identical but are not equal until you normalize with s.normalize('NFC'); the converter tells you when text is not NFC.

Related tools: escape strings for JSON, HTML, SQL and shell, decode URLs, and Base64. Working on app security? See security tools on DevHunt.

FAQ

How do I convert text to Unicode code points?+

Paste the text above with "Text → Unicode" selected. Every character is listed with its code point (U+00E9 for é), and the output box gives the whole text as code points, UTF-8 bytes, UTF-16 units or escapes. In JavaScript, [...text].map(c => c.codePointAt(0).toString(16)) does the same; in Python, [hex(ord(c)) for c in text].

How do I decode UTF-8 bytes to text?+

Switch to "Unicode → text" and paste the bytes in hex: F0 9F 98 80, \xF0\x9F\x98\x80 or %F0%9F%98%80 all work. Invalid bytes are reported with their position and replaced by U+FFFD. In code: new TextDecoder().decode(new Uint8Array(bytes)) in JavaScript, bytes.decode("utf-8") in Python.

What is the difference between Unicode and UTF-8?+

Unicode is the list of characters, each with a number called a code point (U+0000 to U+10FFFF). UTF-8 is one way to store those numbers as bytes: 1 byte for ASCII, 2 for most European and Middle Eastern letters, 3 for the rest of the Basic Multilingual Plane (including most Chinese, Japanese and Korean), and 4 for emoji and other characters above U+FFFF. UTF-16 and UTF-32 are other ways to store the same code points.

Why is an emoji's length 2 in JavaScript?+

JavaScript strings count UTF-16 code units. Characters above U+FFFF, like 😀 (U+1F600), need two units, a surrogate pair (D83D DE00), so "😀".length is 2. [..."😀"].length counts code points (1). An emoji with a skin tone or a ZWJ sequence like 👨‍💻 is several code points but one visible character; Intl.Segmenter counts those.

How do I find hidden or invisible characters in text?+

Paste the text above. Zero width spaces, byte order marks, bidirectional controls, soft hyphens and other invisible characters are flagged and highlighted in the table, along with non-breaking and other unusual spaces. The "Remove invisible and fix spaces" button cleans them out while keeping the joiners inside emoji.

What are lookalike (homoglyph) characters?+

Characters from different scripts that look the same, like Latin a (U+0061) and Cyrillic а (U+0430). They are used in phishing domains and to sneak words past filters. The tool flags common Cyrillic and Greek lookalikes and styled letters such as fullwidth or bold math letters, and can replace them with plain ASCII.

How do I write a Unicode character in HTML, CSS, JavaScript or Python?+

For é (U+00E9): é or é in HTML, \E9 in CSS, \u00E9 in JavaScript and JSON, \u00e9 in Python. For 😀 (U+1F600): 😀, \1F600, \u{1F600} (or \uD83D\uDE00 in JSON and Java) and \U0001F600. Pick a format in the output box to convert a whole string.

Sources: The Unicode Standard, ch. 3 (UTF-8, UTF-16) · RFC 3629 (UTF-8) · RFC 2781 (UTF-16) · UAX #15 (normalization) · UTS #39 (security, confusables) · UAX #29 (grapheme clusters) · Trojan Source (CVE-2021-42574) · MDN: String.prototype.codePointAt() · MDN: Intl.Segmenter · CSS Syntax: escapes · Python: string literals. Checked 2026-10-30.