Guides / Finipage / Fixing problems

Fix Garbled Korean Text in HTML Files (EUC-KR to UTF-8)

By the Qorlize team · Last reviewed

Finipage guide · Edit HTML files without code. Open Finipage

You open an old company page or a file exported from a legacy CMS, and the Korean text reads ÇÑ±Û instead of 한글. Or every Korean character has turned into �. Nothing is lost yet. The bytes are still there, and the browser is reading them with the wrong table. The same problem hits old Japanese (Shift_JIS), Chinese (GB2312, Big5) and Western European (Windows-1252) pages, so most of what follows applies to them too.

What the garbage tells you

A text file is a sequence of bytes. An encoding is the table that maps those bytes to characters. Korean pages made before about 2010 were usually saved in EUC-KR, or in its Microsoft extension CP949 (also called MS949 or "ANSI" on Korean Windows). Almost everything made today is UTF-8. The two store the same word very differently:

EncodingBytes for 한글Bytes per syllable
EUC-KR / CP949C7 D1 B1 DB2
UTF-8ED 95 9C EA B8 803

The symptom tells you which mistake was made:

  • Accented Latin letters like ÇѱÛ: EUC-KR bytes read as Windows-1252. Each byte became one Western character (C7 is Ç, D1 is Ñ, and so on).
  • � replacement characters: EUC-KR bytes read as UTF-8. Those byte patterns are invalid in UTF-8, so the browser gives up on them.
  • Odd Hanja and unrelated Hangul syllables, often mixed with ? or �: the reverse case, a UTF-8 file read as EUC-KR. Three-byte sequences get regrouped into wrong two-byte pairs, and pairs that mean nothing in CP949 become replacement characters.

EUC-KR itself only defines 2,350 precomposed syllables. CP949 adds the remaining 8,822 of the 11,172 possible syllables, which is why names with rare syllables such as 똠 or 햏 sometimes break in strict EUC-KR tools. Browsers treat the label euc-kr as CP949, so in practice the two behave the same on the web.

Who decides the encoding: BOM, server header, meta tag

A browser does not start by guessing. The HTML standard has it check three sources, in this order:

  1. A byte order mark (BOM). If the file starts with the bytes EF BB BF, it is UTF-8, full stop. Nothing else is consulted.
  2. The server's Content-Type header. A response such as Content-Type: text/html; charset=euc-kr wins over anything written inside the file.
  3. The meta tag, <meta charset="utf-8"> or the older <meta http-equiv="Content-Type" content="text/html; charset=euc-kr">. It must sit within the first 1,024 bytes of the file, so put it right after <head> (how an HTML file is structured shows where it belongs).

Only when all three are missing does the browser fall back to guessing, based on the bytes themselves and on your browser or system language, and the guess can differ from one browser to another. This explains "it looks fine on my PC but broken on the server." Opened from disk there is no server header, so the meta tag decides. Uploaded to a server configured with AddDefaultCharset UTF-8 (Apache) or charset utf-8; (nginx), the header overrides an EUC-KR meta tag and the text breaks.

The meta tag is a label, not a conversion. Writing charset="utf-8" on a file whose bytes are EUC-KR does not make it UTF-8. It only makes the browser misread it with confidence.

Finding out what the file really is

Check the bytes, not the label. A few reliable ways:

  • VS Code shows the encoding in the status bar at the bottom right. By default it assumes UTF-8; turn on the files.autoGuessEncoding setting so it actually detects EUC-KR.
  • Windows Notepad shows the detected encoding at the bottom right as well, for example UTF-8, UTF-8 with BOM or ANSI. On Korean Windows, ANSI means CP949.
  • The browser. Open the page, press F12, and type document.characterSet in the Console. In the Network tab, click the HTML request and look at the Content-Type response header to see what the server sent.
  • A hex view. Korean syllables in UTF-8 start with a byte between EA and ED and take three bytes. In EUC-KR they take two bytes, the first usually between B0 and C8.

Converting the file to UTF-8

The fix is always two moves: read the file with its real encoding, then write it back as UTF-8. Do it on a copy first.

VS Code

  1. Open the file. Click the encoding name in the status bar.
  2. Choose Reopen with Encoding, then Korean (EUC-KR). The text should now read correctly. If it does not, the file is in some other encoding; try again before saving anything.
  3. Click the encoding name again, choose Save with Encoding, then UTF-8.

Windows Notepad

On Korean Windows, Notepad usually opens CP949 files correctly on its own. Check the text, then use File > Save as and pick UTF-8 from the Encoding drop-down next to the Save button. What decides this is not the display language but the system locale (Control Panel > Region > Administrative tab > Language for non-Unicode programs). If it is set to anything other than Korean, Notepad reads ANSI files with that region's code page, the text is already broken when it opens, and saving it will make the damage permanent. Use VS Code in that case.

Finipage

If you also want to edit the page, you can open it in the Finipage editor. It detects EUC-KR and other legacy encodings when the file opens, so the Korean text shows correctly without any setting, and it saves the result as UTF-8 with the meta charset changed to match. The file never leaves your browser.

Fix the meta tag, and watch out for BOM

After converting, look at the top of the file. If it still says charset=euc-kr, replace that line with <meta charset="utf-8">. VS Code and Notepad change the bytes but leave your HTML alone, so a stale declaration stays behind. It may look fine on a server that sends a UTF-8 header, but opened from disk or moved to another host, the old label takes over again.

About the BOM: Notepad offers both UTF-8 and UTF-8 with BOM. For HTML, plain UTF-8 is the safer choice. A BOM is harmless to browsers when it is at the very start of the page. When a file with a BOM is pulled into a PHP or server-side include, though, those three bytes land in the middle of the output: they can add a stray gap, appear as  on a page read as Western European, or trigger PHP's "headers already sent" error.

If you control the server, make its header agree too. A header still saying charset=euc-kr will break the converted file.

Convert every file that shares text with the page: included headers and footers, external .js files containing Korean strings, and CSV or text data the page loads. One file left in EUC-KR is enough to bring the garbage back in one section.

Next steps

With the text readable again, you may want to change the wording or layout without hand-editing tags. Editing an HTML file without writing code covers that. If images on the same old page are missing too, see why images don't show in an HTML file.

Want to try it on your own file? Open the Finipage editor. It runs in your browser and your file stays on your device.