PDF生成において「wkhtmltopdfで十分なのか、それともChromiumに移行すべきなのか」は、開発者がよく悩むポイントです。
この記事では、両エンジンの違いを具体的なユースケースとともに解説し、プロジェクトに合った選び方を提案します。
wkhtmltopdfとは
wkhtmltopdfは、QtWebKitエンジンをベースにしたオープンソースのHTML→PDF変換ツールです。2012年から使われており、多くのプロジェクトで採用されています。
特徴
- 高速: Chromiumより2〜5倍速い
- 軽量: メモリ消費が少ない(50〜100MB程度)
- シンプル: コマンドラインで即使える
- 安定: 長年の実績
制限事項
- CSS Grid / Flexboxの対応が不完全
- JavaScript実行の制限
- WebKitの古いバージョンがベース
- メンテナンスの停滞
Chromiumエンジンとは
Puppeteer、Playwright、Gotenbergなどは、内部でChromium(Google Chromeのオープンソース版)を使ってPDFを生成します。
特徴
- 完全なCSS対応: Grid、Flexbox、CSS変数、calc()すべてOK
- JavaScript実行: SPAやChartのレンダリングも可能
- 最新Web標準: ブラウザと同じ描画結果
- @media print対応: 印刷用CSSが正確に反映される
制限事項
- 起動が遅い(コールドスタートで1〜3秒)
- メモリ消費が大きい(200〜500MB)
- Dockerやプロセス管理が必要
品質比較
CSS対応
<!-- このレイアウトはwkhtmltopdfでは崩れる -->
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 16px;">
<div>左カラム</div>
<div>右カラム</div>
</div>
| CSS機能 | wkhtmltopdf | Chromium |
|---|---|---|
| Flexbox | 一部対応 | 完全対応 |
| CSS Grid | 非対応 | 完全対応 |
| CSS変数 | 非対応 | 完全対応 |
| calc() | 一部対応 | 完全対応 |
| @media print | 一部対応 | 完全対応 |
| Webフォント | 要設定 | 自動読込 |
| WebP / AVIF 画像 | 非対応 | 完全対応 |
画像形式の対応
JPEG / PNG / GIF は両エンジンで問題なく利用できます。一方、WebP や AVIF といった新しい形式は wkhtmltopdf(QtWebKit)では描画されず、PDF上では画像が欠落します。ChromiumはブラウザがサポートしているのでWebP/AVIFもそのまま埋め込めます。
<!-- wkhtmltopdf では表示されない(Chromiumのみ) -->
<img src="photo.webp" alt="写真">
<!-- 両エンジンで表示できる -->
<img src="photo.jpg" alt="写真">
FUNBREW PDFでWebP画像を含むHTMLを扱う場合は、"engine": "quality" を指定してください。
日本語フォント
wkhtmltopdfでは日本語フォントの設定が必要で、環境によっては文字化けすることがあります。Chromiumは環境にインストールされたフォントを自動で使用するため、設定不要です。
速度
簡単なHTMLの場合(実測値):
| 内容 | wkhtmltopdf | Chromium |
|---|---|---|
| 1ページのテキスト | 0.3秒 | 1.2秒 |
| テーブル10行 | 0.5秒 | 1.5秒 |
| 画像入り5ページ | 1.2秒 | 2.8秒 |
| CSSリッチなレポート | 1.5秒 | 2.5秒 |
wkhtmltopdfが常に速いですが、その差は用途によっては許容範囲です。
用途別の推奨
wkhtmltopdfが向いている場面
- シンプルなテキスト/表のPDF(領収書、シンプルな帳票)
- 大量生成が必要(月に数千〜数万件)
- レスポンスタイムが重要(リアルタイム生成)
- サーバーリソースが限られている
Chromiumが向いている場面
- デザイン性の高い帳票(CSS Grid/Flexboxを使用)
- グラフやチャートを含むレポート(JavaScript描画が必要)
- Web画面そのままをPDF化(URL→PDF変換)
- 印刷用CSSを正確に反映したい
APIコール例
FUNBREW PDFのAPIを使ってエンジンを切り替える方法を、各言語の実装例で解説します。
cURL
# Fast エンジン(wkhtmltopdf)— 高速生成
curl -X POST https://pdf.funbrew.cloud/api/v1/pdf/from-html \
-H "Authorization: Bearer $FUNBREW_PDF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<h1>請求書</h1><p>合計: ¥10,000</p>",
"options": {
"engine": "fast",
"format": "A4"
}
}' \
-o invoice.pdf
# Quality エンジン(Chromium)— CSS Grid対応が必要な場合
curl -X POST https://pdf.funbrew.cloud/api/v1/pdf/from-html \
-H "Authorization: Bearer $FUNBREW_PDF_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"html": "<div style=\"display:grid;grid-template-columns:1fr 1fr\">...</div>",
"options": {
"engine": "quality",
"format": "A4"
}
}' \
-o report.pdf
Python
import httpx
import os
FUNBREW_PDF_API_KEY = os.environ["FUNBREW_PDF_API_KEY"]
def generate_pdf(html: str, engine: str = "fast") -> bytes:
"""
engine: "fast" (wkhtmltopdf) or "quality" (Chromium)
"""
response = httpx.post(
"https://pdf.funbrew.cloud/api/v1/pdf/from-html",
headers={
"Authorization": f"Bearer {FUNBREW_PDF_API_KEY}",
"Content-Type": "application/json",
},
json={
"html": html,
"options": {
"engine": engine,
"format": "A4",
},
},
timeout=30.0,
)
response.raise_for_status()
return response.content
# 請求書(シンプルなHTML → fastで十分)
invoice_html = "<h1>請求書</h1><table>...</table>"
pdf_bytes = generate_pdf(invoice_html, engine="fast")
with open("invoice.pdf", "wb") as f:
f.write(pdf_bytes)
# グラフ入りレポート(CSS Grid使用 → qualityが必要)
report_html = """
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 24px;">
<div><canvas id="chart1"></canvas></div>
<div><canvas id="chart2"></canvas></div>
</div>
"""
pdf_bytes = generate_pdf(report_html, engine="quality")
Node.js
const fs = require('fs');
async function generatePdf(html, engine = 'fast') {
const response = await fetch('https://pdf.funbrew.cloud/api/v1/pdf/from-html', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.FUNBREW_PDF_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
html,
options: {
engine, // 'fast' (wkhtmltopdf) or 'quality' (Chromium)
format: 'A4',
},
}),
});
if (!response.ok) {
throw new Error(`PDF generation failed: ${response.statusText}`);
}
return Buffer.from(await response.arrayBuffer());
}
// 用途ごとに使い分け
async function main() {
// 領収書: シンプルなHTML → fast
const receiptHtml = '<h1>領収書</h1><p>¥5,000</p>';
const receiptPdf = await generatePdf(receiptHtml, 'fast');
fs.writeFileSync('receipt.pdf', receiptPdf);
// 月次レポート: Chart.js使用 → quality
const reportHtml = `
<html>
<head><script src="https://cdn.jsdelivr.net/npm/chart.js"></script></head>
<body>
<h1>月次レポート</h1>
<canvas id="salesChart" width="400" height="200"></canvas>
<script>
new Chart(document.getElementById('salesChart'), {
type: 'bar',
data: { labels: ['1月','2月','3月'], datasets: [{ data: [65,59,80] }] }
});
</script>
</body>
</html>
`;
const reportPdf = await generatePdf(reportHtml, 'quality');
fs.writeFileSync('report.pdf', reportPdf);
}
main();
ユースケース別フロー
請求書生成(wkhtmltopdf / fast)
請求書は通常テキストと表で構成されており、wkhtmltopdfで十分な品質が得られます。
注文確定イベント
↓
請求データをJSON生成
↓
generate_pdf(html, engine="fast") ← 0.3〜0.5秒で完了
↓
PDFをS3保存 + メール送信
詳細な実装例は請求書PDFの自動生成で解説しています。また請求書自動化のユースケースも参照してください。
月次レポート(Chromium / quality)
グラフやダッシュボードのスクリーンショットが必要な場合はChromiumが必須です。
月末バッチ実行
↓
データ集計 → グラフHTML組み立て(Chart.js等)
↓
generate_pdf(html, engine="quality") ← 2〜3秒かかるが品質優先
↓
PDFをダッシュボードに保存 + 管理者へ配信
レポート自動化のユースケースでグラフ入りレポートの実例を紹介しています。
証明書・修了証(Chromium / quality)
フォント装飾や複雑なレイアウトを使う証明書にはChromiumが適しています。
修了イベント(試験合格・研修完了など)
↓
テンプレートに受講者名・修了日を差し込む
↓
generate_pdf(html, engine="quality") ← Flexboxレイアウト対応
↓
PDFをメール送付 + マイページに保存
証明書発行のユースケースで実装パターンを紹介しています。
大量バッチ生成(wkhtmltopdf / fast)
月末の明細書一括送付など、数千件規模では速度が重要になります。
import asyncio
import httpx
async def batch_generate(records: list[dict]) -> list[bytes]:
"""非同期で並列生成(fastエンジンで高スループット)"""
async with httpx.AsyncClient() as client:
tasks = [
client.post(
"https://pdf.funbrew.cloud/api/v1/pdf/from-html",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"html": build_html(r), "options": {"engine": "fast"}},
timeout=30.0,
)
for r in records
]
responses = await asyncio.gather(*tasks)
return [r.content for r in responses]
FUNBREW PDFでの使い分け
FUNBREW PDFでは、APIリクエスト時にエンジンを選択できます。
{
"html": "<h1>Hello</h1>",
"options": {
"engine": "fast"
}
}
| パラメータ | エンジン | 用途 |
|---|---|---|
"engine": "fast" |
wkhtmltopdf | 高速生成、シンプルなHTML |
"engine": "quality" |
Chromium/Gotenberg | 高品質、モダンCSS |
同じテンプレートでも、エンジンを切り替えるだけで速度と品質のバランスを調整できます。
プランごとの利用可能エンジン
| プラン | Fast (wkhtmltopdf) | Quality (Chromium) |
|---|---|---|
| Free | 利用可 | Playgroundのみ |
| Starter | 利用可 | Playgroundのみ |
| Basic〜 | 利用可 | 利用可 |
移行コストの現実:wkhtmltopdfからChromiumへ
wkhtmltopdfを使っているプロジェクトがChromiumに移行する際に発生するコストを把握しておくことが重要です。
移行の主なハードル
1. インフラの変更
wkhtmltopdfは単一バイナリで動作しますが、ChromiumをPuppeteer/Playwrightで操作するにはNode.jsランタイムと200〜500MBのChromiumバイナリが必要です。Dockerイメージのサイズが数百MB増加し、コールドスタートが遅くなります。
# wkhtmltopdfベースのDockerイメージ(約180MB)
FROM surnet/alpine-wkhtmltopdf:3.1.0-0.12.6-full
# Puppeteerベースのイメージ(約800MB)
FROM node:20-slim
RUN apt-get update && apt-get install -y chromium
2. 本番運用の複雑さ
Chromiumはサンドボックス設定、メモリ管理、プロセス監視が必要です。特にDockerコンテナ上では --no-sandbox フラグの安全な設定や、並行処理時のメモリ上限管理がトラブルになりやすいポイントです。PDF API本番運用チェックリストでも詳しく解説していますが、Chromiumの安定稼働には継続的なメンテナンスが伴います。
3. コスト
| 項目 | wkhtmltopdf | Chromium |
|---|---|---|
| インフラコスト | 低(小メモリで動作) | 高(メモリ500MB+) |
| 開発・保守コスト | 低(シンプル) | 高(Chromium管理が複雑) |
| バージョン管理 | ほぼ不要 | Puppeteer/Chrome更新が必要 |
| セキュリティパッチ | 年数回 | 毎月Chrome更新 |
この複雑さを避けたい場合、マネージドのPDF APIサービスを使うのが合理的な選択です。PuppeteerからFUNBREW PDF APIへの移行ガイドでは、既存のChromiumベースのコードをAPIに置き換える手順を解説しています。
エンジン選択のトラブルシューティング
よくある問題と対処法
問題1: wkhtmltopdfで日本語が文字化けする
wkhtmltopdfはフォントの自動検出が弱く、日本語フォントが未インストールだと文字化けします。
# Ubuntuでの日本語フォントインストール
apt-get install fonts-noto-cjk
# wkhtmltopdfコマンドで明示的にフォントを指定
wkhtmltopdf --encoding utf-8 input.html output.pdf
日本語PDF生成ガイドでフォント設定の詳細を解説しています。Chromiumは環境のフォントを自動参照するため、同じ問題が起きにくいです。
問題2: CSSレイアウトがwkhtmltopdfで崩れる
CSS Gridを使ったレイアウトはwkhtmltopdfでは動作しません。Flexboxも部分的なサポートにとどまります。
/* wkhtmltopdfでは崩れる(Chromiumのみ対応) */
.report-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
}
/* wkhtmltopdfでも動作する代替手法 */
.report-table {
width: 100%;
table-layout: fixed;
}
.report-cell {
width: 33.3%;
vertical-align: top;
padding: 12px;
}
詳細な回避策はHTML to PDF CSS最適化ガイドを参照してください。
問題3: Chromiumで特定ページの改ページが崩れる
/* 改ページを制御するCSS */
.section {
page-break-before: always; /* または break-before: page; */
}
.no-break {
page-break-inside: avoid;
}
PDF出力トラブルシューティングで、改ページ問題の原因特定と解決策を体系的にまとめています。
2026年時点でのエンジン選択状況
wkhtmltopdfのメンテナンス状況
wkhtmltopdfは事実上メンテナンスが停滞しており、GitHubリポジトリへのコミットも激減しています。QtWebKitという古いレンダリングエンジンを使用しており、現代のWebスタンダード(CSS Grid、WebP画像、モダンJavaScript)への対応は期待できません。
新規プロジェクトでのwkhtmltopdf採用は推奨しません。 既存システムでの継続使用は許容範囲ですが、機能追加の際にChromiumへの移行を検討するタイミングといえます。
Chromiumエンジンの動向
Puppeteer v22(2024年〜)以降、Chrome for Testingとの統合が進み、特定バージョンのChromeを固定して使えるようになりました。これにより、予期せぬアップデートによる描画の変化を防げます。
// Puppeteer v22以降: Chrome for Testingで固定バージョンを使用
const browser = await puppeteer.launch({
executablePath: '/path/to/chrome-for-testing',
args: ['--no-sandbox', '--disable-dev-shm-usage'],
});
マネージドAPIという第3の選択肢
wkhtmltopdfもChromiumも自前で管理せず、FUNBREW PDFのようなマネージドAPIを使うという選択があります。
- エンジンのインストール・更新・セキュリティパッチが不要
"engine": "fast"(wkhtmltopdf相当)と"engine": "quality"(Chromium相当)をAPIパラメータで切り替え可能- 月次コスト予測が立てやすく、スパイク時も安定
API料金と自前運用のコスト比較はPDF API料金比較で詳しく解説しています。
エラーハンドリングの違い
wkhtmltopdfとChromiumではエラーの種類と対処法が異なります。PDF APIエラーハンドリングガイドでは両エンジン共通のエラーパターンとAPIを使った場合のリトライ戦略を解説しています。
| エラー | wkhtmltopdf | Chromium |
|---|---|---|
| フォント未検出 | 文字化けしてもエラーにならない(サイレント失敗) | コンソールに警告が出る |
| JavaScript実行エラー | 無視される | エラーになることがある |
| タイムアウト | コマンドが終了しないことがある | page.goto() でタイムアウト制御可能 |
| メモリ不足 | クラッシュ | OOMキラーに落とされる |
まとめ
- 速度優先・シンプルなHTML → wkhtmltopdf(
fast) - 品質優先・モダンCSS → Chromium(
quality) - 両方使い分けたい → FUNBREW PDFのデュアルエンジン
- 新規プロジェクト → wkhtmltopdfの採用は避け、ChromiumベースまたはマネージドAPIを選択
迷ったらまずfastで試して、表示が崩れる場合にqualityに切り替えるのが効率的です。
関連リンク
- HTML to PDF API比較 2026年版 — 主要サービスの料金・機能を比較
- PuppeteerからPDF APIへの移行ガイド — Chromiumの運用負荷を削減
- PDF生成APIクイックスタート — Node.js/Python/PHPのコード例
- PDFテンプレートエンジン入門 — テンプレートを使った効率的なPDF生成
- PDF API本番運用チェックリスト — Chromiumの本番環境設定
- PDF APIエラーハンドリング — エンジン別のエラー対処法
- HTML to PDF CSS最適化ガイド — wkhtmltopdf/Chromium共通のCSS設定
- PDF API料金比較 — 自前運用 vs マネージドAPIのコスト比較
- 請求書自動化のユースケース — 請求書生成の活用パターン
- レポート自動化のユースケース — グラフ入りレポートの活用例
- 証明書発行のユースケース — 修了証・証明書の自動発行
- Playground — ブラウザでエンジンの違いを体験