Chrome ヘッドレス モード

Peter Kvitek
Peter Kvitek

2017 年に Chrome 59 で導入されたヘッドレス モードは、UI が表示されない無人環境でブラウザを実行できる機能です。基本的に、Chrome は Chrome なしで実行できます。

ヘッドレス モードは、PuppeteerChromeDriver などのプロジェクトを通じたブラウザの自動化によく使用されています。以下に、ヘッドレス モードを使用して特定の URL の PDF ファイルを作成する最小限のコマンドラインの例を示します。

chrome --headless --print-to-pdf https://developer.chrome.com/

ヘッドレスの仕組み

ヘッドレスの仕組みを確認する前に、「古い」ヘッドレスの仕組みを理解することが重要です。上記のコマンドライン スニペットでは、--headless コマンドライン フラグを使用しています。これは、ヘッドレスが通常の Chrome ブラウザの動作モードにすぎないことを示しています。意外かもしれませんが、これは事実ではありません。実際、古いヘッドレスは独立した代替ブラウザ実装であり、たまたま同じ Chrome バイナリの一部として出荷されたものです。//chrome の Chrome ブラウザのコードは共有されません。

独立したヘッドレス ブラウザを実装して維持すると、エンジニアリング上のオーバーヘッドが大きくなります。また、ヘッドレスは独立した実装であるため、ヘッドフル Chrome にはなかった独自のバグと機能がありました。これにより、自動ブラウザテストで混乱が生じ、ヘッドフル モードでは合格してもヘッドレス モードでは失敗したり、その逆の場合もあります。

さらに、Headless は、ブラウザ拡張機能のインストールに依存する自動テストを除外しました。他のブラウザレベルの関数についても同様です。ヘッドレスが独自に実装した場合を除き、サポートされていませんでした。

Chrome チームはヘッドレス モードとヘッドフル モードを統合しました。

新しい Chrome ヘッドレスは独立したブラウザ実装ではなく、Chrome とコードを共有するようになりました。

新しいヘッドレス モードは Chrome 112 から利用できます。このモードではプラットフォームウィンドウは 作成されますが表示はされませんそれ以外の関数はすべて、既存および将来を問わず制限なく使用できます。

ヘッドレス モードを使用する

新しいヘッドレス モードを使用するには、--headless=new コマンドライン フラグを渡します。

chrome --headless=new

現在のところ、以前のヘッドレス モードは以下のデバイスで引き続きご利用いただけます。

chrome --headless=old

Puppeteer 内

Puppeteer で新しいヘッドレス モードを有効にするには:

import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({
  headless: 'new',
  // `headless: true` (default) enables old Headless;
  // `headless: 'new'` enables new Headless;
  // `headless: false` enables "headful" mode.
});

const page = await browser.newPage();
await page.goto('https://developer.chrome.com/');

// …

await browser.close();

Selenium-WebDriver 内

Selenium-WebDriver で新しいヘッドレス モードを使用するには:

const driver = await env
  .builder()
  .setChromeOptions(options.addArguments('--headless=new'))
  .build();

await driver.get('https://developer.chrome.com/');

// …

await driver.quit();

他の言語バインディングを使用する例など、詳細については、Selenium チームのブログ投稿をご覧ください。

コマンドライン フラグ

新しいヘッドレス モードでは、次のコマンドライン フラグを使用できます。

--dump-dom

--dump-dom フラグは、ターゲット ページのシリアル化された DOM を stdout に出力します。次に例を示します。

chrome --headless=new --dump-dom https://developer.chrome.com/

これは、curl で行う HTML ソースコードの出力とは異なります。--dump-dom を出力するために、Chrome はまず HTML コードを解析して DOM に変換し、DOM を変更する可能性のある <script> を実行してから、その DOM をシリアル化された HTML 文字列に戻します。

--screenshot

--screenshot フラグを指定すると、ターゲット ページのスクリーンショットが撮影され、screenshot.png として現在の作業ディレクトリに保存されます。これは、--window-size フラグと組み合わせて使用すると特に便利です。

次に例を示します。

chrome --headless=new --screenshot --window-size=412,892 https://developer.chrome.com/

--print-to-pdf

--print-to-pdf フラグを指定すると、ターゲット ページが output.pdf という名前の PDF として現在の作業ディレクトリに保存されます。次に例を示します。

chrome --headless=new --print-to-pdf https://developer.chrome.com/

必要に応じて、--no-pdf-header-footer フラグを追加すると、印刷ヘッダー(現在の日時を含む)とフッター(URL とページ番号を含む)を省略できます。

chrome --headless=new --print-to-pdf --no-pdf-header-footer https://developer.chrome.com/

不可: --no-pdf-header-footer フラグの背後にある機能は、以前は --print-to-pdf-no-header フラグで使用可能でした。以前のバージョンを使用している場合は、古いフラグ名へのフォールバックが必要になる場合があります。

--timeout

--timeout フラグは、ページが読み込み中であっても、--dump-dom--screenshot--print-to-pdf でページのコンテンツがキャプチャされるまでの最長待機時間(ミリ秒単位)を定義します。

chrome --headless=new --print-to-pdf --timeout=5000 https://developer.chrome.com/

--timeout=5000 フラグを指定すると、Chrome では PDF を印刷する前に最大 5 秒待機します。したがって、このプロセスの実行にかかる時間は最大で 5 秒です。

--virtual-time-budget

--virtual-time-budget は、時間に依存するコード(setTimeout/setInterval など)に対して「早送り」として機能します。ブラウザはページのコードをできる限り速く実行しつつ、ページに実際には時間が過ぎたと認識させます。

その使用法を説明するために、このデモでは、setTimeout(fn, 1000) を使用してカウンタを 1 秒ごとにインクリメント、ログ、表示します。関連するコードは次のとおりです。

<output>0</output>
<script>
  const element = document.querySelector('output');
  let counter = 0;
  setInterval(() => {
    counter++;
    console.log(counter);
    element.textContent = counter;
  }, 1_000);
</script>

1 秒後、ページには「1」、2 秒後には「2」と続きます。 42 秒後のページの状態をキャプチャし、PDF として保存する方法を次に示します。

chrome --headless=new --print-to-pdf --virtual-time-budget=42000 https://mathiasbynens.be/demo/time

--allow-chrome-scheme-url

chrome:// URL にアクセスするには、--allow-chrome-scheme-url フラグが必要です。このフラグは Chrome 123 から利用できます。次の例をご覧ください。

chrome --headless=new --print-to-pdf --allow-chrome-scheme-url chrome://gpu

デバッグ

ヘッドレス モードでは Chrome が実質的に見えなくなるため、問題の解決が難しいように聞こえるかもしれません。ヘッドレス Chrome とよく似た方法で、ヘッドレス Chrome をデバッグできます。

--remote-debugging-port コマンドライン フラグを使用して、Chrome をヘッドレス モードで起動します。

chrome --headless=new --remote-debugging-port=0 https://developer.chrome.com/

これにより、一意の WebSocket URL が stdout に出力されます。次に例を示します。

DevTools listening on ws://127.0.0.1:60926/devtools/browser/b4bd6eaa-b7c8-4319-8212-225097472fd9

ヘッドフル Chrome インスタンスでは、Chrome DevTools のリモート デバッグを使用してヘッドレス ターゲットに接続して検査できます。

  1. [chrome://inspect] に移動し、[Configure...] ボタンをクリックします。
  2. WebSocket URL の IP アドレスとポート番号を入力します。
    • 前の例では、「127.0.0.1:60926」と入力しました。
  3. [完了] をクリックします。リモート ターゲットとそのすべてのタブと他のターゲットが表示されます。
  4. [inspect] をクリックして Chrome DevTools にアクセスし、ページのライブビューなど、リモートの Headless ターゲットを検査します。

Chrome DevTools でリモートのヘッドレス ターゲット ページを検査可能

フィードバック

新しいヘッドレス モードについてのフィードバックをお待ちしています。問題が発生した場合は、バグを報告してください。