Skip to content
Encoding2026-08-283 min read

Symptom: garbage or question marks after decoding

You feed a Base64 string into a decoder expecting Chinese, but get:

中文

or a row of black question-mark boxes , sometimes �. This means the decoding succeeded, but the bytes were interpreted with the wrong character set.

Root cause: Base64 encodes bytes, not characters

This is the trap almost everyone hits. Base64 only translates a byte sequence into printable characters — it has no idea what text those bytes represented.

  • Chinese is usually 3 bytes in UTF-8, but 2 bytes in GBK;
  • If the encoder turned "你好" into bytes using GBK, but the decoder reads those bytes as UTF-8, you get mojibake;
  • And vice versa.

So the garble is not a Base64 problem — it is an encoding mismatch between the encode and decode ends.

How to fix it

Method 1: online tool (auto UTF-8 by default)

Open the Base64 Encode/Decode tool on ToolVault:

  1. Paste the content into the input;
  2. The tool restores bytes to characters as UTF-8 by default, so Chinese displays correctly;
  3. If the original data was GBK, switch the charset option before decoding;
  4. Everything runs locally in your browser — no upload, safe for sensitive strings.

Method 2: command line

# Standard decode (shows Chinese when terminal locale is UTF-8)
echo '5ZG95ZG9' | base64 -d
# output: 你好

# Force UTF-8 if the locale is off
echo '5ZG95ZG9' | base64 -d | iconv -f UTF-8 -t UTF-8

Method 3: specify the charset explicitly in code

import base64
raw = base64.b64decode("5ZG95ZG9")
text = raw.decode("utf-8")   # be explicit, don't rely on defaults
print(text)                  # 你好
// Browser / Node: TextDecoder with explicit encoding
const bytes = Uint8Array.from(atob('5ZG95ZG9'), c => c.charCodeAt(0));
const text = new TextDecoder('utf-8').decode(bytes);
console.log(text); // 你好

Why you should not "guess" the encoding

When mojibake appears, some people try GBK, GB2312, UTF-8 one by one. It偶尔 works on tiny samples but is unreliable in production:

  • Mixed Chinese/English data may look "mostly fine" with a few boxes — very hard to debug;
  • The correct approach is to fix and declare the charset at the encode end (UTF-8 is the default best practice) and keep the decode end consistent.

FAQ

What are the black boxes (�)?

That is the Unicode replacement character U+FFFD, meaning the decoder hit a byte it could not represent in the current charset. It is a charset mismatch, not data loss.

I typed Chinese when encoding, why is decoding garbled?

When you "type Chinese", the program first turns it into bytes using some charset, then Base64. If that charset differs from the decoder's, it breaks. Standardizing on UTF-8 eliminates this class of bugs.

Are online tools safe?

If you use a local, no-upload tool (like the ToolVault one above), data is processed only in your own browser and never leaves your device — safe for sensitive strings.


Provided by ToolVault. Related tools: URL Encode/Decode, JWT Decoder, Regex Tester. Visit the home page for more developer tools.


Advertisement