Decoding UTF-8 means reversing the variable-width byte encoding described in RFC 3629 to recover the original Unicode text from a sequence of bytes. Each Unicode scalar value between U+0000 and U+10FFFF maps to exactly one, two, three, or four bytes, with ASCII characters (U+0000 through U+007F) keeping their single-byte values intact and supplementary characters such as the grinning face emoji U+1F600 spreading across the four bytes F0 9F 98 80. When those bytes are presented as hexadecimal, decimal, or 8-bit binary notation, a strict decoder parses them, validates every byte boundary, and returns the corresponding text — or fails loudly with an explicit error if the sequence is malformed. The UTF-8 Encoder / Decoder does exactly that in your browser: it accepts space- or comma-separated byte tokens, an optional 0x prefix, or one continuous even-length hexadecimal string, then either recovers the exact Unicode characters or refuses the input instead of quietly inserting the U+FFFD replacement character that many default decoders emit. Because the tool runs locally and never uploads anything, you can paste confidential byte sequences and inspect the result without a server round trip.

encoding utf 8 decode
encoding utf 8 decode

What Decoding UTF-8 Actually Means

The decode side of a UTF-8 tool is the opposite of encoding: it takes a byte sequence that already obeys the rules of RFC 3629 and reconstructs the Unicode scalar values those bytes represent. Encoding maps each scalar to a specific one-to-four-byte pattern; decoding reads the leading byte to learn how many continuation bytes follow, then stitches the payload bits together to recover the original code point.

UTF-8 distinguishes four leading-byte ranges. A byte starting with 0 carries the scalar directly and uses one byte total. A byte starting with 110 introduces a two-byte sequence, 1110 a three-byte sequence, and 11110 a four-byte sequence. Every continuation byte must start with the bits 10, and the reconstructed scalar value must not exceed U+10FFFF nor land on a UTF-16 surrogate code point in the range U+D800–U+DFFF. Any violation is a malformed sequence.

To see the procedure in action, decode the cent sign (¢) from its two-byte UTF-8 representation:

  • C2 = 11000010 — the leading 110 bits mark a two-byte sequence, leaving scalar bits 00010.
  • A2 = 10100010 — the leading 10 bits mark a continuation byte, leaving scalar bits 100010.
  • Combine the payload bits: 00010 100010 = 00010100010 = 0xA2 = U+00A2 = ¢.

Every well-formed UTF-8 sequence follows this exact same template, which is what allows a small parser to recover billions of characters without ambiguity.

Input Formats the Decoder Accepts

Before clicking the conversion button, make sure the notation matches what you intend. The UTF-8 Encoder / Decoder treats the three notations as different display representations of the same byte array — switching from hexadecimal to decimal to binary does not change the underlying UTF-8 sequence, only how it is written.

The accepted input rules are intentionally narrow so the parser never has to guess what a stray character might mean:

NotationAccepted token shapeExample for ¢ (U+00A2 = C2 A2)
HexadecimalOne continuous even-length string, or space/comma separated one- or two-digit tokens with optional 0x prefixesC2 A2, c2 a2, 0xC2 0xA2, C2,A2, or C2A2
DecimalInteger tokens in the range 0–255194 162
BinaryExactly eight 0-or-1 characters per token, separated by spaces11000010 10100010

If your hexadecimal string has an odd number of digits, the parser rejects it. If a binary token is shorter or longer than eight characters, it is rejected. If a decimal token is non-integer or falls outside 0–255, it is rejected. Empty input decodes to empty text — that is the only silent path. Input is bounded at 200,000 UTF-16 code units for text and 200,000 bytes for decoded notation, so the parser rejects larger inputs rather than truncating them. These tight rules are what allow the decoder to trust every byte it processes without ambiguity.

How to Decode UTF-8 Bytes Back to Text

Paste a short, known sample into the UTF-8 Encoder / Decoder first to confirm the notation and result are behaving as expected, then move on to the real payload.

  1. Choose UTF-8 bytes to text in the operation selector, then pick hexadecimal, decimal, or binary to match the notation of your source.
  2. Paste your byte tokens into the input field, following the format rules above: even-length hex, decimal 0–255, or eight-bit binary.
  3. Select the conversion button. The decoder parses the tokens, applies fatal UTF-8 validation, and either shows the recovered text or reports an explicit error pointing at the malformed byte.
  4. Cross-check the byte count reported by the result panel against your source. If you pasted C2 A2, you should see two bytes consumed and one Unicode code point recovered.
  5. For sensitive data, run a round trip: take the recovered text, switch the operation to Text to UTF-8 bytes, and confirm the output matches your original byte sequence exactly.
  6. Only after the round trip succeeds should you treat the decoded text as a faithful replacement for the original bytes.

The whole operation stays inside your current browser tab, so nothing is uploaded, logged, stored, normalized, translated, escaped for another context, or copied automatically.

Why Fatal Decoding Beats Silent Replacement

Many default UTF-8 decoders — including Python's bytes.decode() configured for non-strict errors, and JavaScript's TextDecoder constructed without fatal: true — respond to malformed input by inserting U+FFFD, the replacement character, and continuing. That behavior is convenient for casual browsing but dangerous when the goal is to verify that a byte dump is genuinely valid UTF-8.

The UTF-8 Encoder / Decoder configures the browser's TextDecoder with fatal: true, so the following categories of malformed input fail with an explicit error instead of producing a string full of replacement glyphs:

  • Overlong encodings, such as C0 AF, which try to represent a code point that already fits in one byte using two.
  • Truncated sequences, such as E2 82 with no continuation byte following the three-byte leader.
  • Isolated continuation bytes, such as A2 standing alone without a leading byte.
  • Surrogate encodings, such as ED A0 80 attempting to encode U+D800.
  • Values above U+10FFFF, which exceed the maximum Unicode scalar.

When you see an error rather than a string full of � marks, you know the bytes were not valid UTF-8. The next step is to identify the actual encoding — Windows-1252, Shift JIS, GBK, or an ISO-8859 family member — rather than forcing the bytes through UTF-8 and pretending the result is verified.

Round-Trip a Known Sample First

Decoded text that looks plausible is not the same as decoded text that is provably identical to the source. Before overwriting any original data with the decoded output, run a round-trip check: encode the recovered text back into bytes and compare every byte against your starting sequence.

Use a short, well-known sample. The dollar sign U+0024 is the simplest case:

  • Known UTF-8 bytes: 24 (hex), 36 (decimal), or 00100100 (binary).
  • Decode to text — the result should be the single character $.
  • Switch to text-to-bytes, paste $, choose the same notation, and run the conversion.
  • The output should be 24, 36, or 00100100 again, byte for byte identical.

If the round trip fails at any point, the original byte sequence was not valid UTF-8 in the first place, or your notation choice was inconsistent between the two operations. Both diagnoses are valuable, and neither can be made if the decoder silently swaps in replacement characters. For multi-byte checks, repeat the same procedure with the cent sign (U+00A2 = C2 A2), the euro sign (U+20AC = E2 82 AC), or the grinning face (U+1F600 = F0 9F 98 80). Always start small before trusting an unknown dump.

UTF-8 Is Not Base64, URL, or HTML Encoding

UTF-8 bytes are commonly confused with several other byte representations that show up in web contexts. Each encoding serves a different transport purpose and is not interchangeable:

RepresentationWhat it encodesUse case
UTF-8 bytesUnicode scalar values mapped to 1–4 bytesFile storage, network protocols, source code
Base64Arbitrary bytes mapped to a 64-character alphabetEmbedding binary inside text-only channels
URL percent-encodingBytes encoded as %HH for safe transport in URLsQuery strings, path segments
HTML entitiesCharacters encoded as &name; or &#nnn;Reserved or invisible characters in HTML markup
Hexadecimal numbersNumeric values written in base 16Color codes, memory addresses, identifiers

If your input begins with letters like iVBORw0KGgo, you are looking at Base64, not UTF-8 hex. If it begins with %E2%82%AC, you are looking at URL percent-encoding of UTF-8 bytes, not the bytes themselves. Sending a percent-encoded string through a UTF-8 decoder will produce literal % characters, not the original text.

Reference Byte Sequences for Common Scalars

To anchor the byte patterns you should expect to see, here are the canonical UTF-8 encodings of eight well-known Unicode scalars used as anchors by the tool and described in the Unicode Standard:

ScalarMeaningUTF-8 bytes (hex)
U+0024Dollar sign ($)24
U+0041Letter A41
U+007FLast one-byte scalar (DEL)7F
U+00A2Cent sign (¢)C2 A2
U+0800First three-byte scalar boundaryE0 A0 80
U+20ACEuro sign (€)E2 82 AC
U+1F600Grinning face (😀)F0 9F 98 80
U+10FFFFMaximum Unicode scalarF4 8F BF BF

When you decode any of these, you should get exactly the character shown in the second column — no replacement glyphs, no padding, no extra whitespace. If the result differs, the input bytes were either mistyped, in the wrong notation, or not UTF-8 in the first place.

If you're weighing options, XOR Cipher Calculator: Encrypt and Decrypt Text Online covers this in detail.