UTF-16 to UTF-8 Converter

Transcode text or byte sequences from UTF-16 to UTF-8

Convert a UTF-16 hex byte sequence to readable text and its UTF-8 byte representation. Auto-detects the byte-order mark, supports forced big- or little-endian, and decodes surrogate pairs correctly. Free, instant, browser-based. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

What is a byte-order mark?

A byte-order mark (BOM) is an optional prefix that signals endianness: FE FF means big-endian UTF-16, FF FE means little-endian. In Auto mode the tool reads and strips it to decide how to interpret the rest.

Transcoding UTF-16 to UTF-8

UTF-16 and UTF-8 are two ways to store the same Unicode text. UTF-16 — common in Windows APIs, Java strings and some file formats — uses two bytes per code unit and can be big- or little-endian. UTF-8 is the byte-compatible, ASCII-friendly encoding the web standardised on. This tool reads a UTF-16 byte sequence and gives you both the human-readable text and its UTF-8 bytes.

How it works

First the hex input is parsed into raw bytes. The tool inspects the first two bytes for a byte-order mark:

FE FF -> UTF-16 big-endian, strip BOM
FF FE -> UTF-16 little-endian, strip BOM
none  -> assume big-endian (or use your forced choice)

The remaining bytes are paired into 16-bit code units using the chosen endianness, decoded into a JavaScript string (which natively reassembles surrogate pairs into astral characters), and finally re-encoded with TextEncoder to produce the UTF-8 byte sequence.

When you actually encounter UTF-16 data

UTF-16 is less common on the web than UTF-8, but it appears frequently in certain contexts:

  • Windows file system and APIs — the Win32 API uses UTF-16LE natively. Filenames, registry values, and text resources in Windows DLLs are typically UTF-16LE.
  • Java internal strings — Java’s String type historically used UTF-16 internally, meaning .getBytes() without an explicit charset argument on some JVMs produces UTF-16.
  • Microsoft Office file formats — older .doc, .xls formats and parts of .docx XML contain UTF-16 encoded strings.
  • Some database exports — SQL Server and older ODBC drivers may export text in UCS-2 (a subset of UTF-16) by default.
  • Certain embedded systems and protocols — Bluetooth SIG specifications, some font file formats, and Windows PE resources use UTF-16.

If you are seeing a byte dump from any of these sources and the text contains lots of 00 bytes alternating with ASCII values, you are almost certainly looking at UTF-16LE ASCII content — the 00 bytes are the high byte of each two-byte code unit.

Understanding byte order and endianness

UTF-16 encodes each code unit as two bytes. The question is which byte comes first: the high byte or the low byte.

Big-endian (UTF-16BE) puts the high byte first. The letter A (U+0041) is stored as 00 41.

Little-endian (UTF-16LE) puts the low byte first. The same A is stored as 41 00.

Windows, and therefore most Windows-originated UTF-16 data, is little-endian. Network protocols more often use big-endian (also called “network byte order”). The byte-order mark tells a consumer which form to expect, which is why it matters.

Worked example

The bytes FE FF 00 47 00 65 00 72 00 61 carry:

  • FE FF — big-endian BOM (stripped during decoding)
  • 00 47 — U+0047 = G
  • 00 65 — U+0065 = e
  • 00 72 — U+0072 = r
  • 00 61 — U+0061 = a

Decoded text: Gera. UTF-8 output: 47 65 72 61 (four bytes, identical to ASCII since all characters are in the U+0000–U+007F range).

For emoji or CJK characters, the UTF-8 output would expand to 3 or 4 bytes per character even though each was two bytes in UTF-16.

Common errors and how to fix them

Odd byte count after BOM — valid UTF-16 always has an even number of bytes after any BOM (each code unit is exactly two bytes). An odd count means the data is truncated, misaligned, or is not actually UTF-16. Check your source and re-export or re-read the bytes.

Wrong endianness without a BOM — if the decoded text looks like garbage (random CJK characters instead of Latin text), the byte order assumption is wrong. Toggle between big- and little-endian to see which produces meaningful output.

Surrogate pairs — characters above U+FFFF (emoji and rare scripts) are stored in UTF-16 as two code units called a surrogate pair. This tool handles them correctly. If you see garbled emoji in another tool, it may be reading the surrogate pair code units as separate characters instead of reassembling them.

Notes

This is a text-level transcoding tool. It encodes and decodes the bytes you provide and does not validate whether the resulting text is meaningful — that depends entirely on the source data being genuine UTF-16 to begin with. All processing happens in your browser; nothing is uploaded.