ego (lite) はブラウザそのもの、ego は端末を横断して動くあなた専属のエージェントです。
順番待ちリストに参加する
WebスクレイピングJavaScriptNode.jsPlaywrightCheerioego (lite)

JavaScriptによるWebスクレイピング:静的HTML、レンダリングページ、Playwright

2026年9月15日13 分で読了
ドット絵の山々と花畑の上に浮かぶ青いブラウザの眼の上で、JSのブロックと喜劇・悲劇の仮面が釣り合っている様子

JavaScriptでのWebスクレイピングは、コードが間違っているからではなく、間違ったアクセス経路を選んだせいで失敗することが少なくありません。データが最初のHTMLに含まれているなら、Node.jsのfetchとHTMLパーサーで十分です。ブラウザが必要になるのは、データが現れる前にページがJavaScriptを実行したり、ページ送りやクリックなどの操作をしたりする必要がある場合だけです。これが静的HTMLとレンダリングページを分ける境界線です。

Playwrightは、あらかじめ分かっていて何度も繰り返すワークフローに向いています。ページを開き、要素を待ち、コントロールをクリックし、項目を抽出し、同じ手順をもう一度実行する、という流れです。問題は、ページ構造やページ送り、操作の流れが変わり、固定されたセレクタとアクションの並びが壊れ始めたときに起こります。

そこでより適しているのが、ego (lite) のようなエージェント駆動のブラウザです。元の手順がまだ存在すると決め打ちするのではなく、エージェントが現在レンダリングされているページを調べ、次に何をするかを判断し、遷移や動的な変化の後も安定して実行を続けられます。

JavaScriptスクレイパーの成否を決めるのは何か

結果を決めるのはアクセス経路です。同じ対象サイトでも、データが最初のHTMLレスポンスに含まれるか、それともブラウザで動くJavaScriptが後から取得して描画するかによって、HTTPで簡単に取得できる場合もあれば、HTTPではまったく見えない場合もあります。

したがって最初の作業はスクレイパーを書くことではありません。対象ページを開き、レンダリング後のDOMではなくソースを表示して、欲しい値が実際どこにあるのかを突き止めることです。このガイドの残りはすべて、その答えから導かれます。

対象サイトに必要なのは3つのアクセス経路のどれか

おおよそすべてのスクレイピング作業は3つの経路で片付き、コスト順に並べられます。静的HTMLが最も安く速い方法です。ページがすでに呼んでいるJSONエンドポイントは、多くの場合もっとも扱いやすいデータが得られます。実ブラウザは最も高機能で、CPU、メモリ、壊れやすさの面で最もコストがかかります。

経路できることできないこと
HTTPリクエスト + HTMLパーサー任意のURLを直接取得し、レスポンスボディを読み、返ってきたマークアップをクエリできます。プロセスあたり毎分数千ページを処理でき、ブラウザのバイナリも不要です。ページのスクリプト実行、クリック、スクロール、フォーム入力はできません。クライアントレンダリングのページでは、データがレスポンスに含まれていないため、空のシェルが返ります。
JSONエンドポイントを直接使うマークアップの解析なしで構造化データを返すため、ページのレイアウトが刷新されてもフィールド名は維持されます。ペイロードは最小で、解析も最速です。サイトの更新をまたいで安定し続けることはできません。こうしたエンドポイントは内部向けで文書化されておらず、予告なく変更されたり、リクエストを拒否し始めたりします。
実ブラウザの自動化ページのJavaScriptを実行し、コンテンツの表示を待ち、人が行うのと同じようにレンダリング結果を操作できます。安価にスケールすることはできません。ブラウザコンテキストごとに実際のメモリを消費し、それを多数並べるとHTTPループより多くのインフラが必要になります。
このガイドがスクレイピングするwebscraper.ioのノートPCカタログの隣に開かれた、laptop-researchという名前のego (lite) Space
第3の経路、すでに実行中。実際のブラウザSpaceの中でエージェントが作業し、右側には同じ対象カタログがあります。経路は選択であって既定ではなく、実行コストが最も高いのはこの経路です。

Node.jsで静的HTMLを取得して解析する方法

まずプラットフォームを使います。Node.jsはFetch APIをグローバルとして公開しているため、リクエストに依存パッケージは一切不要です。以下のパターンが第1の経路のすべてです。リクエストし、ステータスを確認し、テキストを読み、マークアップをパーサーに渡します。

リクエスト自体はプラットフォーム以外に何も必要としません。なぜなら、Fetch APIがNode.jsのグローバルとして同梱されているからです。つまり、素のGETにはインストールすべきHTTPライブラリはありません。

ステータス確認は、真っ先に省かれ、最も後悔される部分です。404やボットブロックのページもボディを返し、そのボディは問題なく解析できて一致する要素がゼロになります。これはセレクタのバグとまったく同じに見えます。

const res = await fetch(url, {
  headers: { "user-agent": "my-scraper/1.0 (+contact@example.com)" },
});

if (!res.ok) {
  throw new Error(`${res.status} ${res.statusText} for ${url}`);
}

const html = await res.text();

レート制限は後付けではなく、同じループの中に入れます。リクエスト間にawaitした待機を1回入れるだけで、小さなジョブは行儀よく保たれ、自分のアドレスがブロックリストに入るのを避けられます。

const sleep = (ms) => new Promise((r) => setTimeout(r, ms));

for (const url of urls) {
  const html = await getHtml(url);
  await parse(html);
  await sleep(1000);
}

第1の経路が実際に何を返すかを示します。以下の表は、公開されているノートPCのテストカタログに対して、素のHTTPリクエストとセレクタライブラリで得た実際の出力です。ブラウザもレンダリング工程もなく、3ページを3つの静的レスポンスとして取得しています。

ノートPCカタログに対して、組み込みのfetch APIとCheerioを使うNode.jsスクリプトを実行しているターミナル。ベースURL、$500の価格上限、?page=Nでのページ送り確認、商品URLをキーにした重複排除の判断が表示されている
第1の経路を最初から最後まで。Node組み込みのfetchとCheerioを使い、ブラウザ自動化も、インストール済みのaxiosも使っていません。ページ送りは単純な?page=パラメータで、重複排除は表示名ではなくURLをキーにしています。
ID名前価格仕様レビュー
32Aspire E1-510$306.9915.6", Pentium N3520 2.16GHz, 4GB, 500GB, Linux2
45Asus VivoBook Max$39915.6" HD, Pentium N4200 1.1GHz, 4GB, 500GB, Windows 10 Home4
31Packard 255 G2$416.9915.6", AMD E2-3800 1.3GHz, 4GB, 500GB, Windows 8.12
46Dell Vostro 15$488.7815.6" FHD, Core i5-7200U, 4GB, 128GB SSD, Radeon R5 M420 2GB, Linux14

18製品のうち4製品が500ドル未満です。これがこのカタログに対する第1の経路の結果のすべてで、リクエストは3回、レンダリングなし、ブラウザプロセスなしです。そしてここからが正直な話です。この表には、読者が当然あると思うはずのものが欠けています。

Cheerio、DOMParser、jsdomのどれを使うべきか

この3つは、互換性のあるライブラリであるかのように比較されます。しかし違います。約束していることが異なるからです。2つはクエリ用にマークアップを解析し、1つはスクリプト実行を伴うDOMを実装します。

このガイドが主に使うパーサーのドキュメントはcheerio.js.orgにあり、Cheerioはページのスクリプトを実行するのではなく、マークアップを解析してクエリするものだと明言しています。

20ページにわたる117製品のカタログについてのターミナルレポート。続けて、フラグが立った2つのパースの罠と、セマンティックなmicrodataセレクタおよび?page=のページ送り方式に関する実装メモが示されている
実際の出力に見える2つの罠。表示名ThinkPad Yogaは別々の2台のマシンで使い回されているため、重複排除は製品IDをキーにする必要があり、また2つの製品名はサイト自身のCSSで切り詰められ、完全な値はリンクのtitle属性にしかありません。
選択肢できることできないこと
CheerioHTML文字列を高速に解析し、jQueryスタイルのセレクタでクエリできます。依存が小さく、ブラウザも不要で、レスポンスボディから数百のフィールドを取り出すのに最適です。ページのスクリプト実行、コンポーネントのレンダリング、レイアウトの解決はできません。マークアップを解析するだけで、ブラウザのように振る舞うことはありません。
jsdomdocument、window、スクリプト実行を備えたDOM実装をNode.js上で提供するため、ブラウザAPI向けに書かれたコードがそのまま動きます。レンダリングや忠実さの面で実ブラウザに匹敵することはできず、1ページあたりの負荷ははるかに大きくなります。DOMの代替であり、Chromeではありません。
DOMParser組み込みのブラウザAPIを使って文字列をクエリ可能なドキュメントに変換します。プロジェクトに依存パッケージを一切追加せずに済みます。awaitすることはできません。同期的でブロッキングであり、Node.jsではごく最近のバージョンでようやくグローバルになりました。

Cheerioからの読み取りには見慣れたセレクタAPIを使います。抽出したテキストは境界でtrimしている点に注目してください。スクレイピングしたマークアップにはインデントや改行が含まれ、そのままではデータセットに現れてしまうからです。

import * as cheerio from "cheerio";

const $ = cheerio.load(html);
const items = $(".product-card").map((i, el) => ({
  name: $(el).find(".name").text().trim(),
  price: $(el).find(".price").text().trim(),
})).get();

同じ抽出をDOMParserで書くと次のようになります。このグローバルが存在する環境でしか動きません。

const doc = new DOMParser().parseFromString(html, "text/html");
const rows = [...doc.querySelectorAll("table tbody tr")].map((tr) => ({
  cells: [...tr.querySelectorAll("td")].map((td) => td.textContent.trim()),
}));

ページがすでに使っているJSONエンドポイントの見つけ方

セレクタを1つ書く前に、ブラウザのネットワークパネルを開き、fetchとXHRで絞り込み、ページを再読み込みして、何が返ってきたかを見ます。データ駆動型のサイトの多くは、表示されているページを少数のJSONレスポンスから組み立てており、マークアップよりはるかに扱いやすいものです。

見つけたら、そのリクエストには通常ページが送ったのと同じヘッダーが必要で、セッションCookieが要ることもあります。手作業で組み立て直すのではなく、ネットワークパネルのcopy-as-fetch出力で再現しましょう。

const res = await fetch("https://example.com/api/listings?page=1", {
  headers: { accept: "application/json" },
});

if (!res.ok) throw new Error(`${res.status} for listings page 1`);

const { items } = await res.json();

クライアントレンダリングのページが空のシェルを返す理由

クライアントレンダリングのページは、ほとんど中身のないマークアップを送ります。最初のレスポンスにはルート要素、スクリプトの束、場合によってはローディング状態が入っています。人が画面で見るテキストは、レスポンスが届いた後にJavaScriptが生成するため、レスポンスを読むだけのHTTPリクエストには読むものがありません。

これは不思議な現象ではなく、診断できます。ほとんどのケースは2つの確認で見つかります。レスポンス内の可視テキストがブラウザの表示のごく一部しかないこと、そしてマークアップの大部分がscriptタグであることです。

const text = html.replace(/<script[\s\S]*?<\/script>/g, "").replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();

console.log({
  textLength: text.length,
  scriptCount: (html.match(/<script\b/g) ?? []).length,
  hasRoot: /id="(root|app|__next)"/.test(html),
});

テキストが短く、スクリプトが多く、ルートのdivが空であれば、正直な答えは第3の経路です。逆にscriptタグがまったくなくテキストが数十文字しかない場合は、もっと単純な理由がほとんどです。リクエストがブロックされたか、URLを間違えています。

実際の違いは次のとおりです。

HTTPレスポンスに現れるシグナル通常それが意味するもの次の一手
充実したコンテンツと本物のマークアップサーバーがページをレンダリングしています。他に必要なものはありません。セレクタライブラリで解析します。
ルートdivと多数のスクリプトクライアントサイドレンダリング。コンテンツはレスポンスの後に届きます。JSONエンドポイントを探すか、ページをレンダリングします。
ごく短いテキスト、スクリプトなしブロック、リダイレクト、あるいは完全に誤ったURLです。パースの前に、ステータス、最終URL、ヘッダーをログに残します。

Playwrightで実ブラウザのページをスクレイピングする仕組み

Playwrightは実ブラウザを動かすため、ページは訪問者に対するのとまったく同じように動作します。スクレイピングの形は多くの人が思うより小さく、コンテキストを開き、URLへ移動し、必要なものだけを待ち、それを読み出すだけです。

ここで使うAPIのドキュメントはplaywright.devにまとまっており、ブラウザ、コンテキスト、locatorを起動するための正典的なリファレンスです。

実際のChromiumウィンドウで対象ページを開くPlaywrightの実行。それを動かす命令は左側のターミナルに表示されている
同じ対象での第3の経路。Playwrightが開いた実際のブラウザです。追加コストで得られるのはスクリプト実行とレンダリング済みのDOMで、これはクライアントレンダリングのページが必要とするものであり、fetchだけではできないことです。

以下の取得パターンでは、セレクタを待ってからpage.evaluateで抽出します。この関数はページ内で実行され、シリアライズ可能な結果を返します。

import { chromium } from "playwright";

const browser = await chromium.launch();
const context = await browser.newContext();

try {
  const page = await context.newPage();
  await page.goto(url, { waitUntil: "domcontentloaded" });
  await page.waitForSelector(".product-card");

  const rows = await page.evaluate(() =>
    [...document.querySelectorAll(".product-card")].map((el) => ({
      name: el.querySelector(".name")?.textContent?.trim() ?? null,
      price: el.querySelector(".price")?.textContent?.trim() ?? null,
    })),
  );

  console.log(rows);
} finally {
  // contexts hold the memory; close it even when the scrape throws
  await context.close();
  await browser.close();
}

セレクタより重要なライフサイクルの詳細が2つあります。1つ目は、コンテキストが安価で使い捨てできる単位であることです。1つのブラウザで複数の分離された実行を処理でき、それぞれがcloseで終わります。2つ目は、ページ上でのテキスト抽出はレンダリングされた値ではなくテキストノードを返すことです。CSSで隠されたコンテンツもDOMには残るため、出力にも現れます。

対象がリスト全体ではなく特定の要素である場合、locatorのほうが取得経路としてすっきりしています。Playwrightのlocatorのドキュメントには、ボタン、リンク、入力欄にはクリックの待機が不要だと記されており、すべての操作を明示的な待機で包む前に思い出しておく価値があります。

const title = await page.getByRole("heading", { level: 1 }).innerText();
const price = await page.locator("[data-testid=price]").innerText();

セッション、ブロックのリスク、CAPTCHAで計画はどう変わるか

対象にログインが必要になった瞬間、スクレイパーはデータ処理ではなくセッション管理の問題になります。Playwrightはこれを直接サポートしています。1回認証し、ブラウザのストレージ状態をファイルに保存し、毎回認証情報の入力をスクリプト化する代わりに以降の実行で再利用します。

// once, interactively
await context.storageState({ path: "auth.json" });

// later runs
const context = await browser.newContext({ storageState: "auth.json" });

そこから運用上の事実が2つ導かれます。保存したセッション状態は資格情報なので、リポジトリではなくシークレットストアに置くべきです。また保存したセッションは期限切れになるため、突然ログインページを返し始めた実行は、セレクタではなくセッションの問題です。

その状態を起動をまたいで生かし続けることは、それ自体がひとつのテーマです。エージェント実行をまたいだ永続ブラウザセッションで詳しく解説しています。

自動化されたトラフィック全般については、3つの制約がスクレイピングが成立するか無駄な戦いになるかを決めます。サイトのrobots指令と規約が何を許すか、サイトが公表または許容するレートはどれくらいか、返ってくるレスポンスがコンテンツなのかチャレンジページなのか、です。これらはコードを書く前に決着させる方針の問題で、詳しくは次のガイドで扱っています。ログインの壁の内側をスクレイピングする

本番環境でJavaScriptスクレイパーが壊れる原因

スクレイパーが失敗するのは、セレクタが間違っていたからではありません。2回目の実行、100本目のURLで、ページが遅い、レスポンスがリダイレクト、サイトがスロットリングを始めた、といったときに壊れます。対策は地味で、具体的です。

async function getWithRetry(url, attempt = 0) {
  const res = await fetch(url);
  if (res.status === 429 || res.status >= 500) {
    if (attempt >= 3) throw new Error(`giving up on ${url}`);
    const retryAfter = Number(res.headers.get("retry-after"));
    const waitMs = Number.isFinite(retryAfter)
      ? retryAfter * 1000
      : 2 ** attempt * 1000;
    await new Promise((r) => setTimeout(r, waitMs));
    return getWithRetry(url, attempt + 1);
  }
  if (!res.ok) throw new Error(`${res.status} for ${url}`);
  return res.text();
}

2つ目の罠は並行性です。1台のマシンで10個のブラウザコンテキストを並行させるのは、ほぼ同じCPUを取り合うことになり、スループットの向上はメモリのコストに見合わず、サイトから見れば少しずつではなく一気にアクセスが集中することになります。まずは逐次処理で始めて計測し、対象が耐えられる場合にだけ数を増やします。

3つ目は、約束のないエンドポイントを読むスクレイパーにはフォールバックが必要だということです。表示ページをセレクタで解析するコードをコードベースに残し、JSON呼び出しが失敗したらそこへ流すようにします。そうすれば、上流の静かな変更で実行が空になるのではなく、劣化で済みます。

ページ2と3がページ1と同じ古いレコードを返しているターミナル。待機条件がコンテンツではなくactive-stateクラスに付けられていたためです。
2ページ目でだけ現れる不具合。待機がコンテンツではなくclassの変化をキーにしていたため、ページ2と3がページ1の行を返してしまいます。例外は何も起きず、データは正しく見えます。

実ブラウザが本当に必要なのはどんなときか

実ブラウザが正解になるのは、ブラウザにしか提供できないものが必要なときです。自分のマシンにすでにある認証済みセッション、操作の後に初めて現れるコンテンツ、途中で人が介入する必要がある流れ、取得するのではなく起きている最中に見守らなければならない結果などです。それ以外のケースでは、パーサー付きのHTTPのほうが速く、安く、動かし続けるのも簡単です。

ヘッドレスブラウザと実ブラウザのトレードオフは、AIエージェント向けのヘッドレスブラウザと実ブラウザの比較

そうした状況では、タスク駆動型のブラウザエージェントを導入する価値が出てきます。ego (lite) は、エージェント駆動の作業のために作られたブラウザです。目的を伝えると、実ブラウザ上で動作し、すでに開いているログイン済みセッションも利用できます。人間の判断が必要なステップでは、目に見えるインターフェースから操作を引き継げます。実ログイン状態、動的なページ、目に見える実行、人への引き継ぎが必要なスクレイピング作業では、前述のセッション接続の手間がなくなります。Playwrightの代替ではなく、すべてのサイトを保証するものでもありません。チャレンジで応答するページや自動アクセスを禁じているページは、他のどの経路と同じように対象外です。素のHTTPリクエストや公式APIですでに必要なものが得られるなら、ブラウザエージェントを足すと作業が遅くなるだけです。

ブラウザが本当に答えになった後のブラウザツールをより深く比較したい場合は、PlaywrightとPuppeteerのスクレイピング比較でライブラリの選定そのものを扱い、AI Webスクレイパーのワークフローでは、スクレイパーのパイプラインにエージェントがどこで関わるかを扱っています。

主な課題と制限事項

この枠組みのどの経路にも、エンジニアリングでは取り除けない故障の形があります。それを事前に知っているかどうかが、1年動くスクレイパーと1週間で止まるスクレイパーを分けます。

静的解析は、サイトがマークアップを作り替えたときに壊れます。気づく手段がないため、完全にクラッシュするより、フィールドが黙ってnullになることのほうが多いのです。パイプラインを信じるのではなく、実行のたびにサンプルを検証しましょう。

内部JSONエンドポイントはまったく予告なく壊れ、どのサイトでも最も契約性の低い部分です。今日の成功は、来月の証拠にはなりません。

ブラウザ自動化は最も現実的で、大規模では最も壊れやすい方法です。メモリは並行数とともに増え、セッションは期限切れになり、アンチボットシステムは意図ではなくパターンに反応します。そのため、ノートPCでうまくいく手法がデータセンターでは通用しないことがあります。

そして最大の制限は技術的なものではありません。何を収集してよいか、どのくらいの頻度でよいか、集めたものをどう扱ってよいかは、サイトの規約、robots指令、そしてあなたの法域の法律が決めます。コードが動くからといって、それが変わることはありません。

ここまでの話から導かれるトラブルシューティングの手順は短いです。スクレイピングが何も返さないときは、まずステータスコードを確認し、次にコンテンツがそもそもレスポンスに入っているかを確認し、それからセレクタがソースではなくレンダリング後のDOMに一致しているかを確認します。ブラウザを検討するのは、この3つを確認した後です。

よくある質問

Node.jsでHTTPリクエストを送るのにライブラリは必要ですか

いいえ。Node.jsはFetch APIをグローバルとして公開しているため、何もインストールせずにfetchが使え、responseオブジェクトとそのok、status、text()メンバーも利用できます。必要なのはパーサーです。fetchは文字列を返し、HTMLに対する文字列マッチングはマークアップが変わった瞬間に壊れてしまうからです。

ブラウザでは問題なく表示されるページなのに、スクレイパーが空のリストを返すのはなぜですか

最も可能性が高い原因は、ページがクライアントレンダリングで、データがHTTPレスポンスに含まれていないことです。生のレスポンス内の可視テキストとブラウザの表示を比べ、コンテンツに対するscriptタグの数を数えて確認します。レスポンスがシェルなら、サイトのJSONエンドポイントへ移るか、実ブラウザでページをレンダリングします。

Cheerioはヘッドレスブラウザの代替になりますか

いいえ。CheerioはHTMLを解析し、セレクタでクエリできるようにするだけです。JavaScriptを実行しないため、読み込み後にページが生成するコンテンツは得られません。第1の経路には適したツールで、第3の経路には不向きです。Cheerioで足りる場面でブラウザに手を伸ばすのは、スクレイピングコードで最もよくある無駄なコストです。

ページがサーバーレンダリングかクライアントレンダリングかはどう見分けますか

URLにリクエストを送り、レンダリング後のDOMではなく生のレスポンスを見ます。欲しい値がレスポンスボディにあればサーバーレンダリングで、安い経路が使えます。ボディにルート要素とスクリプトの束があり、テキストが少なければ、コンテンツはブラウザ側で組み立てられています。

ログインが必要なページはどうスクレイピングしますか

ブラウザコンテキストで1回ログインし、ストレージ状態をファイルに保存して、以降の実行でその状態を読み込みます。ファイルはシークレットとして扱い、期限切れを前提にし、使用を許可されているセッションを使うようにします。対象がCAPTCHAや所有権確認の回避を要求するなら、止まって公式の経路を使ってください。

スクレイピングにはPlaywrightとPuppeteerのどちらが適していますか

どちらも実ブラウザを動かし、同じページをスクレイピングできます。判断のポイントはアクセス経路ではなく、locatorの対応、待機の挙動、言語バインディングといったライブラリの詳細で、次の記事で扱っています。PlaywrightとPuppeteerの比較。どちらを選ぶにしても、この記事の経路の判断が先です。

一度に何ページまでスクレイピングできますか

まず逐次処理で始め、計測してから並行数を増やします。HTTPリクエストはブラウザコンテキストよりはるかに安くスケールし、1台のマシンでブラウザを並行させるのは同じCPUを取り合うだけで、対象サイトには一気にトラフィックが集中します。HTTPスクレイピングなら、数十本より、待機を入れて同時4〜8本にするのが安全な出発点です。

429レスポンスが返ってきたときはどうすればよいですか

Retry-Afterヘッダーを読み、少なくともその時間だけ待ってから、小さな上限まで指数バックオフで再試行し、それを超えたら大きな失敗として扱います。429はレートのシグナルであり、短い間隔のリトライループで打ち破るべきエラーではありません。これを無視すると、アドレスがブロックリストに入ってしまいます。

スクレイピングは合法ですか

サイト、データ、法域、そして結果をどう使うかによります。robots指令と利用規約がサイトの許可する範囲を示し、個人データやデータベースの権利に関するルールは国ごとに異なります。この記事は法的助言ではありません。大規模に収集する前に、規約と適用法を確認してください。

スクレイピングではなく公式APIを使うべきなのはどんなときですか

必要なフィールドを網羅する公式APIが存在するなら、いつでもそちらです。文書化されたAPIは安定した契約で、通常は明示的なレート制限があり、ページレイアウトが変わっても壊れません。スクレイピングは、対応するアクセス経路のないブラウザ公開データのためのフォールバックであり、既定の手段ではありません。

スクレイピングにブラウザエージェントは必要ですか

実ログイン状態、操作後に現れるコンテンツ、目に見える実行、途中での人による引き継ぎが必要なタスクに限られます。コンテンツをHTTPで返すページや、公式APIのあるサイトでは、ブラウザエージェントは能力を足さずにコストだけを増やします。

本当に必要としているスクレイピング作業でブラウザエージェントの経路を試したいなら、ego (lite) は無料でダウンロードできます。また、価格スクレイパーSERPスクレイパーのページで、2つの具体的な作業を最初から最後まで解説しています。