UnicodeDecodeError (Python) and mojibake
In short: Python cannot read bytes as text because the file has a different character encoding than assumed.
In more detail: Message: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe4 in position 12: invalid continuation byte or on Windows 'charmap' codec can't decode byte …. Text consists of bytes; an encoding defines which bytes correspond to which characters. If the assumed one does not match the actual one, this error or mojibake (“ä” instead of “ä”) arises.
In Depth
Causes
- The file is Latin-1/Windows-1252 (for example from older Excel or Windows), Python expects UTF-8.
- On Windows the default encoding of
open()is oftencp1252, not UTF-8. - Binary data (images, ZIP) is read as text.
- A UTF-8 file with BOM (byte order mark) or UTF-16.
- Text wrongly re-encoded several times.
Solutions
- Specify the encoding:
open("file.txt", encoding="utf-8")orencoding="cp1252"/"latin-1". - Detect the encoding: editor (VS Code: bottom right),
file -i file.txt, librarycharset-normalizer. - With BOM:
encoding="utf-8-sig". - For binary data open in
"rb"mode. - As a last resort replace errors:
errors="replace"or"ignore"(loses characters, only if acceptable). - Standardise everything on UTF-8, save files as UTF-8 and set
<meta charset="utf-8">in HTML. For CSV from Excel: choose “CSV UTF-8” or readcp1252.
Repairing mojibake
Typical pattern: UTF-8 text was read as Latin-1. Way back in Python: text.encode("latin-1").decode("utf-8"). The library ftfy helps. Always test with examples, because multiple mis-encodings are more complicated.
See also: ASCII and character sets, UTF-8 and character encoding, ModuleNotFoundError