---
title: "PyMuPDF4LLMの使い方｜PDFをMarkdownに変換する手順と日本語PDFの注意点【1.28.2】"
url: "https://www.issoh.co.jp/tech/details/2325/"
published: 2024-05-29
updated: 2026-10-12
categories: ["LLM・RAG"]
publisher: "株式会社一創"
---

# PyMuPDF4LLMの使い方｜PDFをMarkdownに変換する手順と日本語PDFの注意点【1.28.2】

PyMuPDF4LLMは、PDFを見出し・表・箇条書きの構造を残したMarkdownに変換するPythonライブラリです。`pymupdf4llm.to_markdown("input.pdf")`の1行で動き、GPUも要りません。この記事では2026年10月時点の最新版1.28.2で全コードを実行し直し、公式ドキュメントに書かれていない日本語PDFでの癖、表抽出のモードによる差、1.28.2で入ったコマンドラインでの一括変換まで、実際の出力を示しながら説明します。

## まとめ

- 導入は`pip install pymupdf4llm`。Python 3.10以上が必要で、PyMuPDFとレイアウト解析のpymupdf\_layoutが同じ版番号で入る。
- 変換は`to_markdown()`。プレーンテキストなら`to_text()`、座標付きの構造データなら`to_json()`を使う。
- 日本語のスキャンPDFは`ocr_language="jpn"`を必ず付ける。既定の`"eng"`のままだと文字化けした結果が返る。
- 罫線の無い表を崩さずにMarkdown表にできたのは既定のレイアウトモードだけ。`table_strategy`や`margins`は`use_layout(False)`の従来モードでしか効かない。
- 1.28.2から`pymupdf4llm`コマンドでフォルダ内のPDFを一括変換できる。日本語OCRは`--opt ocr_language=jpn`で指定する。
- ライセンスはAGPL-3.0とArtifex商用ライセンスのデュアル。ソースを公開しない製品やSaaSに組み込むなら商用ライセンスが要る。

## PyMuPDF4LLMとPyMuPDF・pymupdf\_layoutの関係

PyMuPDF4LLMは、PDF処理エンジンのPyMuPDFの上に載った変換用のパッケージです。PyMuPDF単体の`page.get_text()`は見出しや表の区別がない平文を返しますが、PyMuPDF4LLMはページを解析して見出しに`#`、表にパイプ記法を付けたMarkdownを組み立てます。PDFを開く・編集する・画像を抜くといった操作そのものはPyMuPDFの役割で、本体の使い方は[PyMuPDF（fitz）とは｜インストールから使い方・ライセンスまで解説【2026年版】](/tech/details/4017/)で扱っています。

もう1つの構成要素がpymupdf\_layoutです。PDFの内部情報（文字の位置・フォント・罫線）から「これは見出し」「これは表」「これはページヘッダー」と領域を分類するモデルで、ONNX Runtime上のCPUだけで動きます。[変更履歴](https://github.com/pymupdf/pymupdf4llm/blob/main/CHANGES.md)によると1.27.2.1から自動でインストールされ、`import pymupdf4llm`の時点で有効になります。以前の解説にある「`import pymupdf.layout`を先に書く」手順は、現行版では要りません。止めたいときは`pymupdf4llm.use_layout(False)`を呼ぶと、pymupdf\_layoutを使わない従来の処理（以下、従来モード）に切り替わります。

## PyMuPDF4LLMのインストールと動作要件

```
pip install pymupdf4llm
```

[PyPI](https://pypi.org/project/pymupdf4llm/)の1.28.2（2026年8月6日公開）は、Python 3.10以上を要求し、`pymupdf==1.28.2`・`pymupdf_layout==1.28.2`・tabulate・psutilに依存します。3つのパッケージは版番号を揃えて固定されているので、PyMuPDFだけを別の版に上げると依存の解決で衝突します。

インストール容量は軽くありません。Python 3.12の仮想環境に1.28.2を入れると、site-packagesは252MBになりました。内訳はPyMuPDFが110MB、pymupdf\_layoutが引き込むonnxruntimeが69MB、sympyが29MB、numpyが27MBです。この容量は検証したmacOS・Python 3.12環境の参考値です。コンテナの容量は、対象OS・CPU向けの依存パッケージとベースイメージを含めて別途測定してください。

スキャンページをOCRするには、TesseractかRapidOCR（rapidocr\_onnxruntime）のどちらかが実行環境に必要です。PyMuPDF4LLMは見つかった方を自動で使います。Tesseractの導入と日本語データの入れ方は[Tesseract OCRの使い方｜インストールと日本語設定・主要コマンド【5.5.3対応】](/tech/details/8204/)にまとめています。

## to\_markdownによるPDFのMarkdown変換

### to\_markdownの最小コードとUTF-8保存

```
from pathlib import Path
import pymupdf4llm

md_text = pymupdf4llm.to_markdown("input.pdf")
Path("output.md").write_bytes(md_text.encode())
```

戻り値は全ページを結合した1本の文字列です。`write_bytes(md_text.encode())`はUTF-8で書き出すので、Windowsで`open()`の既定エンコーディングがcp932になって日本語が化ける事故を避けられます。第1引数にはファイルパスのほか、`pymupdf.open()`で開いたDocumentも渡せます。パスワード付きPDFは`doc.authenticate("パスワード")`で開いてから渡すと変換できました。

### to\_markdownの主要引数とモード別の対応範囲

[公式のAPIリファレンス](https://pymupdf.readthedocs.io/en/latest/pymupdf4llm/api.html)には30以上の引数がありますが、レイアウトモードで実際に効くのは次の範囲です。

| 引数              | 既定値        | 用途                      |
| --------------- | ---------- | ----------------------- |
| pages           | None（全ページ） | 0始まりのページ番号リスト           |
| header / footer | True       | Falseで各ページのヘッダー・フッターを除外 |
| page\_chunks    | False      | Trueでページごとの辞書リストを返す     |
| write\_images   | False      | 図をPNGで書き出しMarkdownから参照  |
| embed\_images   | False      | 図をbase64で本文に埋め込む        |
| use\_ocr        | True       | 文字の無いページを自動でOCR         |
| force\_ocr      | False      | 全ページを強制的にOCR            |
| ocr\_language   | “eng”      | TesseractのOCR言語         |
| show\_progress  | False      | 進捗バーを表示                 |

`table_strategy`・`margins`・`fontsize_limit`・`ignore_images`などは、リファレンスに「use\_layout() must be False」と書かれた従来モード専用の引数です。レイアウトモードで`table_strategy="lines"`を渡しても表の検出は変わりません。表が崩れたときに最初に疑うのはこの引数ではなく、次の章で扱うモードの違いです。

`force_ocr=True`は、文字が入っているのに化けているPDFに限って使います。公式ドキュメントも、きれいなテキストPDFに強制OCRをかけると処理が大幅に遅くなり、品質も落ちうると注意しています。

### to\_textとto\_jsonの使い分け

同じ解析結果を別の形式で出す関数が2つあります。`to_text()`は記号を付けないプレーンテキストで、Markdownの`#`や`|`がノイズになる全文検索の索引に向きます。`to_json()`はページごとの領域（boxclassが`page-header`・`section-header`・`text`など）と座標、フォント名・サイズまで含むJSON文字列を返します。帳票から特定の位置の値を抜く、見出しの階層を自前で判定するといった、Markdownでは情報が足りない処理に使います。

## 日本語PDFで出る癖と直し方

公式ドキュメントのサンプルは英語のPDFだけです。そこで、日本語の見出し・本文・表・ヘッダー・フッターを持つ2ページと、文字を画像にしたスキャン相当の1ページからなるPDFを作り、1.28.2で変換しました。検証環境はmacOS、Python 3.12、Tesseract 5.5.3（eng・jpn）です。出てきた癖は3つです。

### 日本語スキャンPDFのOCR言語設定

文字を選択できないページは自動でOCRされますが、OCR言語の既定値は`"eng"`です。日本語のスキャンページを既定のまま変換すると、「第4章 附則」のページが`# 45 AYA`という意味の無い文字列になりました。`ocr_language="jpn"`を付けると「第4章 附則」「この規程は2026年4月1日から施行する。」と正しく出ます。

```
import pymupdf4llm

md_text = pymupdf4llm.to_markdown(
    "input.pdf",
    header=False,
    footer=False,
    ocr_language="jpn",
)
```

Tesseract側に日本語の学習データ（jpn.traineddata）が入っていることが前提です。英語と日本語が混ざる文書は`"jpn+eng"`のように`+`でつなぎます。OCRがかかるのは文字の無いページと、文字化けが多い領域だけです。文字だけのページはOCRに回りません。

### 和文の空白除去と見出しの太字補正

テキストを持つページでも、日本語には次の2つの癖が出ました。空白の挿入は両モードで、見出し中の数字の太字化はレイアウトモードで確認しました。

- 和文と数字の間、PDF上で改行していた位置に半角空白が入る（「翌月 10 日」「電子帳簿保存法に 従います」）
- レイアウトモードでは、見出し中の数字だけが太字になる（「### 第 \*\*1\*\* 章 経費精算」）

LLMに読ませるだけなら大きな害はありませんが、ベクトル検索や全文検索では「10日」と「10 日」が別のトークン列になり、キーワード一致が外れます。索引に入れる前に、和文の前後の空白だけを詰める後処理を挟んでください。次の関数は英単語どうしの空白を残しますが、空白の由来までは判定しません。コードブロックや、空白で区切った和文の固有名詞を含む文書では、本文の段落だけに適用してください。

```
import re

CJK = r"぀-ヿ㐀-鿿！-｠"

def normalize_ja(md: str) -> str:
    # 見出しの数字だけに付いた太字を外す
    md = re.sub(
        r"(?m)^(#{1,6} +)([^\n]*)$",
        lambda m: m[1] + re.sub(r"\*\*([0-9][0-9.\-]*)\*\*", r"\1", m[2]),
        md,
    )
    # 和文と数字の間、改行由来で和文の途中に入った空白を詰める
    md = re.sub(rf"(?<=[{CJK}]) +(?=[{CJK}0-9])", "", md)
    md = re.sub(rf"(?<=[0-9]) +(?=[{CJK}])", "", md)
    return md
```

この関数で「翌月10日までに申請します。領収書の電子保存は電子帳簿保存法に従います。」「### 第1章経費精算」に戻ります。見出しの「章」と章名の間の空白も詰まるので、見出しの体裁を保ちたい場合は見出し行を除外してください。チャンクの長さを日本語でどう決めるかは[チャンクとトークンの違いとは？チャンク分割の手法とRAGのサイズ設計を日本語で実測【2026年版】](/tech/details/8016/)で検証しています。

## 表の抽出結果：レイアウトモードと従来モードの差

同じページに罫線付きの表と罫線の無い表（3列×4行）を置いたPDFで、2つのモードを比べました。

| 比較項目       | レイアウトモード（既定） | 従来モード              |
| ---------- | ------------ | ------------------ |
| 罫線付きの表     | Markdown表になる | 表になるが見出しを1行目に巻き込む  |
| 罫線の無い表     | Markdown表になる | 既定では平文・text戦略で崩れた表 |
| OCR関連の引数   | 有効           | 無視される（警告が出る）       |
| 60ページの処理時間 | 約21秒         | 約7秒                |

従来モードの罫線付きの表は、直前の見出し「罫線付きの表」を表の1行目に取り込み、`|罫線付きの表|Col2|Col3|`という余計な行ができました。従来モードでも`table_strategy="text"`を指定すると罫線の無い表が表として出力されますが、行ごとに空の行と`<br>`が挟まり、直前の見出しも「線なしの表」と1文字欠けて表に取り込まれました。処理時間は、テキストだけの60ページのPDFを別プロセスで各2回変換した値（Intel Core i9-9880H・OCRなし・モデルの読み込みを含む）です。今回のテキストのみの60ページPDFでは、レイアウトモードの処理時間が従来モードの約3倍でした。

結論として、表を含む文書は既定のレイアウトモードのまま使ってください。従来モードに切り替えてよいのは、表が無く、数万ページを短時間で流す必要があり、OCRも要らない場合に限ります。ただしレイアウトモードでも検出漏れはあります。HTMLから生成したPDFの表は、同じ3列×4行でも表と判定されず、セルの値が1行に並んだ平文になりました。表の値をそのまま回答に使うRAGでは、変換後のMarkdownで表の部分だけ目で確かめる工程を外さないでください。

```
import pymupdf4llm

pymupdf4llm.use_layout(False)  # 従来モードに切り替える（プロセス全体に効く）
md_text = pymupdf4llm.to_markdown("input.pdf", table_strategy="lines")
```

## CLIによるフォルダ内PDFの一括変換（1.28.2以降）

1.28.2のパッケージには`pymupdf4llm`コマンドが入りました（1.28.0のwheelには入っていません）。フォルダを渡すと、PDFごとにサブフォルダを作ってMarkdownと処理ログ（run-log.txt）を書き出し、CPUコア数とファイル数からワーカー数を自動で決めて並列処理します。

```
pymupdf4llm ./pdfs --out ./md --opt ocr_language=jpn
```

注意点が2つあります。1つ目は、CLIではヘッダーとフッターが既定で除外されることです。Pythonの`to_markdown()`は既定で含めるので、両者で出力が変わります。残したいときは`--header`と`--footer`を付けます。

2つ目は、1.28.2の`--ocr-lang jpn`が変換処理に渡らないことです。ソースを読むと、`__main__.py`が値を`options["ocr_lang"]`に入れていますが、変換関数が受け取る引数名は`ocr_language`で、この値はどこからも参照されていません。実際に`--ocr-lang jpn`で日本語のスキャンページを変換すると英語OCRの化けた結果になり、上のように`--opt ocr_language=jpn`で渡すと正しく出ました。出力形式は`--backend md|json|txt`、対象ファイルは`--pattern`（既定`*.pdf`）で変えられます。

## RAG向けのpage\_chunks・画像処理とLlamaIndex・LangChain連携

### page\_boxesによる出典付きチャンクの生成

`page_chunks=True`にすると、戻り値がページごとの辞書のリストになります。1.28.2のレイアウトモードで返るキーは`metadata`・`toc_items`・`page_boxes`・`text`の4つでした。古い解説にある`tables`・`images`・`words`は従来モードでしか返りません。

`page_boxes`は領域ごとに種類（`class`）と、`text`内の位置（`pos`）を持ちます。これを使うと、ヘッダー・フッターを落としながら領域単位でチャンクを作り、ファイル名とページ番号を出典として付けられます。

```
import pymupdf4llm

chunks = pymupdf4llm.to_markdown("input.pdf", page_chunks=True, ocr_language="jpn")
records = []
for ch in chunks:
    meta = ch["metadata"]
    for box in ch["page_boxes"]:
        if box["class"] in ("page-header", "page-footer"):
            continue
        start, stop = box["pos"]
        text = ch["text"][start:stop].strip()
        if text:
            records.append({
                "source": meta["file_path"],
                "page": meta["page_number"],  # 1始まり
                "class": box["class"],        # section-header / text / list-item など
                "text": text,
            })
```

引数の`pages`は0始まり、出力の`page_number`は1始まりです。取り違えると出典のページが1つずれます。`section-header`の領域を区切りにして直後の本文とまとめれば、見出し単位のチャンクになります。取り込みと検索をどう分けて設計するかは[RAGパイプラインとは？取り込み系と推論系に分ける工程設計と再索引の実装判断](/tech/details/16473/)を参照してください。

### write\_imagesによる図の画像保存

```
md_text = pymupdf4llm.to_markdown(
    "input.pdf",
    write_images=True,
    image_path="images",
    dpi=200,
)
```

図の領域がPNGで保存され、Markdownには`![](images/input.pdf-0001-02.png)`のような参照が入ります。図の領域にある抽出可能な文字は、既定の`force_text=True`で本文にも出力されます。ただし、画像の画素にしか存在しない文字の抽出にはOCRが必要です。`force_text=False`にすると、図の領域の文字は本文から外れて画像の中にだけ残るので、RAGに使う場合は既定値のままにしてください。`embed_images=True`はbase64で埋め込むためMarkdownが大きく膨らみ、チャンクに画像データが混ざるのでRAGには向きません。

### LlamaIndex・LangChainのローダー連携

```
import pymupdf4llm

reader = pymupdf4llm.LlamaMarkdownReader()
docs = reader.load_data("input.pdf")
```

LlamaIndexの`LlamaMarkdownReader`は、llama-index本体を別途インストールしないと`NotImplementedError`になります。LangChainでは公式パッケージ[langchain-pymupdf4llm](https://pypi.org/project/langchain-pymupdf4llm/)の`PyMuPDF4LLMLoader`を使います。

```
from langchain_pymupdf4llm import PyMuPDF4LLMLoader

loader = PyMuPDF4LLMLoader(file_path="input.pdf", mode="page")
docs = loader.load()
```

langchain-pymupdf4llmの最新版1.28.0は依存を`pymupdf4llm==1.28.0`に固定しています。1.28.2を入れた環境に追加すると1.28.0へ戻り、上で紹介したCLIが使えなくなります。CLIを使うなら、LangChainのローダーとは仮想環境を分けてください。

## PDFをMarkdownに変換する他のツールとの選び分け

PDFからMarkdownを作る手段はPyMuPDF4LLMだけではありません。ライセンスと得意な文書で選びます。

| ツール         | 最新版     | ライセンス              | 向く文書            |
| ----------- | ------- | ------------------ | --------------- |
| PyMuPDF4LLM | 1.28.2  | AGPL-3.0／商用        | テキストPDFの大量変換    |
| Marker      | 2.0.0   | Apache-2.0＋重みは条件付き | 数式・複雑な段組み       |
| Docling     | 2.137.0 | コードはMIT／モデルは個別条件   | コードの公開義務を避けたい場合 |
| MinerU      | 4.0.12  | 独自ライセンス            | 数式や表の多い論文       |
| MarkItDown  | 0.1.8   | MIT                | Office文書を含む多形式  |

選び方を言い切ると、デジタル生成のPDFが中心で、GPUを使わずに大量に流したいならPyMuPDF4LLMです。ソースを公開しないSaaSに組み込むのに商用ライセンスを買う予定が無いなら、PyMuPDF4LLMは外し、コードがMITのDoclingを選びます。Markerは[2.0.0（2026年7月20日）](https://pypi.org/project/marker-pdf/)でコードがApache-2.0になりましたが、モデルの重みは別ライセンスです。前年の総売上または累計の株式・借入による調達額が500万米ドルを超える場合、個人利用・研究目的の例外を除き別途許諾が必要です。競合製品・サービスの提供にも別の制限があります。各ツールの導入手順と判断材料は、[Marker（marker-pdf）の使い方｜PDFをMarkdown変換する手順と商用ライセンス制約](/tech/details/12109/)、[Doclingとは？PDFをMarkdown化してRAGに載せる実装手順と採用判断](/tech/details/17736/)、[MinerUとは？PDFをMarkdownに変換するOSS文書解析ツールの使い方](/tech/details/6505/)、[MarkItDown（マークイットダウン）とは｜各種ファイルをMarkdownに変換するMicrosoft製Pythonツール](/tech/details/4810/)で個別に扱っています。

## 商用利用とAGPLライセンスの判断

PyMuPDF4LLM・PyMuPDF・pymupdf\_layoutの3つは、いずれもGNU AGPL 3.0とArtifex商用ライセンスのデュアルライセンスです。AGPLは、改変したプログラムをネットワーク越しに利用させる場合にも、利用者へソースコードを提供する義務を課します。PDFの取り込みを含むWebサービスをAGPLで使うなら、そのサービスのソースを公開する前提になります。

社内のバッチでPDFをMarkdownに変換し、結果のテキストだけを使う構成では、プログラムを外部に配布もネットワーク提供もしないので、ソース公開の義務は生じにくくなります。境界が曖昧になるのは、変換処理を顧客向けの機能として提供するときです。その場合は採用前に商用ライセンスの見積もりを取り、取れないならDoclingに切り替えてください。社内文書を検索できるRAGの設計からPDFの取り込み方式の選定までを外部に任せたい場合は、[RAG構築支援](/service/ai/rag/)で相談を受け付けています。

## よくある質問

### PyMuPDFの読み方は？

「パイミューピーディーエフ」と読みます。MuPDFはArtifexが開発するC言語製のPDFエンジンで、そのPythonバインディングがPyMuPDFです。PyMuPDF4LLMは「PyMuPDF for LLM」を縮めた名前です。

### pymupdf\_layoutとは何ですか？外せますか？

PDF内部の文字や罫線の情報から見出し・表・ヘッダーなどの領域を分類する、CPUで動くレイアウト解析モデルです。1.27.2.1以降はPyMuPDF4LLMの必須依存なので、インストールからは外せません。処理で使わないようにするには`pymupdf4llm.use_layout(False)`を呼びます。

### PyMuPDFとPyMuPDF4LLMの違いは？

PyMuPDFはPDFを開く・描画する・編集する・テキストを抜くための土台のライブラリで、`import pymupdf`（旧名`fitz`）で使います。PyMuPDF4LLMはその上でMarkdown・JSON・テキストへの変換だけを担います。PDFを操作したいならPyMuPDF、LLMに渡す文書が欲しいならPyMuPDF4LLMです。

### pip install pymupdf4llmで古い版が入るのはなぜですか？

Python 3.9の環境だと、pipはPython 3.9に対応する最後の版0.0.27（2025年7月）を入れます。0.0.27はpymupdf\_layoutに依存しないため、この記事のレイアウトモードやpage\_boxesは使えません。`python -m pip show pymupdf4llm`で版を確かめ、1.28.2でなければPython 3.10以上の環境を作り直してください。

### PyMuPDF4LLMは商用利用できますか？

できます。条件は2通りで、AGPL-3.0に従ってソースを公開するか、Artifexから商用ライセンスを購入するかです。社内でPDFを変換して結果のテキストだけを使う用途なら、AGPLのままで運用できる場合が多いです。

## 関連記事

- [PyMuPDF（fitz）とは｜インストールから使い方・ライセンスまで解説【2026年版】](/tech/details/4017/)
- [Doclingとは？PDFをMarkdown化してRAGに載せる実装手順と採用判断](/tech/details/17736/)
- [Marker（marker-pdf）の使い方｜PDFをMarkdown変換する手順と商用ライセンス制約](/tech/details/12109/)
- [Tesseract OCRの使い方｜インストールと日本語設定・主要コマンド【5.5.3対応】](/tech/details/8204/)
- [チャンクとトークンの違いとは？チャンク分割の手法とRAGのサイズ設計を日本語で実測【2026年版】](/tech/details/8016/)

---

出典: [PyMuPDF4LLMの使い方｜PDFをMarkdownに変換する手順と日本語PDFの注意点【1.28.2】](<https://www.issoh.co.jp/tech/details/2325/>)（株式会社一創）
