概要
業務でHeadless Chromeを使う機会があったのですが、画面のないブラウザくらいの理解しかできていなかったのでHeadless Chromeの仕組み等についてまとめていきたいと思います。
Headless Chrome とは?
Headless Chrome は画面表示を行わない Chrome の起動モードです。HTML/CSS のレンダリングや JavaScript の実行は通常の Chrome と同じように行われます。
仕組み
Headless Chrome は外部からの制御を Chrome DevTools Protocol(CDP)を通じて受けます。CDP は WebSocket(および一部 HTTP)でコマンドやイベントをやり取りし、ページナビゲーションや要素操作、スクリーンショットの取得、ネットワーク制御、パフォーマンス計測などの機能を提供します(ツールによってはローカル起動時に pipe 接続を使う場合もあります)。Puppeteer や Playwright はこれらの低レベルな API をラップして、高水準な操作を可能にするライブラリです。
実際に動かしてみる
今回は Headless Chrome でスクリーンショットを動かしてみます。
前提
以下の技術を使用します。
- Node.js:23.6.0
- npm
- Puppeteer(Chromium 操作用ライブラリ)
手順
- 作業用ディレクトリを作成して移動する
mkdir headless-sample && cd headless-sample
-
package.jsonを作成し、puppeteerをインストールする
npm init -y
npm install puppeteer
- スクリーンショット用のjsファイルを作成する
const puppeteer = require('puppeteer');
(async () => {
let browser;
try {
// Puppeteer を使って Chromium を起動する
// --no-sandbox: サンドボックス無効化(コンテナ/CIでの互換性向上、ただしセキュリティリスクあり)
// --disable-setuid-sandbox: setuid ベースのサンドボックスを無効化して一部環境での起動を助ける
browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
// 新しいページ(タブ)を作成する
const page = await browser.newPage();
// ビューポートサイズを指定する(スクリーンショットの解像度を固定)
await page.setViewport({ width: 1280, height: 800 });
// 指定 URL に遷移する。`waitUntil: 'networkidle2'` はネットワークが落ち着くまで待つ設定
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
// `fullPage: true` でページ全体をキャプチャする
await page.screenshot({ path: 'example.png', fullPage: true });
console.log('Saved screenshot: example.png');
} finally {
if (browser) await browser.close();
}
})();
- スクリーンショットを取得する
node screenshot.js
実行すると、example.pngが作成されます。
指定したHTMLを出力する場合
スクリーンショットの内容をカスタマイズしたい場合は以下のように変えることができます。
const puppeteer = require('puppeteer');
(async () => {
let browser;
try {
browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
const page = await browser.newPage();
// カスタムHTMLを直接セットする例
const html = `
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Custom Screenshot</title>
<style>
body { font-family: Arial, sans-serif; display:flex; align-items:center; justify-content:center; height:100vh; margin:0; background:#f6f8fa; }
.card { background:#fff; padding:40px; border-radius:8px; box-shadow:0 8px 24px rgba(0,0,0,0.08); text-align:center; }
h1 { margin:0 0 8px; font-size:28px; }
p { margin:0; color:#555; }
</style>
</head>
<body>
<div class="card">
<h1>ここに任意のタイトル</h1>
<p>この画像は Puppeteer で生成したカスタムコンテンツです。</p>
</div>
</body>
</html>
`;
await page.setViewport({ width: 1200, height: 800 });
await page.setContent(html, { waitUntil: 'networkidle0' });
await page.screenshot({ path: 'custom-fullpage.png', fullPage: true });
console.log('Saved full page screenshot: custom-fullpage.png');
} finally {
if (browser) await browser.close();
}
})();
まとめ
- Headless Chromeは画面表示なしでも、HTML/CSSの描画やJavaScript実行などを通常のChromeとほぼ同等に扱える
- Puppeteer/Playwrightを使うと、ページ操作やスクショ取得を高水準APIで扱える