CJK (pdfLaTeX / XeLaTeX)

TeX was designed around fonts of 256 characters. Chinese needs tens of thousands. The answer the CJK package gave in 1994 was brutally direct: chop the font into 256-glyph pieces and load whichever piece the next character happens to fall into. Run pdfLaTeX over a Chinese paragraph today and that is still literally what comes out — a PDF carrying gbsnu4e, gbsnu5b, gbsnu65, one subfont per Unicode block. This page covers CJK in LaTeX outside the pTeX world: CJK/CJKutf8 on pdfLaTeX, xeCJK on XeLaTeX, ctex for Chinese and kotex for Korean. Every one of those routes fails first at the font, so it also spells out which CJK fonts a stock TeX Live 2024 actually gives you.

Chinese and Korean on pdfLaTeX: CJKutf8 still works

Being stuck on pdfLaTeX does not stop you setting Chinese or Korean. On TeX Live 2024 it is enough to add \usepackage{CJKutf8} and wrap the body in a CJK* environment — no font installation at all. Measured here, simplified Chinese (gbsn), traditional Chinese (bsmi), Korean (mj) and Japanese (min) each compiled on the first run and embedded Type 1 subfonts in the PDF. The package is by Werner Lemberg, its copyright header reads 1994–2021, and the version in TeX Live is 4.8.5 of 16 October 2021. Think of it as frozen rather than broken. The catch is that CJK can only read fonts that were converted for TeX in advance; an OpenType font installed on the operating system is out of reach. That single limitation is what separates it from XeLaTeX.

latex
% pdflatex — simplified Chinese, no extra fonts needed
\documentclass{article}
\usepackage{CJKutf8}
\begin{document}
\begin{CJK*}{UTF8}{gbsn}
这是一段中文,混排 English words 也没问题。
\CJKfamily{gkai}换成楷体。
\end{CJK*}
\end{document}

The first argument of the environment is the encoding; the second is the font family, and what you may write there depends entirely on which pre-converted fonts you have. Eight families compiled untouched on TeX Live 2024, listed below. Only song failed, with Font cyberb30 at 600 not found — it expects Cyberbit, a font you have to obtain separately. The other thing everyone hits once is writing CJK characters outside the environment. That produces ! LaTeX Error: Unicode character 日 (U+65E5) not set up for use with LaTeX. — one error per character, so a stray paragraph yields dozens of them. Read the first error in the log, not the count.

FamilyLanguageUnderlying fontTeX Live 2024
gbsnSimplified ChineseArphic GB Song (arphic)bundled, compiles as is
gkaiSimplified ChineseArphic GB Kai (arphic)bundled, compiles as is
bsmiTraditional ChineseArphic Big5 Ming (arphic)bundled, compiles as is
bkaiTraditional ChineseArphic Big5 Kai (arphic)bundled, compiles as is
mjKoreanUHC Myeongjo (uhc)bundled; kotex is the better route
minJapaneseWadalab Mincho (wadalab)bundled; upLaTeX is the better route
gothJapaneseWadalab Gothic (wadalab)bundled, compiles as is
maruJapaneseWadalab Maru Gothic (wadalab)bundled, compiles as is
songChineseCyberbit (obtain separately)fails with Font cyberb30 at 600 not found

The difference between CJK and CJK* is not cosmetic. A comment in CJK.sty states it flatly: CJK* swallows the space after a CJK character, whereas CJK does not. In real manuscripts a Chinese sentence gets broken across source lines, and to TeX that line break is one space. Inside CJK the result was 汉字之间不应该 出现空格。 with a gap in the middle of the sentence; inside CJK* it came out correctly closed up as 汉字之间不应该出现空格。 For Chinese and Japanese, CJK* is the default choice. For the same reason, always break the line right after \begin{CJK*}{UTF8}{gbsn} — anything on that same line is read before the CJK meanings are in force. To change font mid-text use \CJKfamily{gkai}; there is no need to nest environments.

If Japanese on pdfLaTeX is forced on you, bxcjkjatype (by ZR; v0.5 of 23 July 2023 in TeX Live 2024), which sits on top of CJK, is far less painful. Writing \usepackage[whole]{bxcjkjatype} wraps the whole document automatically, so you never write a CJK* environment yourself, and it handles both the line-break space and the space between Japanese and Latin. Measured here it closed up correctly and embedded ipaex-type1, IPAex Mincho converted to Type 1. It remains a workaround for being pinned to pdfLaTeX, though; if the engine is yours to pick, read on.

CJK on XeLaTeX: where xeCJK font setup goes wrong

xeCJK is XeLaTeX-only, and whether it compiles or dies comes down to how you spell the font name. Writing nothing but \usepackage{xeCJK} produces a PDF with zero errors, because Fandol Song is loaded by default. But Fandol Song is a Chinese font. Mix Korean into the same document and the log fills with Missing character: There is no 한 (U+D55C) in font [FandolSong-Regular.otf] while the exit status stays 0 and the Hangul simply vanishes from the PDF. Extracting the text confirmed it: the Korean sentence was not there at all. If you use xeCJK for a mixed-script document, naming a font per script is not optional.

latex
% xelatex — one font per script; file names, not family names
\documentclass{article}
\usepackage{xeCJK}
\setCJKmainfont{FandolSong-Regular.otf}[
  BoldFont   = FandolSong-Bold.otf,
  ItalicFont = FandolKai-Regular.otf]
\setCJKsansfont{FandolHei-Regular.otf}
\newCJKfontfamily\korean{UnBatang.ttf}
\begin{document}
这是一段中文。{\korean 한국어 문장입니다.}
\end{document}

What bites here is that XeTeX asks the operating system for its fonts. \setCJKmainfont{FandolSong-Regular.otf} is a file name, resolves inside the TeX tree, and works. Write the very same font as a family name, \setCJKmainfont{Fandol Song}, and it dies with ! Package fontspec Error: The font "Fandol Song" cannot be found. — even though it ships with TeX Live. Conversely, fonts the operating system knows about — Songti SC, PingFang SC, Hiragino Sans on macOS — resolved by family name without complaint. The much-copied \setCJKmainfont{Noto Sans CJK SC} fails the same way, because Noto CJK is not bundled with TeX Live; unless you installed it yourself you get The font "Noto Sans CJK SC" cannot be found. The rule is simple: TeX-tree fonts by file name including the extension, operating-system fonts by family name. The underlying behaviour is covered in depth on the XeTeX page.

Once the fonts are settled, the spacing is next. xeCJK exposes its inter-character spacing through \xeCJKsetup{...}: CJKglue is the space between CJK characters, CJKecglue the space between CJK and Latin. On TeX Live 2024 the defaults are 0pt plus 0.08\baselineskip for CJKglue and ~ for CJKecglue — meaning a full interword space is inserted between a Chinese character and an English word. For readers who know pTeX, these are the same idea as \kanjiskip and \xkanjiskip with different defaults; those are covered on the Japanese typesetting details page. Punctuation compression is PunctStyle, and line breaking between punctuation marks is AllowBreakBetweenPuncts. Note that loading xeCJK under LuaLaTeX stops with ! Critical Package xeCJK Error: The xeCJK package requires XeTeX to function. The name is not decorative.

For Chinese, use ctex — and always pin the fontset

For a Chinese document, reaching for ctex beats configuring xeCJK by hand. Either \documentclass{ctexart} (there are also ctexrep, ctexbook and ctexbeamer) or \usepackage[UTF8]{ctex} on top of an existing class gives you the typefaces, the leading, Chinese heading layout, punctuation compression and Chinese-numeral chapter numbers in one move. ctex detects the engine automatically, by a mechanism as plain as it gets: it checks whether a file named ctex-engine-<engine>.def exists. The supported set is xelatex, lualatex, pdflatex, uplatex and aplatex; anything else stops with Engine '...' is not yet supported, ctex will abort! The version in TeX Live 2024 is 2.5.10.

latex
% xelatex or lualatex — fandol is the only fontset TeX Live guarantees
\documentclass[fontset=fandol]{ctexart}
\begin{document}
\section{中文标题}
这是一段中文,混排 English words。今天是\today\end{document}

The trouble is not the engine but the font set. ctex also tries to detect your operating system — windows on Windows, mac on macOS, fandol otherwise. The macOS test is delightful: it checks whether the file /System/Library/Fonts/Menlo.ttc exists. A typesetting package identifying your OS by the presence of a programmer's monospace font. While the guess is right this is pleasant; when it is wrong it fails loudly. Measured here, running ctexart without a fontset, XeLaTeX succeeded but LuaLaTeX died with ! Package fontspec Error: The font "STHeiti" cannot be found. and pdfLaTeX died with ! Critical Class ctexart Error: CTeX fontset 'mac' is unavailable in current mode. The conclusion is single: always write fontset= yourself. Fandol is the only Chinese family TeX Live is guaranteed to have, so fontset=fandol is the safe choice for a document you will send to someone else. Even then pdfLaTeX reports CTeX fontset 'fandol' is unavailable in current mode., because fandol is Unicode-engine only. On pdfLaTeX, ctex loads CJKutf8 plus CJKpunct/CJKspace internally and expects Windows fonts. If you must use pdfLaTeX for Chinese, drop down to CJKutf8 with gbsn rather than fighting ctex.

Korean with kotex: one line, any engine

Korean needs one line — \usepackage{kotex} — and it works on pdfLaTeX, XeLaTeX and LuaLaTeX alike. That is the friendliest situation of the three CJK languages, and opening kotex.sty explains why: the file is less a package than a dispatcher. It looks for \directlua and \XeTeXrevision and then loads one of three entirely different packageskotexutf (cjk-ko) under pdfTeX, xetexko under XeTeX, luatexko under LuaTeX. Options are forwarded downstream unchanged, so the author never has to think about which route is running. The fonts really do ship, too: measured here, the pdfLaTeX route embedded Nanum Myeongjo Type 1 subfonts (nanumtype1) and the XeLaTeX route embedded UnBatang (unfonts-core). Text extraction came out correct in both.

latex
% pdflatex, xelatex or lualatex — all three work unchanged
\documentclass{article}
\usepackage[hangul]{kotex}
\begin{document}
\section{한국어 시험}
오늘은 \today 입니다.
\end{document}

Adding [hangul] Koreanises the document strings and the date as well: measured, \today became 2026년 8월 13일 and figure captions became 그림 1: (without the option they stay August 13, 2026). Swapping fonts brings XeLaTeX's name-resolution quirk back into play — \setmainhangulfont{UnBatang} died with ! Package fontspec Error: The font "UnBatang" cannot be found., while \setmainhangulfont{UnBatang.ttf} worked. UnBatang.ttf sits inside the TeX tree, and yet the family name does not find it. You can load xetexko directly, but going through kotex means the source does not encode which engine it expects, which makes co-authoring and journal submission easier.

Which CJK fonts you actually have in TeX Live

There is no Noto CJK anywhere in the TeX Live 2024 font tree. Not one file named NotoSansCJK or NotoSerifCJK exists, and what TeX Live's noto package actually provides is NotoSerif, NotoSans and NotoSansMono — the Latin families. The \setCJKmainfont{Noto Sans CJK SC} you see on the web works only because whoever wrote it had Noto CJK installed on their operating system. Put that line in a document you distribute, or in a container image, and it will fail on someone else's machine. What genuinely ships is in the table below, and it shows how thin the Chinese side is: Fandol is the only OpenType family, with Arphic available only in its pre-converted form for the CJK package. Japanese (Harano Aji, IPAex) and Korean (Un fonts, Baekmuk, Nanum) leave you rather more choice.

TeX Live packageLanguageFormatUsed by
fandolChineseOpenTypexeCJK default and ctex fontset=fandol
arphicChineseType 1 subfontsCJKutf8 families gbsn/gkai/bsmi/bkai
arphic-ttfChineseTrueTypeUnicode engines, by file name
haranoajiJapaneseOpenTypedefault for LuaTeX-ja, zxjatype and friends
ipaexJapaneseTrueTypeUnicode engines, by file name
wadalabJapaneseType 1 subfontsCJKutf8 families min/goth/maru
unfonts-coreKoreanTrueTypedefault for xetexko and luatexko
nanumtype1KoreanType 1 subfontskotex on pdfLaTeX (cjk-ko)
uhcKoreanType 1 subfontsCJKutf8 family mj

Choosing a route

When the engine is yours to choose: ctex on XeLaTeX or LuaLaTeX for Chinese, kotex for Korean, and upLaTeX or LuaTeX-ja for Japanese. Drop to CJK/CJKutf8 only when a class or template pins you to pdfLaTeX — a journal's submission rules, typically. Japanese is the one language where the calculus differs: once kinsoku, JFM, ruby and vertical writing enter the picture, xeCJK does not reach what the pTeX family and LuaTeX-ja have accumulated. The comparison of Japanese routes belongs to the Japanese typesetting methods page, and the fine spacing work to the Japanese typesetting details page. For documents that cross languages — a German text quoting Chinese, say — the subject becomes babel, polyglossia and font switching, which the multilingual page owns.

  • Chinese\documentclass[fontset=fandol]{ctexart} on XeLaTeX or LuaLaTeX. Always state fontset explicitly.
  • Korean\usepackage{kotex}, on any engine. Add [hangul] to Koreanise the document strings.
  • Cannot leave pdfLaTeXCJKutf8 with a CJK* environment; gbsn/bsmi for Chinese, kotex for Korean (it falls through to cjk-ko).
  • Several scripts under XeLaTeXxeCJK plus one \newCJKfontfamily per script. Without that, missing characters disappear silently.
  • Japanese → out of scope here; choose upLaTeX or LuaTeX-ja instead.