MarkItDown はよく Web スクレイパーと同じものとして扱われますが、それは誤解です。クローラーも JavaScript 実行環境もなく、URL を取りに行って余計な装飾を削る機能もありません。このツールがやるのは、すでに手元にあるデータ——PDF、Word 文書、スプレッドシート、スライド資料など——を、言語モデルが読みやすい Markdown に変換することです。
私は数週間かけて、Microsoft の MarkItDown を 1 台の Mac で実際の文書群に対して検証し、実行前に用意したマニフェストと照らし合わせながら各テーブルを採点し、変換時間も計測しました。結論を先に言うと、きれいな入力では高速で忠実、ただしパッケージには想定外の 73 MB の機械学習ランタイムが含まれ、テーブル処理は「文字が残ったか」は通っても「正しい列に入ったか」は落ちることがあります。以下、数値つきで全体像を見ていきます。
MarkItDown は実際には何か
MarkItDown は Microsoft が提供する Python ユーティリティで、ファイルや Office 文書を LLM 向けに最適化された Markdown に変換します。PDF、.docx、.xlsx、.pptx、画像、HTML ファイルなどを渡すと、Markdown を返してくれます。呼び出し方法は 3 つあり、CLI(markitdown file.pdf -o out.md、または stdin からのパイプ入力)、Python API(MarkItDown().convert(...))、そしてエージェント向けのオプション MCP サーバーです。

ここで大事なのは、やらないことです。README にもその主張はなく、実際のテストでも確認しましたが、クローリング、JS レンダリング、リンク追跡、ページネーション、readability 的な本文抽出は一切行いません。これは文書全体を変換するツールです。あなたがバイト列を持ち込み、MarkItDown がそれを整形します。この違いひとつで、ツールを採用すべきかが決まるので、以降も何度か触れます。
GitHub の見栄え指標では、このリポジトリはかなりの大型です。2026 年 7 月中旬時点で 165,282 stars と 11,790 forks があり、MIT ライセンス、最新リリースは v0.1.6(2026-05-26)です。ただし、この star 数は Microsoft 系リポジトリが LLM ツール熱の波に乗っている結果であって、変換内部の成熟度そのものを示すものではありません。未解決 issue も 833 件あり、その中にはインストール前に知っておきたいものがいくつかあります(後述)。
HTML→Markdown:高速かつほぼ完全、ただし不要な装飾もそのまま
このスクレイパーレビュー連載では同じ 4 つの Web フィクスチャを使っているので、MarkItDown にも同じローカル HTML を与えました。スクレイパーとして採点するためではなく、HTML→Markdown 変換の品質を見るためです。適切にマークアップされたページでは、かなり優秀です。
4 ページすべてが追加依存なしの標準インストールで変換でき、本文の確認ポイントもすべて生き残りました。Wikipedia の “Web scraping” 記事(226 KB)は見出し構造がそのまま再現され、h1 が 1、h2 が 7、h3 が 12 で、実際の章構成と一致しました。418 件のリンクも [text](url) として正しく保持されています。Scrape This Site のフォームページ にある 25×9 のホッケースタッツ表は、きれいな 27 行の GFM パイプテーブル(ヘッダー+区切り+データ 26 行)になりました。空セルもそのままです。処理速度も問題なく、小さな quotes ページでは中央値 48 ms、226 KB の Wikipedia ページでも 352 ms でした。
ただし、ここに落とし穴があります。これはバグというより設計上の選択です。MarkItDown は不要な装飾を削りません。<body> 全体を変換するため、サイトのナビゲーションやフッターも一緒に入ってきます。そして、その残りカスはページの装飾が多いほど増えます。
| ページ | 出力文字数 | 見出し数 (h1/h2/h3) | リンク数 | サイト装飾の行数 |
|---|---|---|---|---|
| Books to Scrape | 10,478 | 1 / 0 / 0 | 94 | 0.6% (1/159) |
| Quotes to Scrape | 2,973 | 1 / 1 / 0 | 55 | 1.2% (1/86) |
| ScrapeThisSite forms | 3,385 | 1 / 0 / 0 | 31 | 6.7% (5/75) |
| Wikipedia Web scraping | 60,159 | 1 / 7 / 12 | 418 | 12.4% (42/338) |
ほぼ装飾のない Books のトップページでは、出力行の 0.6% だけが装飾 です。一方 Wikipedia では 12.4% に達し、338 行中 42 行が「コンテンツへ移動」「目次を切り替える」「22 言語」「Retrieved from」「Cookie とライセンスのフッター」などです。Wikipedia の保守用バナー(「この記事には追加の出典が必要です」など)まできちんと変換され、結果として実データのないページでも 9 行分のテーブルが生まれます。
でも、これは MarkItDown の間違いではありません。これは全文変換ツールであって、読みやすさ抽出ツールではないからです。忠実な HTML→Markdown 変換と、きれいな記事抽出は別の仕事です。Trafilatura や Firecrawl 系のツールは本文だけを返すことを目指しますが、MarkItDown はページ全体を返します。内部実装では _html_converter.py が <script> と <style> を削除し、その後、ページ全体を markdownify ライブラリに渡します。本文抽出のヒューリスティックはどこにもありません。記事だけが欲しいなら、この層は違います。
本来の守備範囲:PDF、DOCX、XLSX、PPTX
MarkItDown が本領を発揮するのは文書です。私は実際の公開ファイルを対象にテストしました。文字レイヤー付きの arXiv 論文、Bitcoin ホワイトペーパー、文字のない画像のみのスキャン PDF(レンダリングして用意)、そして MarkItDown 自身のテストスイートに含まれる DOCX/XLSX/PPTX です。内容の欠落を検出するため、UUID を埋め込んだものも使いました。
| 文書 | 入力サイズ | 出力文字数 | プローブ | 中央値時間 | 備考 |
|---|---|---|---|---|---|
| arXiv 1706.03762(文字レイヤー付き PDF) | 2.2 MB | 40,174 | 7/7 | 3.7 s(warm) | title, "Transformer", "BLEU", "References" がすべて存在 |
| Bitcoin whitepaper(9 ページ PDF) | 184 KB | 22,485 | 6/6 | 1.4 s | "Satoshi Nakamoto", "proof-of-work", "Conclusion" を確認 |
| スキャン PDF(テキストレイヤーなし) | 89 KB | 0 | 0/4 | 15 ms | 空出力、エラーなし、OCR なし |
| DOCX(test.docx) | 136 KB | 4,651 | — | 70 ms | 見出し+GFM テーブル;埋め込んだ UUID は保持 |
| 数式入り DOCX | 15 KB | 240 | — | 101 ms | Office Math を LaTeX として保持 |
| XLSX(test.xlsx) | 12 KB | 808 | — | 57 ms | 各シート → ## SheetName + GFM テーブル |
| PPTX(test.pptx) | 278 KB | 2,047 | — | 52 ms | スライド番号のマーカー、表、グラフ → テーブル |
文字レイヤー付き PDF では文字回収率が非常に高く、arXiv の “Attention Is All You Need” 論文では事前登録した 7 個のプローブがすべて、Bitcoin whitepaper では 6 個すべて通過しました。Office ファイルでも UUID のサインが 1 つも失われず、メンテナの回帰テスト用フィクスチャではサイレントな内容欠落はありませんでした。小さいながら嬉しい発見として、DOCX の経路(mammoth 経由)は Office Math の数式を LaTeX として保持し、equations.docx を本物の $$...$$ 数式に変換します。数式の多い Word 文書を LLM に流すなら、これはかなり実用的な強みです。
この領域で特に注意が必要な点が 2 つあります。どちらも、実運用でハマりやすいものです。
文字レイヤーのないスキャン PDF は消える
テキストレイヤーのない画像だけの PDF を MarkItDown に渡すと、空文字列が返ります。文字数ゼロ、例外なし、警告なし。抽出対象がないので、約 15 ms で終わります。MarkItDown の PDF 経路はテキスト抽出専用で、内部では pdfminer と pdfplumber を使っていますが、コアにも pip の extra にも OCR は含まれていません。
これはバッチ処理では重要です。PDF のフォルダを丸ごと処理し、その中にスキャン画像が混ざっていると、そのファイルだけが何も出さずに空になります。何かがスキップされた兆候はありません。念のため pdfminer の extract_text を直接当ててみて、フィクスチャ自体に問題がないことも確認しました。結果はゼロ文字、テキストレイヤーなし、つまり空出力は MarkItDown の本当の挙動です。これは長く開いたままの OCR フォールバックのギャップ (#1268) を再現するものです。文書化されている回避策は Azure Document Intelligence のオプションバックエンドかプラグインですが、どちらも標準インストールには入っていません。
PDF は構造ではなくフラットなテキストとして出てくる
文字レイヤー付き PDF 2 件のどちらでも、MarkItDown が出力した Markdown の見出しマーカーは 0 でした。PDF には意味的な見出しタグがなく、MarkItDown もフォントサイズから推測しないため、すべての行が本文レベルに落ちます。文字の回収率は高いものの、構造は平坦です。
これは私だけの結果ではありません。第三者の公開ベンチマークでも、MarkItDown の PDF 見出し階層は約 0.0、テーブルの忠実度は約 0.27 と評価されており、Docling の TableFormer ベースの 0.88 を大きく下回っています(MarkItDown vs Docling vs Marker の比較 と READoc ベンチマーク を参照)。私のフィクスチャも同じ傾向を再現しており、これは証拠としてはむしろ強みです。外部ソースと数字が一致しているからです。同じベンチマークが示すトレードオフは、MarkItDown が Docling よりおよそ 100 倍速いという点で、私の「分単位ではなく秒単位」の結果とも一致します。要するに、MarkItDown は PDF のテキストをきれいかつ高速に取り出せる一方、PDF の構造は返しません。見出しやテーブルをそのまま残したいなら、Docling や Marker のようなレイアウトモデル系の層が適しています。
テーブル:内容は残るが、構造は時々崩れる
テーブルは、「文字が残ったか」と「データとして使えるか」が分かれるところです。そこで私は 13 ケースのマトリクスを作り、各ケースごとに 1 つの <table> を用意し、実行前に書いたマニフェストと突き合わせて採点しました。どの形が保たれ、どれが壊れるのかを正確に見極めるためです。

結論をひとことで言うと、MarkItDown はテーブル内容を一度も落としませんでした。13 ケースすべてで、事前登録したトークンは 100% 保持されています。ただし、構造の忠実度は 3 パターンに分かれました。13 件中 7 件は整った GFM のグリッドになりました(通常、header-colspan、24 列幅、headerless、empty-cells、block-in-cell、右→左のアラビア語)。4 件は崩れました。Markdown にはスパンセルの概念がないため、rowspan、colspan、そして元データが不完全なケースでは短い行として出るからです。さらに 2 件は明確に壊れました。
その 2 つは名前を挙げる価値があります。ネストしたテーブル(<td> の中に <table> があるケース)はインラインに平坦化され、子テーブル自身のパイプ記号や区切り行が親セルに流れ込み、14 列相当のゴミ行になります。さらに、セル内のリテラルな | がエスケープされません。a | b は 2 列に、x || y は 3 列に分裂します。その結果、2 列テーブルなのに 2 列、3 列、4 列の行が混在し、後段の Markdown パーサーは誤った境界を読むことになります。興味深いことに、セル内のアスタリスクやバッククォートはエスケープされるのに、パイプだけはそのままです。根本原因は、MarkItDown の HTML 経路が markdownify の標準テーブル処理を使っており、カスタムサブクラスはリンク、画像、見出しは上書きしているのに、テーブルセルは手を加えていないことです。同じパイプエスケープ不具合は、CSV 変換器の オープン issue (#2019) でも見られますが、その修正は私が検証した HTML 経路には効きません。
特にデータエンジニアに見てほしいのは、rowspan の挙動です。ケース t03 は単に崩れるだけでなく、静かに列ズレを起こします。rowspan=2 のラベル(“Fruit”)は 1 回だけ出力され、その下の行は短い 2 列行(| Banana | 8 |)になります。すると “Banana” は Item 列ではなく Group 列に入ってしまいます。トークン自体はすべて存在します。雑に「2 列目を読む」処理は、誤った値を取ります。これは文字が残ったかのチェックを通りつつ、データセットを静かに壊すタイプのバグです。
スパン対応そのものは既知の設計制約で、追跡されている issue があります (#1211, #1248)。フラットな GFM のパイプグリッドでは、スパンやネストを表現できないため、変換器は構造と引き換えに内容の完全性を取っているわけです。良い振る舞いもあります。ヘッダーのないテーブルには空のヘッダー行が合成されるため、データが勝手にヘッダーへ昇格することはありません。空セルも保持され、<caption> はテーブルの上にテキスト行として残ります。
インストールと起動:『軽量ユーティリティ』が黙って課すコスト
ここは本当に意外でした。そして、「軽量な Python ユーティリティ」という説明が静かに言い過ぎになっている部分でもあります。

まず、pip install 'markitdown[all]' は実行しないでください。Python 3.14 では、何の警告もなく markitdown 0.0.2 まで巻き戻ります。これは 2 年前のリリースで、クリーンな仮想環境で実際に再現しました。理由を確認すると、pip install 'markitdown[all]==0.1.6' が失敗するのは、[all] extra が youtube-transcript-api~=1.0.0 を固定しており、現行の PyPI ではその範囲のビルドがすべて Python <3.14 に制限され、3.14 対応ビルドだけがその固定条件から外れるためです。結果として resolver は、依存関係を満たせる最後のリリースまで丸ごと戻ってしまいます。これは オープン issue (#2179) と一致します。対処は簡単で、バージョンを固定して extra を個別に入れます。pip install 'markitdown==0.1.6' の後に、pip install 'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6' を実行します。それぞれは問題なく解決します。毒になっているのは [all] のまとめパッケージだけです。(この落とし穴は Python バージョン依存です。Python 3.13 以前では制限に引っかからず、[all] の解決結果が変わることがあります。)
次にフットプリントです。コアのインストールだけで 161 MB(13 MB の空の venv + 148 MB)あります。このうち onnxruntime が 73 MB、numpy が 34 MB で、合わせて 107 MB、つまりコア全体の 66% を占めます。そして両者は単一の強依存である magika(Google の機械学習ベースのファイル種別判定器)に引き込まれています。つまり、テキスト変換ツールの基本インストールに、1 つも文書用 extra を追加する前から 73 MB の ONNX 推論ランタイムが付いてくるわけです。文書系の extra を足すと、venv は 310 MB に達します。ヘッドレスブラウザのスタックよりはずっと軽いですが、pip install したらすぐ終わるマイクロユーティリティを期待していたなら、ONNX ランタイムが同梱されることは知っておくべきです。
3 つ目は、今回の検証で新規性チェックをすべて通った唯一の発見ですが、クリーンインストール後でも import markitdown にこのマシンでは約 3.35 秒 かかります。コストのほとんどは import 時に発生しており、markitdown._markitdown がコンバーターのレジストリ全体を先読みするためです(累積 2.56 秒、全体の 76%)。その過程で pandas(1.21 秒、XLSX コンバーター経由)、python-pptx(427 ms)、magika(354 ms)、requests(270 ms)が、実際にその形式を変換するかどうかに関係なく読み込まれます。長時間動くサービスならこの import コストは償却され、ほぼ気になりません。しかし CLI の 1 回実行やサーバーレスのコールドスタートでは、1 プロセスごとの税金として確実に効きます。「軽量ユーティリティ」というラベルからは想像しにくいコストです。(公平のために補足すると、これは 1 回のプロファイリング結果であり、分布ではなく単一観測として扱っています。)

スケール:クラッシュはしないが、PDF には CPU、スプレッドシートには RAM を見込むべき
4 種類の大きな対象を、それぞれ別プロセスで処理しました。前の実行の影響でピークメモリが汚染されないようにするためです。クラッシュは一切ありませんでした。ただし、コストプロファイルはかなり偏っています。

| 対象 | 入力サイズ | 出力文字数 | 中央値時間 | ピーク RSS 増分 |
|---|---|---|---|---|
| NIST SP 800-53r5(492 ページ PDF) | 6.07 MB | 1,625,365 | 192.5 s | +40 MB |
| XLSX 50,000 行 × 8 列 | 2.1 MB | 3,722,955 | 62.1 s | +374 MB |
| arXiv 1706.03762(約 15 ページ PDF) | 2.2 MB | 40,174 | 12.6 s | +25 MB |
| XLSX 200 行 × 64 列 | 46 KB | 120,129 | 2.9 s | +22 MB |
492 ページの NIST PDF は中央値 192.5 秒、つまり約 3.2 分(1 ページあたり 0.39 秒)かかりました。pdfplumber が各ページで word-position のフォーム検出を行うためです。ピーク RSS は +40 MB に収まっており、メモリより CPU がボトルネックです。15 ページの arXiv PDF でさえ、別プロセスで回すと 12.6 秒かかりました。これは同じファイルを文書スイート内で warm に回したときの 3.7 秒より約 3.4 倍遅い値です。この差がコールドプロセスのコストであり、処理量の支配要因が生のバイトサイズではないことを示しています。その PDF に 1 つ数値を置くなら、分離実行の 12.6 秒を使うのが妥当です。
スプレッドシート経路はボトルネックが逆転します。2.1 MB、50,000 行の XLSX は +374 MB のピーク RSS(出力文字数 370 万超)まで膨らみました。コンバーターがシート全体を読み込み、巨大な Markdown 文字列を 1 本で組み立てるからです。実用上の指針ははっきりしています。大きな PDF には CPU を数分、巨大なスプレッドシートには RAM を数百 MB 見積もってください。これらは macOS arm64 と Python 3.14 上の単一マシンでの数値で、ページ数あたり・行数あたりの定数は環境依存です。ただし、「PDF は遅くて CPU 寄り、XLSX はメモリを食う、どちらもクラッシュしない」という形は他環境にもかなりそのまま当てはまります。
Thunderbit が適している場面、適していない場面
ここは誇張しやすい比較なので、線引きを丁寧にしておきます。MarkItDown と Thunderbit は隣接する問題を解くツールであって、同じものではありません。
MarkItDown は、すでに持っているファイルを変換します。Thunderbit は、まずページを取得します。Thunderbit の /distill エンドポイント は、ライブな Web ページを LLM 向けのきれいな Markdown に変換し、MarkItDown にはない JS レンダリング、ボット対策、動的コンテンツを処理します。さらに /extract エンドポイントは、生の Markdown ではなく、スキーマに合わせた構造化 JSON を返します。開発者向けには、これらは 1 つの AI エンジンを共通基盤として、API(POST /distill / POST /extract)、MCP サーバー、CLI(npx @thunderbit/thunderbit-cli)として提供されています。背後にあるのは、10 万人超のユーザーを持つ拡張機能 と同じエンジンです。
つまり、両者の重なる部分は 1 つだけです。どちらも「LLM 向け Markdown」を出力できます。ただし入力ドメインは違います。Thunderbit の distill は公開 Web 上の URL を扱い、MarkItDown はローカルファイルを扱います。置き換え可能な代用品ではありません。現実的な構成は両方を使うことです。Thunderbit(または Firecrawl 系サービス)で Web を取得・クロールし、同時に手元にある PDF、スライド、スプレッドシートといったローカル文書を MarkItDown で正規化する。前者はネットワーク、後者はファイル棚を担当します。
長所と短所
長所
- きれいな HTML では本文をほぼ完全に回収(4/4 ページ)、見出しツリーとリンクも忠実に保持
- PDF/DOCX のテキスト回収率が高い(arXiv 7/7、Bitcoin 6/6)、かつメンテナ自身の Office フィクスチャでサイレントな内容欠落なし
- Office Math の数式を LaTeX として保持できる、珍しく実用的な強み
- 492 ページ PDF と 5 万行 XLSX まで、どの規模でもクラッシュしなかった
- CLI、
convert()、stdin パイプ、オプション MCP サーバーと呼び出しが簡単 - MIT ライセンス、Microsoft による継続保守、issue 対応も比較的活発
短所
- 不要な装飾を保持するため、Wikipedia では最大 12.4% がナビやフッターに相当。記事抽出器ではない
- テーブルがスパン、ネスト、セル内のパイプで壊れる(13 件中 2 件は壊れ、4 件は崩れた)。rowspan は静かに列ズレを起こす
- スキャン/画像のみの PDF は空出力で、OCR もエラーもなし
- PDF の出力には見出し構造が一切ない(公開ベンチマークとも一致)
- コアインストールが 161 MB、73 MB の ONNX ランタイムを含む。コールド import は約 3.35 秒
[all]extra は Python 3.14 で 2 年前の 0.0.2 に静かに巻き戻る
どんな人に向いていて、どんな人には向かないか
Word、Excel、PowerPoint、文字レイヤー付き PDF など、手元にある混在文書を LLM パイプライン向けの Markdown に統一したいなら、MarkItDown は有力です。特に、構造の保持よりもテキストの完全性を重視する場面には向いています。バッチ処理の最終段で、きれいなテキストをモデルに渡す用途なら、高速で忠実、しかも無料です。
逆に、次のような場合は別の選択をしたほうがよいです。Web ページから本文だけを取り出したいなら、readability 系か Firecrawl 系のツールを使うべきです。PDF の見出しや表をそのまま残したいなら、Docling や Marker の領域です。入力に OCR が必要なスキャン文書が含まれるなら、Azure バックエンドか、別のツールが必要です。そして「スクレイパー」を探していた、つまり取得やクロールが必要だというなら、これはその役割ではありません。
スクレイパー向けの観点で仮採点すると、MarkItDown は 60/100 でした。ただしこれは、コンバーターをクローラー用の試験で採点したことによる見かけ上の低さです。自分の土俵ではテキスト忠実度は高く、弱点は構造(テーブル、PDF 見出し)とパッケージング(サイズ、import、[all] の罠)にあります。ファイル→Markdown 変換ツールとして評価するなら、実用的でよく保守されたツールであり、本番投入前に把握しておくべき尖った癖がいくつかある、というのが正しい見方です。
よくある質問
MarkItDown は Web スクレイパーですか?
いいえ。クローラーも JavaScript レンダリングもリンク追跡もページネーションもありません。PDF、DOCX、XLSX、PPTX、画像、HTML など、すでに手元にあるファイルや文書を Markdown に変換するだけです。ライブな Web ページを取得してクロールしたいなら、Thunderbit や Firecrawl のようなスクレイピングツールが必要です。MarkItDown はその後段で、取得済みまたはローカルのファイルをきれいな Markdown に整える役目です。
なぜ pip install markitdown[all] で古い版が入るのですか?
Python 3.14 では、[all] extra が youtube-transcript-api~=1.0.0 を固定しており、その範囲のビルドはすべて Python 3.14 未満に制限されています。resolver はその条件を満たせないため、何も言わずに markitdown 0.0.2 まで戻ります。対処法は、バージョンを固定して extra を個別に入れることです。pip install 'markitdown==0.1.6' の後で、'markitdown[pdf,docx,pptx,xlsx,xls]==0.1.6' を追加してください。これは issue #2179 で追跡されています。
MarkItDown はスキャン PDF に OCR をかけますか?
標準インストールではしません。PDF 経路はテキスト抽出のみなので、テキストレイヤーのない画像 PDF は空文字列を返します。エラーも警告もありません。OCR には、オプションの Azure Document Intelligence バックエンドかプラグインが必要で、どちらもデフォルトでは含まれていません。これは長く追跡されているギャップです (issue #1268)。
MarkItDown のテーブル処理はどの程度ですか?
内容面ではかなり優秀です。私の 13 ケースのテストでは、すべてのケースでテーブル内容を 100% 保持しました。構造面は形によります。単純なテーブル、横に広いテーブル、ヘッダーなし、空セルありのテーブルはきれいな GFM グリッドになりますが、rowspan と colspan は崩れやすく、rowspan は静かに別の列へデータをずらすことがあります。ネストしたテーブルはゴミ行に平坦化され、セル内のリテラルなパイプ記号はエスケープされません。Markdown のフラットなテーブル形式では、スパンやネストを表現できないためです。
MarkItDown は大きな文書でも十分速いですか?
大きなファイルでもクラッシュはしませんが、種類ごとにリソースを見積もる必要があります。492 ページ PDF はページごとのフォーム検出を行うため約 3.2 分(約 0.39 秒/ページ)かかり、CPU ボトルネックです。5 万行のスプレッドシートは約 1 分で終わりましたが、メモリ上に巨大な Markdown 文字列を作るため RAM を +374 MB 消費しました。大きな PDF には CPU を数分、大きなスプレッドシートには RAM を数百 MB 見ておくのが無難です。
Web データ抽出なら Thunderbit を試す Get Started Free


