スクレイピング

スクレイピングにヘッドレスブラウザが本当に必要になるのはどんな時か

ヘッドレスブラウザはページを取得する方法の中で最もコストがかかります。ほとんどのサイトではその必要はありません。ここでは、通常のHTTPとフルブラウザのどちらを使うべきか判断する方法を説明します。

Chris Collins

Chris Collins

2026年8月20日 · 1 分で読める

スクレイピングの案件が始まると、反射的にヘッドレスブラウザに手を伸ばしがちだ。Playwright、Puppeteer、Seleniumは実際のブラウザにできることは何でもできるので、無難な既定の選択肢に思える。しかしヘッドレスブラウザは、ページを取得する方法としては最もコストがかかる部類に入る。CPUとメモリを消費し、ページ全体とそれに付随するすべてのアセットを引っ張ってくるうえ、動作が遅いため、ワーカーあたりに収集できるページ数の上限も下がる。多くの場合、実際には平文で最初から存在していたわずかなフィールドを抽出するために、そのすべてのコストを払っていることになる。本当に問うべきなのは「ブラウザを使うか使わないか」という習慣ではなく、その特定のページが実際に何を必要としているかだ。以下、その判断方法を示す。

ヘッドレスブラウザが実際にもたらすもの

ヘッドレスブラウザとは、可視ウィンドウのない本物のブラウザエンジンだ。ページのJavaScriptを実行し、DOMを構築し、最近のページが行うバックグラウンドのfetchやXHR呼び出しを実行し、クライアントサイドのコンテンツをレンダリングし、クリックやスクロール、入力によって結果と対話することもできる。また、本物のブラウザであるがゆえに、完全でリアルなブラウザフィンガープリントとTLSハンドシェイクを示す。これは非常に大きな能力だ。問題は、そのすべてに何らかのコストがかかることであり、そしてほとんどのページはその能力のほとんどを必要としないということだ。

平文のHTTPで十分な場合、これは思っている以上に多い

ブラウザを自動化する前に、そのページが実際に何でできているかを見てみよう。多くの場合、PythonのrequestsやhttpxのようなプレーンなHTTPクライアントだけで十分だ。

1つ目のケースは、サーバーサイドでレンダリングされたHTMLだ。欲しいデータが最初のHTMLレスポンスに存在している場合、ページのソースを見るかcurlでURLを取得すればそこにそのまま存在していることが分かる。この場合、ブラウザはオーバーヘッド以外何ももたらさない。2つ目の、そして最も見落とされがちなケースは、背後にあるJSON APIだ。最近のページはバックエンドのエンドポイントから、ページ自身が呼び出す形でレンダリングされていることが非常に多く、ネットワークパネルを開いてXHRリクエストを観察すると、欲しいデータそのものがきれいなJSONレスポンスとして返ってきていることが頻繁にある。HTMLの解析は一切不要だ。そのエンドポイントを直接HTTPで呼び出す方が、そのページ自体をレンダリングするよりも速く、安定していて、パースも簡単だ。3つ目のケースは、静的またはやや動的なページで、重要な部分がクライアントサイドのスクリプトに依存していない場合だ。

この方法は単にシンプルというだけでなく、劇的に安上がりだ。1回のHTTPリクエストで要求したバイトだけを取得するので、速く、並列化しやすく、プロキシを通るデータ量もごくわずかで済む。この最後の点はコストに直結する。一般的なクライアントのパターンについてはPythonでレジデンシャルプロキシAPIを使うガイドに詳しいが、HTTPの経路にとどまることは、プロキシの帯域幅を削減することとレイテンシを抑えることの両方において最大級のレバーの1つだ。

本当にブラウザが必要な場合

一部のページは本当にブラウザを必要とし、それに対してHTTPを無理に使おうとすること自体が時間の無駄になる。データがJavaScriptの実行後にしか存在しない場合、つまりアクセス可能なAPIを持たず、クライアントサイドでコンテンツをレンダリングするシングルページアプリケーションの場合はヘッドレスブラウザを使うべきだ。データが対話を通じて組み立てられる場合、つまりスクロールやクリックによってのみ追加のデータを取得する無限スクロールと遅延読み込みのページネーションの場合も同様だ。ログインや多段階のフローが、使用可能なセッションを確立するためにクライアントサイドのスクリプトに依存している場合もブラウザが必要になる。そして、サイトが実際のブラウザコンテキストを積極的にチェックしている場合、つまりJavaScriptのチャレンジを実行したり、素のHTTPクライアントでは満たせないブラウザ固有のシグナルを検査したりしている場合もブラウザが必要だ。これらのケースでは、ブラウザはオーバーヘッドではなく、データを取得できる唯一の手段だ。

ブラウザ経路のコストを率直に述べる

ブラウザを使う場合は、何にコストを払っているかを把握しておくべきだ。最大の隠れたコストは帯域幅だ。ブラウザは、人間が見るのと同じようにページ全体、つまりHTMLに加えてすべての画像、スタイルシート、フォント、トラッカー、サードパーティのスクリプトを読み込む。これは、実際に欲しかった1つのHTML文書やJSONの塊のサイズの何倍にもなり得る。そのすべてのバイトがプロキシを経由する。対処法は、不要なリソースタイプ、画像、メディア、フォント、アナリティクスをブロックすることだ。そうすればブラウザはページ全体をダウンロードすることなく、データを生成するのに十分なレンダリングを行える。これによりブラウザ経路のプロキシ帯域幅を大幅に削減できる。2つ目のコストは速度だ。レンダリングは遅いため、ブラウザワーカーはHTTPワーカーに比べて1分あたりに収集できるページ数がはるかに少ない。またブラウザはメモリを大量に消費するため、それらを大量に稼働させることはHTTPリクエストを発行するよりも重いインフラを必要とする。3つ目のコストは多くのチームにとって意外なものだ。ヘッドレスブラウザは自動的にステルス性が高くなるわけではない。素の状態ではそれ自体に検出可能な特徴を伴っているため、素朴なヘッドレスの設定は、きちんと整形されたHTTPリクエストよりもむしろフラグを立てられやすいことがある。

ほとんどの人が飛ばしてしまう中間の道

「ブラウザが必要だ」という状況の多くは、実際には「本物らしく見えるリクエストが必要だ」という状況だ。完全なレンダリングにエスカレートする前に、正しく一貫したフィンガープリントを備えたプレーンなHTTPを試してみよう。完全で首尾一貫したヘッダー、適切なクッキー処理、そして一致するTLSとHTTP/2のフィンガープリントだ。というのも、ブラウザらしい複数のフィンガープリントの組み合わせを伴うリクエストは、素のクライアントではブロックされる場面を通過できることが多いからだ。これをブロックを回避するための一般的な規律と組み合わせれば、ブラウザを要求しているように見えた多くのページが、実際には整形されたHTTPリクエストではるかに低いコストで応じてくれることが分かる。データが他のどんな方法でも本当に得られない場合にのみ、ブラウザへとエスカレートすべきだ。

どちらにせよプロキシは必要

HTTPをブラウザより優先することは、クリーンなネットワークアイデンティティの必要性を変えるものではない。どちらの経路も、一般的な訪問者に見えるようにするためにレジデンシャルIPを経由する。変わるのは、それにいくら払うかだ。ブラウザは1ページあたりプロキシを通過させるデータ量がはるかに多いため、従量制のレジデンシャル帯域幅では、選んだツールがコストに直接影響する。レジデンシャルプロキシとそのGB単位の価格設定はどちらの手法でも根本的には同じものであり、だからこそ、機能する場面では軽いツールを選ぶという規律に価値があるのだ。

簡単な判断フロー

自動化のコードを1行書く前に、対象となる各サイトを同じ簡単なチェックにかけてみよう。

  1. データは最初のHTMLに含まれているか? HTTPを使う。
  2. ページはデータを返すJSONまたはXHRエンドポイントを呼び出しているか? そのエンドポイントをHTTPで呼び出す。
  3. コンテンツはJavaScriptの実行後にしか現れず、アクセス可能なAPIもないか? ヘッドレスブラウザを使う。
  4. データはスクロールやクリックを通じてのみ読み込まれるか? ヘッドレスブラウザを使う。
  5. 正しいデータ経路にもかかわらずブロックされているか? まずフィンガープリントとIPを修正し、それでも駄目な場合の最終手段としてブラウザを検討する。

実際には、view-sourceとネットワークパネルをさっと確認するだけで最初の2つの問いに答えが出ることが多く、この2つだけで大半の人が想定するよりも多くのサイトをカバーできる。レンダリングが必要な場合は、できるだけ軽く保とう。

# HTTP first: hit the underlying JSON endpoint the page already calls
import requests
PROXY = "http://customer-USERNAME-country-us:PASSWORD@p.shifter.io:443"
proxies = {"http": PROXY, "https": PROXY}
r = requests.get("https://shop.example.com/api/products?page=1",
proxies=proxies, timeout=15)
r.raise_for_status()
data = r.json() # structured data, no rendering, minimal bytes
# Only if rendering is truly required, run a browser through the same
# proxy and block heavy resource types so it does not pull the whole page:
# route.abort() on image / media / font / stylesheet requests
# before reading the rendered content.

結論

ヘッドレスブラウザは、クライアントサイドのレンダリングと本当に必要な対話に対しては正しいツールであり、それ以外のほとんどのウェブに対しては誤ったツールだ。何かを自動化する前に、データがHTMLに含まれているか、それともJSONエンドポイントの背後にあるかを確認し、ブラウザを立ち上げるよりも本物のフィンガープリントを備えた整形されたHTTPリクエストを優先し、レンダリングが必要な場合でも、不要なものはブロックして、わずかなフィールドのためにページ全体をダウンロードする対価を払わないようにしよう。どちらの経路もレジデンシャルIPを必要とするが、レコードごとにページ全体をプロキシに通すのはそのうちの一方だけだ。ブラウザは最初ではなく最後の手段とし、確実にデータを取得できる最も安上がりなツールを使うべきだ。

そのネットワーク層を提供しているのがレジデンシャルプロキシであり、プレーンなHTTPで取得する場合でも完全なブラウザを動かす場合でも同じように機能する、実在の家庭用IPからなる大規模なプールだ。GB単位の価格設定は、軽い経路の方が割に合う理由を物語っている。実際に必要なデータだけを、案件が要求するだけ多くの対象にわたって転送できるからだ。

始める準備はできていますか?

Shifterのレジデンシャルプロキシをお試しください。IP 205M+件、195+カ国、$0.75/GBから。

始める