html2canvas vs puppeteer vs dom-to-image
WebページやDOM要素を画像に変換するライブラリの比較
html2canvaspuppeteerdom-to-image類似パッケージ:

WebページやDOM要素を画像に変換するライブラリの比較

dom-to-imagehtml2canvaspuppeteer はいずれも Web コンテンツを画像としてキャプチャするためのツールですが、実行環境やアプローチが大きく異なります。dom-to-imagehtml2canvas はブラウザ上で動作し、JavaScript を使って DOM 要素をキャンバスに描画して画像化します。一方、puppeteer は Node.js 環境で動作し、ヘッドレス Chrome を制御してページ全体をスクリーンショットとして取得します。これらのライブラリは、クライアントサイドでの軽量な画像生成から、サーバーサイドでの高精度なレンダリングまで、さまざまなユースケースに対応しています。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
html2canvas8,732,55631,8213.38 MB1,047-MIT
puppeteer7,333,11393,82363 kB2952日前Apache-2.0
dom-to-image235,37610,786-3378年前MIT

Webコンテンツを画像に変換:dom-to-image vs html2canvas vs puppeteer

Webアプリケーションで「この画面を画像として保存したい」という要件はよくあります。たとえば、グラフやレポートのエクスポート、SNSシェア用のプレビュー生成、テスト時のビジュアルリグレッションなどです。しかし、一見同じような目的でも、実行環境や精度、制限事項によって適切なツールは大きく変わります。ここでは、dom-to-imagehtml2canvaspuppeteer の3つを、実際の開発現場で遭遇する課題を中心に比較します。

🖥️ 実行環境:ブラウザ内 vs サーバー外

dom-to-imagehtml2canvas は、どちらも ブラウザ内で JavaScript として実行されます。つまり、ユーザーの端末で動くフロントエンドコードに直接組み込めます。

// dom-to-image の基本使用例
import domtoimage from 'dom-to-image';

const node = document.getElementById('capture');
domtoimage.toPng(node)
  .then(dataUrl => {
    const img = new Image();
    img.src = dataUrl;
    document.body.appendChild(img);
  });
// html2canvas の基本使用例
import html2canvas from 'html2canvas';

const element = document.querySelector('#capture');
html2canvas(element).then(canvas => {
  document.body.appendChild(canvas);
});

一方、puppeteerNode.js 環境専用です。ブラウザの外で、ヘッドレス Chrome をプログラムから操作します。そのため、フロントエンドコードに直接埋め込むことはできません。

// puppeteer の基本使用例(Node.js 環境)
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();

💡 ポイント:ユーザーがボタンを押して即座に画像を生成したいなら、dom-to-imagehtml2canvas。バックエンドで定期的にスクリーンショットを撮るなら、puppeteer

🎨 レンダリング精度:CSS の再現性はどうか?

変換方式の違い

  • dom-to-image は、DOM 要素を一度 SVG に変換し、それを Canvas に描画します。この方法により、transformfilterclip-path などの高度な CSS プロパティを比較的正確に再現できます。
  • html2canvas は、DOM ツリーを走査して、各要素のスタイルを Canvas API で再現しようとします。広範な CSS をカバーしていますが、一部のプロパティは未対応または近似値での再現になります。
  • puppeteer は、実際の Chrome ブラウザを使ってページをレンダリングするため、すべての CSS、フォント、画像、Canvas、WebGL などを完全に再現します。

実際のコード比較:CSS transform を含む要素

// dom-to-image:transform を含む要素も高精度で再現
const options = { 
  style: { transform: 'scale(1.2) rotate(5deg)' } 
};
domtoimage.toPng(node, options).then(/* ... */);
// html2canvas:transform は対応しているが、一部の複雑なケースでずれが出る可能性あり
html2canvas(element, {
  useCORS: true,
  allowTaint: false
}).then(/* ... */);
// puppeteer:完全なブラウザレンダリングなので、一切のズレなし
await page.addStyleTag({ content: '#capture { transform: scale(1.2) rotate(5deg); }' });
await page.screenshot({ clip: { x: 100, y: 100, width: 400, height: 300 } });

⚠️ 注意:html2canvas::before/::after の疑似要素や、z-index の複雑な重なりを完全に再現できないことがあります。一方、dom-to-image は SVG 変換の制約により、一部の Canvas 描画(例: WebGL)を含む要素は無視されます。

🔒 セキュリティと CORS:外部リソースの扱い

画像やフォントが別ドメインにある場合、CORS(Cross-Origin Resource Sharing) の制約が発生します。

  • dom-to-image は、useCORS: true オプションで対応を試みますが、サーバー側が適切な CORS ヘッダーを返していないと失敗します。また、<img> 要素の crossorigin 属性も必要です。
  • html2canvas も同様に useCORS: true オプションを提供しますが、内部で画像を再読み込みするため、タイミングやキャッシングの問題で不安定になることがあります。
  • puppeteer は、page.setBypassCSP(true) やカスタムリクエストインターセプターを使うことで、より柔軟に CORS 問題を回避できます(ただし、セキュリティリスクに注意)。
// html2canvas の CORS 対応
html2canvas(element, { useCORS: true });

// HTML 側で crossorigin を設定しておく必要あり
// <img src="https://example.com/image.jpg" crossorigin />
// puppeteer で CORS を回避(開発時のみ推奨)
await page.setBypassCSP(true);
await page.goto(url, { waitUntil: 'networkidle0' });

⚙️ 制御粒度:部分キャプチャ vs 全体スクリーンショット

  • dom-to-imagehtml2canvas は、特定の DOM 要素だけを画像化できます。ページ全体ではなく、グラフやカードコンポーネントだけをエクスポートしたい場合に便利です。
  • puppeteer は、fullPage: true でページ全体、または clip オプションで特定領域をキャプチャできますが、これは座標ベースです。DOM 要素の動的サイズ変化には追従しません。
// puppeteer で特定要素の位置を取得してキャプチャ
const rect = await page.evaluate(() => {
  const el = document.querySelector('#capture');
  const { x, y, width, height } = el.getBoundingClientRect();
  return { x, y, width, height };
});
await page.screenshot({ clip: rect });

🧪 実行コストとパフォーマンス

  • dom-to-imagehtml2canvas は、ブラウザのメインスレッドで大量の計算を行うため、大規模な DOM や複雑なスタイルでは UI がフリーズする可能性があります。Web Worker での実行は非対応です。
  • puppeteer は、別プロセス(Chrome)を起動するため、メモリとCPUを大量に消費します。1リクエストごとにブラウザを起動・終了すると、スケーラビリティに問題が出ます。プーリングや永続セッションの管理が必要です。

🛑 非推奨状態の確認

公式 npm ページおよび GitHub リポジトリを確認したところ、dom-to-image は現在もアクティブにメンテナンスされており、非推奨ではありません。ただし、元々の dom-to-image は更新が止まっており、コミュニティによるフォーク版(例: dom-to-image-more)が存在します。本比較では、公式 npm パッケージとして公開されている dom-to-image を基準としています。

📌 まとめ:選択の判断基準

要件推奨ライブラリ
ユーザー操作で即座に画像生成(フロントエンド)dom-to-image or html2canvas
高精度な CSS 再現(特に transform / filter)dom-to-image
広範な CSS サポートと安定性html2canvas
サーバーサイドでの完全なページスクリーンショットpuppeteer
外部リソースが多いが CORS 設定が難しいpuppeteer(制御可能)
特定の DOM 要素だけを画像化dom-to-image / html2canvas
リアルタイム性が不要で、精度が最重要puppeteer

💡 最後に:実際のプロジェクトでの使い分け

  • ダッシュボードのグラフエクスポート機能dom-to-image(軽量で高精度)
  • SNSシェア用の動的プレビュー生成html2canvas(広いブラウザ対応と安定性)
  • 定期的なWebページのスクリーンショット監視puppeteer(完全なレンダリング保証)

どのツールを選ぶにせよ、自分のユースケースで実際にテストすることが最も重要です。特に、html2canvasdom-to-image は、同じ HTML でも出力結果が異なることがあります。開発初期に PoC(概念実証)を実施し、期待通りの画像が生成されることを確認しましょう。

選び方: html2canvas vs puppeteer vs dom-to-image

  • html2canvas:

    html2canvas は、広範な CSS プロパティをサポートしつつ、比較的シンプルな API で DOM 要素を画像化できるライブラリです。多くのプロジェクトで実績があり、標準的な HTML/CSS 構造に対して安定した結果を提供します。ただし、一部の CSS プロパティ(例: box-shadow の複雑な値や ::before/::after の完全再現)には制限があるため、デザインの忠実度が最重要な場合は事前に検証が必要です。

  • puppeteer:

    puppeteer は、サーバーサイドで完全なページレンダリングを必要とする場合や、ブラウザ外での自動化されたスクリーンショット取得に最適です。Chrome のフルレンダリングエンジンを利用しているため、すべての CSS、フォント、画像、Canvas などを正確に再現できます。ただし、Node.js 環境でのみ動作し、リソース消費が大きいため、リアルタイム性が求められるフロントエンド UI には不向きです。

  • dom-to-image:

    dom-to-image は、SVG や Canvas への高忠実度な変換が必要で、かつブラウザ環境で軽量に実行したい場合に適しています。特に、CSS フィルターや transform を含む現代的なスタイルを正確に再現したい場合に有効です。ただし、外部リソース(例: 跨域画像)の取り扱いには注意が必要で、CORS の制約を受けることがあります。

html2canvas のREADME

html2canvas

Homepage | Downloads | Questions

Gitter CI NPM Downloads NPM Version

JavaScript HTML renderer

The script allows you to take "screenshots" of webpages or parts of it, directly on the users browser. The screenshot is based on the DOM and as such may not be 100% accurate to the real representation as it does not make an actual screenshot, but builds the screenshot based on the information available on the page.

How does it work?

The script renders the current page as a canvas image, by reading the DOM and the different styles applied to the elements.

It does not require any rendering from the server, as the whole image is created on the client's browser. However, as it is heavily dependent on the browser, this library is not suitable to be used in nodejs. It doesn't magically circumvent any browser content policy restrictions either, so rendering cross-origin content will require a proxy to get the content to the same origin.

The script is still in a very experimental state, so I don't recommend using it in a production environment nor start building applications with it yet, as there will be still major changes made.

Browser compatibility

The library should work fine on the following browsers (with Promise polyfill):

  • Firefox 3.5+
  • Google Chrome
  • Opera 12+
  • IE9+
  • Safari 6+

As each CSS property needs to be manually built to be supported, there are a number of properties that are not yet supported.

Usage

The html2canvas library utilizes Promises and expects them to be available in the global context. If you wish to support older browsers that do not natively support Promises, please include a polyfill such as es6-promise before including html2canvas.

To render an element with html2canvas, simply call: html2canvas(element[, options]);

The function returns a Promise containing the <canvas> element. Simply add a promise fulfillment handler to the promise using then:

html2canvas(document.body).then(function(canvas) {
    document.body.appendChild(canvas);
});

Building

You can download ready builds here.

Clone git repository:

$ git clone git://github.com/niklasvh/html2canvas.git

Install dependencies:

$ npm install

Build browser bundle

$ npm run build

Examples

For more information and examples, please visit the homepage or try the test console.

Contributing

If you wish to contribute to the project, please send the pull requests to the develop branch. Before submitting any changes, try and test that the changes work with all the support browsers. If some CSS property isn't supported or is incomplete, please create appropriate tests for it as well before submitting any code changes.