dom-to-image、html2canvas、puppeteer はいずれも Web コンテンツを画像としてキャプチャするためのツールですが、実行環境やアプローチが大きく異なります。dom-to-image と html2canvas はブラウザ上で動作し、JavaScript を使って DOM 要素をキャンバスに描画して画像化します。一方、puppeteer は Node.js 環境で動作し、ヘッドレス Chrome を制御してページ全体をスクリーンショットとして取得します。これらのライブラリは、クライアントサイドでの軽量な画像生成から、サーバーサイドでの高精度なレンダリングまで、さまざまなユースケースに対応しています。
Webアプリケーションで「この画面を画像として保存したい」という要件はよくあります。たとえば、グラフやレポートのエクスポート、SNSシェア用のプレビュー生成、テスト時のビジュアルリグレッションなどです。しかし、一見同じような目的でも、実行環境や精度、制限事項によって適切なツールは大きく変わります。ここでは、dom-to-image、html2canvas、puppeteer の3つを、実際の開発現場で遭遇する課題を中心に比較します。
dom-to-image と html2canvas は、どちらも ブラウザ内で 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);
});
一方、puppeteer は Node.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-imageかhtml2canvas。バックエンドで定期的にスクリーンショットを撮るなら、puppeteer。
dom-to-image は、DOM 要素を一度 SVG に変換し、それを Canvas に描画します。この方法により、transform、filter、clip-path などの高度な CSS プロパティを比較的正確に再現できます。html2canvas は、DOM ツリーを走査して、各要素のスタイルを Canvas API で再現しようとします。広範な CSS をカバーしていますが、一部のプロパティは未対応または近似値での再現になります。puppeteer は、実際の Chrome ブラウザを使ってページをレンダリングするため、すべての CSS、フォント、画像、Canvas、WebGL などを完全に再現します。// 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(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' });
dom-to-image と html2canvas は、特定の 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-image と html2canvas は、ブラウザのメインスレッドで大量の計算を行うため、大規模な 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(軽量で高精度)html2canvas(広いブラウザ対応と安定性)puppeteer(完全なレンダリング保証)どのツールを選ぶにせよ、自分のユースケースで実際にテストすることが最も重要です。特に、html2canvas と dom-to-image は、同じ HTML でも出力結果が異なることがあります。開発初期に PoC(概念実証)を実施し、期待通りの画像が生成されることを確認しましょう。
html2canvas は、広範な CSS プロパティをサポートしつつ、比較的シンプルな API で DOM 要素を画像化できるライブラリです。多くのプロジェクトで実績があり、標準的な HTML/CSS 構造に対して安定した結果を提供します。ただし、一部の CSS プロパティ(例: box-shadow の複雑な値や ::before/::after の完全再現)には制限があるため、デザインの忠実度が最重要な場合は事前に検証が必要です。
puppeteer は、サーバーサイドで完全なページレンダリングを必要とする場合や、ブラウザ外での自動化されたスクリーンショット取得に最適です。Chrome のフルレンダリングエンジンを利用しているため、すべての CSS、フォント、画像、Canvas などを正確に再現できます。ただし、Node.js 環境でのみ動作し、リソース消費が大きいため、リアルタイム性が求められるフロントエンド UI には不向きです。
dom-to-image は、SVG や Canvas への高忠実度な変換が必要で、かつブラウザ環境で軽量に実行したい場合に適しています。特に、CSS フィルターや transform を含む現代的なスタイルを正確に再現したい場合に有効です。ただし、外部リソース(例: 跨域画像)の取り扱いには注意が必要で、CORS の制約を受けることがあります。
Homepage | Downloads | Questions
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.
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.
The library should work fine on the following browsers (with Promise polyfill):
As each CSS property needs to be manually built to be supported, there are a number of properties that are not yet supported.
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);
});
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
For more information and examples, please visit the homepage or try the test console.
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.