Skip to content
Back to blog

Where Mojibake Comes From in Cyrillic Text

5 min read
Where Mojibake Comes From in Cyrillic Text

Anyone who used the Russian-language internet in the 1990s or early 2000s is likely to remember an email, webpage, or text file in which ordinary words appeared as Привет or ╨Я╤А╨╕╨▓╨╡╤В. Russian speakers often call such text krakozyabry, while international technical writing commonly uses the Japanese term mojibake (文字化け).

These strings are not random, and they usually do not indicate a hardware failure. The bytes of the original message may still be present, but the program has read them through the wrong character table. Cyrillic made the problem particularly visible because DOS, Unix, Windows, and early network services used different single-byte encodings for years, while the information identifying the intended table could be lost or mislabeled in transit.

Bytes do not know which letters they represent

A text file stores numbers rather than letters. An encoding is the agreement that maps each number, or sequence of numbers, to a character. In a legacy single-byte encoding, one byte usually represents one character, so a value such as 0xCF can mean different letters in different tables. UTF-8 works differently because characters outside ASCII are represented by multibyte sequences.

The Russian word Привет begins with the bytes D0 9F D1 80 in UTF-8. Give the complete sequence to a UTF-8 decoder and it produces the original word. Interpret those same bytes as Windows-1251 and the result is Привет; interpret them as CP866 and a different garbled string appears. The bytes have not changed. Only the decoding rule has.

This also explains a crucial limit of encoding repair. Mojibake can be reversed only while the mistake itself remains reversible. If an editor replaced unknown characters with ? or ``, discarded bytes, applied a lossy normalization, or saved an already corrupted string through several destructive conversions, the missing information is no longer available to reconstruct.

The same UTF-8 byte sequence becomes the word ‘Привет’ or several forms of mojibake depending on the selected decoder

From a Soviet standard to KOI8-R

One historical branch begins with GOST 19768-74, adopted in the Soviet Union in 1974 for data interchange and processing. It described KOI-7 and KOI-8 character sets, and its early eight-bit table later became one of the sources for network Cyrillic encodings. Modern KOI8-R was not merely that GOST table under a new name: RFC 1489 says that its repertoire also drew on several other Cyrillic sets.

RFC 1489 was published as an Informational document in July 1993 by Andrei Chernov of the Relcom Development Team. It did not declare KOI8-R an international standard. Instead, it documented an encoding already used by a large community and described it as a de facto standard for Unix and global network applications in the former Soviet Union, including Relcom.

KOI8-R is remembered for the way it places Russian letters. The lower half of the table matches ASCII, while many Cyrillic characters in the upper half sit opposite approximately corresponding Latin letters. If an old seven-bit mail route cleared the high bit, the phrase would not survive intact, but it might remain recognizable. Код для обмена информацией, for example, becomes kOD DLQ OBMENA INFORMACIEJ after the high bit of every byte is cleared.

It is tempting to call that result transliteration, but it is only a consequence of the table. Letter case changes, the correspondences are approximate, and symbols without a useful ASCII counterpart can disappear or mutate. The property could help a reader identify a familiar phrase after a particular transmission failure, but it never guaranteed that arbitrary prose would remain legible. The same arrangement also meant that Cyrillic code values were not in ordinary alphabetic order, so correct sorting required encoding-aware software.

CP866 for DOS and Windows-1251 for Windows

DOS followed a different branch. CP866 grew from the so-called Alternative Cyrillic encoding and retained much of the IBM PC box-drawing repertoire: lines, corners, and blocks that text-mode applications used to construct windows and tables. It shipped with the Russian version of MS-DOS 4.01 in 1990, and the current Microsoft identifier table classifies it as OEM Russian, Cyrillic (DOS). This is why CP866 still turns up in old text files, archives, games, terminal interfaces, and documents produced by DOS software.

Windows spread another table. Windows-1251 was already listed as the Windows Cyrillic code page in 1992 Windows 3.1 documentation, and it later became common in Windows applications and on Russian-language websites. Its main Russian letter blocks are close to alphabetic order, while additional Cyrillic letters and punctuation occupy other positions in the table.

The period is often summarized as three large environments: KOI8-R for Unix, email, and early networks; CP866 for DOS; and Windows-1251 for desktop Windows software and a substantial part of the web. That is a helpful map, not a complete census. ISO-8859-5, Mac Cyrillic, and local variants existed alongside them, so two programs could both support Cyrillic and still disagree about the bytes.

How the encoding war produced mojibake

Multiple tables do not damage text by themselves. Trouble starts when encoding metadata disappears from the chain or one application ignores it. An email could arrive without a correct charset parameter, a web server could send one character set in its HTTP header while the HTML declared another, or an editor could open an old file using the operating system default. The same class of error appeared during CSV imports, database migrations, and connections configured with the wrong client encoding.

Sometimes the incorrectly decoded text was saved again. In one step, the original UTF-8 bytes became visible Windows-1251 characters; in the next, those characters were encoded as a new string. Multistage mojibake emerged from repeated conversions, and its appearance sometimes reveals the route the data took. This everyday incompatibility is what made the phrase “encoding war” feel appropriate. Each platform could behave consistently within its own boundaries while communication between platforms repeatedly exposed the mismatch.

Unicode and the gradual move to UTF-8

Unicode 1.0 was published in October 1991 with a different model: instead of giving every language a small, separate table, it assigned characters to a shared code space. UTF-8 became a way to represent those code points as bytes while preserving ASCII compatibility. Its specification evolved with Unicode and ISO/IEC 10646, and the form used on the internet today is defined in documents including RFC 3629, published in 2003.

A better standard did not produce an instant migration. Operating systems, editors, databases, server configurations, and existing archives all had to change. UTF-8 adoption grew throughout the 2000s and 2010s while old websites and documents continued to use Windows-1251, KOI8-R, or CP866. According to W3Techs, UTF-8 was used by 99% of websites with a known character encoding in August 2026, but that statistic cannot rewrite the bytes in an old archive or backup.

Mojibake therefore still appears today. It usually comes from a legacy file, an export from an older database, an incorrectly imported CSV, a misleading HTTP header, or text that was previously opened and saved with the wrong encoding rather than from a modern document that failed without cause.

What String Transformer actually does

String Transformer can investigate such a string directly in the browser. Its automatic recovery tries common pairs of visible and presumed source encodings, including UTF-8, Windows-1251, KOI8-R, CP866, ISO-8859-5, and Mac Cyrillic. It scores the resulting strings and displays up to six plausible candidates for Cyrillic or Hebrew. The ranking is a heuristic rather than proof, so the final choice still has to be checked against the meaning of the text.

Manual mode lets you choose a character set for byte-oriented transformations such as URL encoding, Base32, Base45, Base64, hex, Ascii85, quoted-printable, and byte escapes. The available legacy sets depend on TextDecoder support in the current browser, and the interface disables options the browser cannot decode. Processing is local, so the entered text is not sent to the server.

The tool also changes letter case and naming styles, repairs text typed with the wrong English or Russian keyboard layout, transliterates Cyrillic, and transforms HTML entities, Unicode escapes, Morse code, and Braille. Keyboard-layout repair is separate from encoding recovery: in the first case the user pressed keys under the wrong layout, while in the second case a program interpreted the correct bytes through the wrong table.

For a quick test, paste Привет and inspect the proposed recovery candidates, then type ghbdtn and apply the keyboard-layout correction separately. If a recovered candidate looks right, save it as a new UTF-8 file and keep the only copy of the original data untouched.

Frequently asked questions

What is mojibake?

Mojibake (文字化け) is garbled text produced when a sequence of bytes written in one encoding is decoded according to another. The bytes may still be intact, but the program assigns the wrong characters to them.

Which Cyrillic encodings were used before UTF-8?

KOI8-R was prominent on Unix and early networks, CP866 was common in DOS, and Windows-1251 spread with desktop Windows. This is only a useful shorthand: ISO-8859-5, Mac Cyrillic, and other character sets also existed, so the real compatibility landscape had more than three participants.

Why did KOI8-R partly survive the loss of the high bit?

KOI8-R places many Cyrillic letters so that clearing the high bit produces roughly corresponding ASCII letters. For example, «Код для обмена информацией» becomes 'kOD DLQ OBMENA INFORMACIEJ'. This is neither normal transliteration nor a guarantee that arbitrary text will remain readable, but a familiar phrase could sometimes still be recognized.

Can broken Cyrillic text be repaired automatically?

Sometimes. Recovery works when the original bytes are still represented and the mistaken conversion is reversible. If an application has replaced unknown characters with question marks or U+FFFD, truncated data, or performed several lossy saves, the missing information is no longer present in the garbled string.

Author

Fullstack Engineer

In commercial development since 2011 — over 15 years. Author of two SaaS products, TeleGo.io and LingvoHabit.com. The articles here come out of real client and product work.

About the authorWrite on Telegram

Related Articles