Webスクレイピングの実務ガイド|法規制・robots.txt・ToS・個人情報の境界線

Webスクレイピング robots.txt 個人情報保護法 コンプライアンス Web開発
結論

スクレイピングの可否は「技術的に取得できるか」ではなく、robots.txt・利用規約(ToS)・著作権・個人情報保護法の4軸で決まる。公式APIを最優先し、取得は識別可能なUser-Agent・低頻度・最小限のデータで行う。429・CAPTCHA・WAF遮断は「止まれ」の信号であり、技術的回避の前に Anti-Bot対策記事 で防御の意味を理解したうえで、グレーゾーンは実装前に法務へ相談する。

スクレイピングと法務の全体像

Webスクレイピングとは、HTTPでHTML・JSON・RSSなどを取得し、必要なフィールドを抽出・正規化・保存する一連の処理を指す。価格監視、SEO分析、研究用データセット、競合調査、機械学習の教師データ作成など、ビジネス上の需要は大きい。

一方で、取得先のサーバー負荷、サイト運営者の意図に反する利用、著作物の無断複製、個人のプライバシー侵害といったリスクも常に付きまとう。「公開ページだから自由」という前提は成り立たない。エンジニアが最初に押さえるべき論点は次の4つだ。

論点主な問い典型的なリスク
robots.txtクロール禁止パスはどこかToS違反・信頼関係の毀損・ブロック
利用規約(ToS)自動取得・再配布は許可されているか差止・損害賠償・アカウント停止
著作権・不正競争複製・翻案・公衆送信に当たるか侵害警告・訴訟
個人情報保護法個人データの取得・利用・第三者提供は適法か行政指導・罰則・信用失墜

技術チームは「実装できるか」より先に「何を・なぜ・どこまで・いつまで」を1枚の設計メモに書き出す。後から「知らなかった」では済まされない場面が多い。

法務と技術の役割分担

担当判断すること判断しないこと
エンジニアrobots.txt パース、レート制限、429停止、取得フィールドの最小化個別案件の刑事・民事責任の最終判断
法務・コンプライアンスToS解釈、APPI適用、契約・ライセンス交渉DOMセレクタのメンテナンス
プロダクト取得の事業必要性、API vs スクレイピングのコストWAF突破の実装方針
この記事は法律助言ではない

以下はエンジニア向けの実務整理であり、個別案件の法的判断は弁護士・社内法務に委ねること。国・州・業界ごとに法制度は異なる。

robots.txtの読み方とパース実装

robots.txt はサイトルート(https://example.com/robots.txt)に置かれるプレーンテキストで、クローラーへのクロール方針を伝える仕組みだ。RFC 9309 で標準化されており、Googlebot など主要クローラーはこれを尊重する。

ただし重要なのは、robots.txt は法的拘束力そのものではない点だ。Disallow されたURLにアクセスしても自動的に刑事罰が課されるわけではない。逆に Allow されていても、ToS・著作権・個人情報の問題は残る。スクレイパー側は「マナー」として尊重し、禁止パスへは入らない実装を標準とする。

記述例と意味

例1:管理画面とAPIの拒否

User-agent: *
Disallow: /admin/
Disallow: /api/private/
Allow: /api/public/docs/

Sitemap: https://example.com/sitemap.xml
  • User-agent: * — すべてのクローラーが対象
  • Disallow: /admin//admin/ 以下はクロールしないでほしい
  • Allow: — より具体的なパスで Disallow を上書き(/api/public/docs/ は許可)
  • Sitemap: — サイトマップの場所(クロール可否とは別のヒント)

例2:特定ボットだけ全面拒否

User-agent: GPTBot
Disallow: /

User-agent: *
Disallow: /checkout/
Crawl-delay: 2
  • ボット名ごとに方針を分けられる(GPTBotGooglebot など)
  • Crawl-delay は非標準だが、一部クローラーがリクエスト間隔の目安として参照する

例3:ワイルドカードとクエリ文字列(Google拡張)

User-agent: *
Disallow: /*?*sessionid=
Disallow: /search?
Allow: /search?type=product$

パス末尾の $ は「ここで終わる」という Google 独自のマッチ。実装ライブラリによって解釈が異なるため、本番前に対象サイトの robots.txt を実際にパースしてテストする。

Python:標準ライブラリでパース

from urllib.parse import urlparse
from urllib.robotparser import RobotFileParser

def can_fetch(url: str, user_agent: str = "MyResearchBot/1.0") -> bool:
    parsed = urlparse(url)
    robots_url = f"{parsed.scheme}://{parsed.netloc}/robots.txt"

    rp = RobotFileParser()
    rp.set_url(robots_url)
    rp.read()  # ネットワーク取得。キャッシュは自前で層を足す

    return rp.can_fetch(user_agent, url)

# 使用例
target = "https://example.com/products/123"
if can_fetch(target):
    print("取得候補")
else:
    print("robots.txt により取得をスキップ")

RobotFileParser はシンプルだが、キャッシュTTL・リダイレクト・HTTPエラー時の扱いは自前実装が必要だ。robots.txt が 5xx を返した場合の方針(取得中止 vs 制限なしとみなす)はチームで決めておく。

Python:TTL付きキャッシュと取得前チェック

import time
from urllib.parse import urlparse
from urllib.robotparser import RobotFileParser

class RobotsCache:
    """ホストごとに RobotFileParser をキャッシュ(TTL簡略版)"""

    def __init__(self, ttl_seconds: float = 3600):
        self._cache: dict[str, tuple[RobotFileParser, float]] = {}
        self._ttl = ttl_seconds

    def allowed(self, url: str, ua: str) -> bool:
        host = urlparse(url).netloc
        now = time.monotonic()
        entry = self._cache.get(host)
        if entry is None or now - entry[1] > self._ttl:
            rp = RobotFileParser()
            scheme = urlparse(url).scheme or "https"
            rp.set_url(f"{scheme}://{host}/robots.txt")
            try:
                rp.read()
            except OSError:
                return False  # 読めないときは保守的に拒否
            self._cache[host] = (rp, now)
            entry = self._cache[host]
        return entry[0].can_fetch(ua, url)

Node.js:robots-parser の例

import robotsParser from "robots-parser";
import fetch from "node-fetch";

async function isAllowed(url, userAgent = "MyResearchBot/1.0") {
  const { origin } = new URL(url);
  const res = await fetch(`${origin}/robots.txt`);
  const body = await res.text();
  const robots = robotsParser(`${origin}/robots.txt`, body);
  return robots.isAllowed(url, userAgent) ?? true;
}

robots.txt パースで落としがちな罠

  • User-agent の不一致MyBot/1.0can_fetch しているのに、実際の HTTP リクエストは python-requests/2.x だと、運営者から見て「別ボット」になる
  • Disallow パスの部分一致/private/private-info にもマッチするかはパーサー実装依存
  • robots.txt 未更新 — 本番デプロイ後に Disallow が追加されても、キャッシュTTLが長いと禁止パスへアクセスし続ける
  • サブドメイン単位www.example.comapi.example.com は別ファイル。ホストごとに取得が必要
robots.txt だけでは足りない

Disallow は「クロールしてほしくない」という申し出であり、認証なしの秘密保持手段ではない。/secret/ を Disallow にしてもURLが漏れれば誰でもアクセスできる。サイト運営者は robots.txt に頼らず認証・noindex・WAFで守るべきだ。

利用規約(ToS)違反が問題になるケース

多くのWebサービスは利用規約で自動アクセス・スクレイピング・データの再配布・商用利用を明示的に禁止している。「ブラウザで見える=利用規約上も許可されている」ではない。ログイン後のダッシュボード、検索結果、レビュー一覧も、ToS上は自動取得が禁じられていることがほとんんだ。

典型的なToS条項

  • ロボット・スパイダー・クローラーによるアクセス禁止
  • コンテンツの複製・改変・再配布・派生データセットの販売禁止
  • APIキーの共有禁止、レート制限の迂回禁止
  • CAPTCHA・技術的保護手段の回避禁止
  • 競合サービス・モデル学習への利用禁止

違反が直ちに刑事事件になるとは限らないが、民事上の損害賠償・差止命令・アカウント永久停止・IPブロックは現実的な制裁だ。B2Bでデータを商品化する場合、契約・ライセンス条項の精査は必須になる。

ToS違反の具体例(パターン別)

パターン典型的な行為想定される制裁
明示禁止の迂回ToSで「自動取得禁止」とあるECサイトの価格を毎時クロールアカウント停止・IPブロック・損害賠償請求
API迂回無料APIの1日1000件制限を、HTMLスクレイピングで突破ToS違反・契約解除・差止
CAPTCHA突破reCAPTCHA表示後、突破サービスで継続取得ToS + CAPTCHA提供者ToS違反。CFAA/不正アクセスの論点も
Cookie流用ログインセッションCookieをスクリプトに埋め込み会員限定データ取得アカウント規約違反・不正アクセス
再配布・学習利用レビュー全文をCSV化し社外販売・LLM学習に提供著作権・ToS・APPIの複合リスク
競合分析転職サイトの求人・年収データを社内DBに蓄積不正競争・ToS違反で警告・訴訟に至った報道例あり

海外・国内で議論になった事例(整理)

事例・論点概要エンジニアへの示唆
hiQ Labs v. LinkedIn(米国)公開プロフィールのスクレイピングを LinkedIn が制止。CFAA(不正アクセス法)適用を巡る争い「公開」と「ToS上の自動取得禁止」は別。サイト側は技術・契約の両面で防御する
Meta v. Bright Data(米国)公開データの取得を巡るToS・CFAA論点公開ページでもToS・技術的防御との組み合わせで争点化
Ryanair 等(EU)航空券価格のスクレイピングを ToS・DB権で争った判例群価格・スケジュールも「データベースの抽出」で問題になりうる
国内:転職・求人・口コミサイト利用規約違反・不正競争で警告・訴訟に至った報道例あり競合分析目的でも「社内利用」は免責にならない
SNS・マーケットプレイスボット検知・API制限・法的通知によるアカウント停止が日常化API・パートナープログラムが用意されているサービスほど、迂回はリスクが高い

技術的に取得できた事実は、ToS違反の抗弁にはならない。「止められなかったから許された」ではなく「許可された範囲だけ取る」のがプロの前提だ。

米国CFAAと日本法の比較:不正アクセスの線引き

越境サービスや米国サーバー上のデータを扱う案件では、米国 Computer Fraud and Abuse Act(CFAA) が議論に上がる。日本の不正アクセス禁止法と「似ているが同じではない」点を理解しておく。

制度の概要

観点米国 CFAA(18 U.S.C. § 1030)日本 不正アクセス禁止法
対象コンピュータ(広義)への不正アクセス・超過権限利用アクセス制御機能を突破した行為
「公開」の扱いhiQ v. LinkedIn 等で「ToS違反=CFAA」論点が争われた(2022年最高裁は一定限界を示唆)公開ページの polite 取得と、CAPTCHA/WAF突破は別評価
典型例認証突破、権限外データ取得、内部API総当たりCAPTCHA回避、漏洩認証情報でのログイン、保護機能の意図的回避
民事・刑事刑事罰+民事損害賠償刑事罰(不正アクセス罪等)+損害賠償請求
ToS違反単独判例上、ToS違反だけでは不十分という方向性もToS違反は主に民事(契約)・別法令で評価

エンジニア向けの線引き表

行為 CFAA / 日本法上のリスク感(一般論・個別相談要)
公開ページを低頻度・robots遵守で取得 CFAA: 争点になりにくい方向。日本: ToS・著作権で別評価。429なら停止
ToS禁止サイトをWAF突破で取得 CFAA: 超過アクセス論点。日本: 不正アクセス・ToS民事リスク
CAPTCHA突破サービス利用 技術的保護回避。CFAA・不正アクセス・ToSの複合
漏洩パスワードでログイン 典型的な不正アクセス(日米とも高リスク)
内部API(/api/internal)を総当たり アクセス制御突破。刑事・民事とも高リスク
429無視・IPローテーションで継続 CFAA直接よりToS・損害賠償・永久ブロックが現実的

hiQ Labs v. LinkedIn から学ぶこと

LinkedIn は hiQ Labs の公開プロフィール取得を CFAA 違反として制止しようとした。争いは「ToSで禁止された公開データへのアクセスが CFAA の『不正アクセス』に当たるか」が焦点だった。2022年米最高裁は、権限内アクセスの定義について一定の限界を示し、ToS違反だけを自動的に CFAA 犯罪とみなす道は狭まった方向と言われる。

ただし「CFAAの心配が減った=スクレイピング自由」ではない。LinkedIn は ToS・差止・技術的防御(Anti-Bot)で対抗し続けている。エンジニアは CFAA を知ったうえで、ToS・robots.txt・429停止を実務の第一防衛線に据えるべきだ。

日本の個人情報保護法(APPI)とスクレイピング

日本の個人情報保護法(APPI)は、生存する個人に関する情報で、特定の個人を識別できるもの(個人情報)、および個人情報データベース等を構成する個人データ保有個人データを規律する。2022年改正以降、漏えい報告義務仮名加工・匿名加工の枠組みも実務に直結する。

スクレイピングで扱いやすいデータ例

  • SNSの表示名・プロフィール文・投稿内容・フォロー関係
  • 掲示板のハンドルネーム・投稿日時・IPが推測できるログ
  • レビューサイトのユーザーID・購入履歴に紐づくコメント
  • 不動産・求人サイトに掲載された担当者名・電話番号

APPI上の実務ポイント

1. 利用目的の特定と公表 — 個人データを事業で取得・利用するなら、何のために使うかを特定し、原則として本人が知り得る状態(プライバシーポリシー等)に置く。社内分析だけでも、法人として取り扱うなら該当しうる。

2. 要配慮個人情報 — 人種、信条、病歴、犯罪経歴などは原則として取得・利用・第三者提供に同意が必要。プロフィールや投稿から推測できる場合も、設計段階で除外・マスキングを検討する。

3. 第三者提供・共同利用 — スクレイプした個人データをそのまま別会社に渡す、クラウド上の学習用に再配布するなどは第三者提供に当たりうる。契約・匿名化・統計化の要否を法務と確認する。

4. 仮名加工情報・匿名加工情報 — 一定の手続を踏めば、分析・AI学習に使いやすい形にできるが、復元可能性・再識別リスクの評価が必要。「ハッシュしたから個人情報ではない」は単純には成り立たない。

5. 国外移転 — 海外サーバーへ保存する、OpenAI等の国外APIに渡す場合は、外国にある第三者への提供のルール(同意・十分な体制等)を確認する。

6. 漏えい報告 — 個人データの漏えい等が一定規模に達すると、個人情報保護委員会への報告と本人通知が義務化されている。

個人情報を含みうるかの判定フロー

1

取得フィールド一覧を書き出し、氏名・メール・電話・住所・ユーザーID・位置情報・顔画像の有無を確認する

2

他のデータと組み合わせて特定個人を識別できるか(リンク可能性)を評価する

3

利用目的・保存期間・削除手順をドキュメント化し、不要フィールドは取得段階で落とす

4

第三者提供・国外移転・AI学習利用の有無を法務とすり合わせる

5

仮名化・匿名化が必要なら、復元攻撃を想定した設計レビューを行う

公開=自由利用、ではない

インターネット上に表示されていても、投稿者の著作権・肖像権・プライバシーは残る。研究・AI学習向けデータセットでも、近年はガイドラインと規制が強まっている。必要最小限・匿名化・保存期限をコードとポリシーの両方で実装する。

著作権・不正競争防止法

著作権法

Webページ上の文章、写真、イラスト、動画、レイアウト、場合によってはデータベースの構成(データベースの著作物)も著作権で保護される。スクレイピング結果をそのまま再公開・販売・学習データとして再配布すると、複製権・翻案権・公衆送信権の侵害が問題になる。

一方、事実のみ(商品価格、気温、株価の数値、営業時間)や、独自の集計・ランキングロジックは別評価になりうる。境界は案件依存のため、生HTMLの丸ごと保存は避け、必要最小限のフィールドを正規化して保存する設計が無難だ。

不正競争防止法

営業秘密や、相当の施行を伴う顧客リストなど、限定公開・技術的保護されたデータを無断取得・利用すると、不正競争防止法(第2条第1項各号)の問題になりうる。ログイン後のみ見える卸価格、会員限定の在庫情報は特に注意。

保存・利用の実務指針

  • 生HTMLアーカイブ — 監査・デバッグ用に短期保持するならアクセス制限。長期一括保存は著作権リスク
  • 正規化フィールド — 価格・SKU・在庫数など事実データに限定
  • 出典・取得日時 — 後追い説明と削除要求への対応用にメタデータを残す
  • 再配布 — 社外提供・API公開前に法務レビュー

公式APIとスクレイピングの意思決定マトリクス

同じデータでも、公式API・データフィード・パートナープログラムがあれば、そちらを第一選択にする。HTMLスクレイピングはDOM変更に弱く、メンテナンスコストも高い。

観点 HTMLスクレイピング 公式API
ToS・法務リスク 多くのサイトで明示禁止。グレーゾーンを踏みやすい 利用条件が明文化。キー発行で契約関係が成立しやすい
安定性 CSSセレクタ・DOM構造変更で即壊れる スキーマ変更が changelog で通知されることが多い
レート制限 暗黙の上限。ブロックされてから気づく ヘッダー・プランで上限が明示(429 + Retry-After)
コスト インフラ・保守人件費は見えにくい 従量課金・プラン料金が発生しうる
取得範囲 ページに出ていれば取れるが、それが許可されているとは限らない 公開フィールドに限定されることが多い
認証・個人情報 セッションCookie流用はアカウント規約違反になりやすい OAuth・スコープで最小権限を設計しやすい

意思決定の目安

状況推奨
公式APIがあり、必要フィールドが揃うAPIのみ
APIはあるが不足フィールドがあるデータ提供の問い合わせ → ダメなら取得範囲を再設計
APIはないが robots.txt・ToS が許容的低頻度の polite スクレイピング + 連絡先付き UA
ToS が自動取得を明示禁止スクレイピングしない(契約・ライセンス交渉)
ログイン必須・CAPTCHA・会員限定公式連携・OAuth・パートナーAPI を探す
個人情報が大量に含まれる取得自体を見直す(APPI・同意の要否)

「APIがあるのにスクレイピングで迂回する」は、短期的には早くても、中長期ではブロック・訴訟・再実装コストのほうが大きくなりやすい。

倫理的判断マトリクス:取得前に立ち止まる

法務レビュー前のエンジニア自己点検用に、2軸で「進む・止まる」を切り分ける。X軸は許可の明示度、Y軸はデータの敏感性

マトリクス(一般論)

許可が明示的(ToS OK / データライセンス / 書面許諾)グレーゾーン(ToS 無記載・robots 許容)明示的禁止(ToS禁止 / Disallow / CAPTCHA)
公開の非個人データ(価格・天気・統計)✅ 進める(API優先・polite実装)⚠️ 法務確認後・低頻度・停止可能設計❌ 止める(交渉か代替データ)
公開だが個人に紐づく(レビュー・SNS・プロフィール)⚠️ APPI・目的限定・最小化❌ 原則止める(法務必須)❌ 止める
認証・会員限定⚠️ OAuth/API・契約スコープ内のみ❌ 止める❌ 止める(不正アクセスリスク)
競合・学習・再配布用途⚠️ ライセンス条項を精読❌ 止める❌ 止める

セルごとの推奨アクション

✅ 進める — 公式APIまたは polite スクレイピング。User-Agent・robots・レート制限・ログを実装。429で自動停止。

⚠️ 法務確認 — 設計書(目的・フィールド・保存期間)を1枚にまとめ、止まれる実装(feature flag)を入れてから PoC。

❌ 止める — 技術的回避(WAF・CAPTCHA・プロキシローテ)に進まない。代替API・手動サンプル・第三者データベースを検討。

倫理の核心原則

倫理とは「バレないようにする」ことではない。相手の意図・負荷・利用規約を尊重し、疑義があれば取得を止められる体制を持つことだ。429・403・CAPTCHAは、サイト側が送る停止信号として解釈する(技術的詳細は Anti-Bot対策記事 参照)。

ポライトスクレイピング:レート制限の実装

相手サーバーへ短時間に大量リクエストを送ると、DoSに近い負荷を与える。倫理的にも、ToS・損害賠償の文脈で問題になりうる。実装では次をセットで入れる。

  • 識別可能な User-AgentMyBot/1.0 (+https://example.com/bot-info) のように連絡先URL付き
  • ホストごとの最小間隔 — 1秒以上、または robots.txt の Crawl-delay 遵守
  • 並列数の上限 — 同一ホストへ同時接続は2〜3本程度
  • 指数バックオフ — 429 / 503 応答時は待機を倍増
  • キャッシュ — ETag / If-Modified-Since で再取得を避ける
  • ピーク時間の回避 — 夜間バッチ・ジョブキューで分散

Python:PoliteFetcher(robots + レート制限 + バックオフ)

import random
import time
from collections import defaultdict
from dataclasses import dataclass, field
from typing import Optional
from urllib.parse import urlparse

import requests
from urllib.robotparser import RobotFileParser

USER_AGENT = "KawaResearchBot/1.0 (+https://kawa.dev/bot; [email protected])"


@dataclass
class PoliteFetcher:
    min_interval: float = 1.5
    max_retries: int = 5
    _last_request: dict[str, float] = field(default_factory=lambda: defaultdict(float))
    _robots: dict[str, RobotFileParser] = field(default_factory=dict)
    session: requests.Session = field(default_factory=requests.Session)

    def __post_init__(self) -> None:
        self.session.headers["User-Agent"] = USER_AGENT

    def _host(self, url: str) -> str:
        return urlparse(url).netloc

    def _ensure_robots(self, url: str) -> RobotFileParser:
        host = self._host(url)
        if host not in self._robots:
            rp = RobotFileParser()
            scheme = urlparse(url).scheme or "https"
            rp.set_url(f"{scheme}://{host}/robots.txt")
            try:
                rp.read()
            except OSError:
                pass
            self._robots[host] = rp
        return self._robots[host]

    def _wait_polite(self, url: str) -> None:
        host = self._host(url)
        elapsed = time.monotonic() - self._last_request[host]
        jitter = random.uniform(0.2, 0.8)
        delay = self.min_interval + jitter - elapsed
        if delay > 0:
            time.sleep(delay)

    def get(self, url: str) -> Optional[str]:
        rp = self._ensure_robots(url)
        if not rp.can_fetch(USER_AGENT, url):
            return None

        for attempt in range(self.max_retries):
            self._wait_polite(url)
            self._last_request[self._host(url)] = time.monotonic()

            resp = self.session.get(url, timeout=30)
            if resp.status_code == 429:
                retry_after = float(resp.headers.get("Retry-After", 2 ** attempt))
                time.sleep(retry_after + random.uniform(0, 1))
                continue
            if resp.status_code in (403, 503):
                # WAF / Anti-Bot の可能性。継続より停止を優先
                return None
            if resp.status_code in (500, 502, 504):
                time.sleep(min(60, (2 ** attempt) + random.uniform(0, 1)))
                continue
            resp.raise_for_status()
            return resp.text

        return None

セマフォで並列数を抑える例

import asyncio
import aiohttp

HOST_SEMAPHORES: dict[str, asyncio.Semaphore] = {}

def semaphore_for(url: str, limit: int = 2) -> asyncio.Semaphore:
    from urllib.parse import urlparse
    host = urlparse(url).netloc
    if host not in HOST_SEMAPHORES:
        HOST_SEMAPHORES[host] = asyncio.Semaphore(limit)
    return HOST_SEMAPHORES[host]

async def fetch_one(session: aiohttp.ClientSession, url: str) -> str:
    async with semaphore_for(url, limit=2):
        await asyncio.sleep(1.2)
        async with session.get(url, headers={"User-Agent": USER_AGENT}) as resp:
            if resp.status in (403, 429):
                raise RuntimeError(f"Blocked or rate limited: {url}")
            resp.raise_for_status()
            return await resp.text()

429 が返ってきたら間隔を広げる・並列を下げる・そのホストの取得を一時停止する。相手の Retry-After ヘッダーは最優先で尊重する。403 が Cloudflare の cf-ray 付きで返る場合は、突破より Anti-Bot記事 のフローに従い停止・問い合わせを検討する。

Anti-Bot対策との関係:技術記事との併読

法務・倫理と技術は切り離せない。サイト側の防御(WAF、Cloudflare Bot Fight Mode、フィンガープリント、CAPTCHA)を理解しないと、「403だからToS違反を突破しよう」という誤った判断に至りやすい。

記事間の読み分け

本記事(法的・倫理)Anti-Bot対策記事
robots.txt / ToS / 著作権の解釈WAF / Cloudflare / フィンガープリントの仕組み
規約違反時の法的リスク429・403の技術的対応
個人情報・再配布のコンプライアンスレート制限・CAPTCHAの実装と挙動
迷ったときの法務相談フロー防御に抵触しない取得の作法

防御シグナルと法的含意

シグナル技術的意味(Anti-Bot記事)法的・倫理的含意(本記事)
429 + Retry-Afterレート超過。待機・頻度低下継続はToS・損害賠償リスク。尊重して停止判断
403 + cf-rayCloudflare WAF / Bot Management自動取得拒否。突破はToS・不正アクセス論点
CAPTCHA人間確認。HTTPクライアントでは不可停止信号。突破サービスは非推奨
503 + Set-CookieJSチャレンジ前段サイト意図に反する迂回は避ける

Anti-Botの「回避テクニック」を学ぶ目的は、防御を理解し、許可された範囲で持続可能なデータ取得を設計することにある。防御を破るための手順書ではない。

倫理的チェックリストと社内ガバナンス

技術的コンプライアンスと倫理はセットだ。次のチェックリストを、プロジェクト着手時・四半期ごと・ToS改定時に見直す。

1

対象URL・取得フィールド・利用目的・保存期間・削除手順を1枚の設計書にまとめたか

2

robots.txt をパースし、禁止パス・Crawl-delay をコードで尊重しているか

3

利用規約で自動取得・再配布・商用利用・AI学習が禁止されていないか確認したか

4

同等データの公式API・データライセンス・問い合わせ窓口を調査したか

5

User-Agent にボット名と連絡先URL(またはメール)を明記したか

6

レート制限・並列上限・バックオフ・ログ・キャッシュを実装したか

7

個人情報・要配慮個人情報が含まれないか、含む場合はAPPI上の措置を法務と合意したか

8

生HTMLの一括保存ではなく、必要最小限の正規化データだけを保持しているか

9

CAPTCHA・ログイン壁・技術的保護手段を迂回する実装をしていないか

10

429・403検知時に自動停止するサーキットブレーカーを実装したか

11

ステージングで少量取得し、DOM変更・HTTPエラー・ブロックの監視アラートを設定したか

12

本番運用後も ToS・robots.txt の変更を定期チェックする担当を決めたか

社内で決めておくとよいポリシー

  • 禁止リスト — 転職サイト・SNS・金融系など、法務判断でNGとしたドメイン
  • エスカレーション — グレーゾーンは誰(法務・セキュリティ)に止まって相談するか
  • インシデント — IPブロック・Cease and Desist を受けたときの停止手順
  • 監査ログ — いつ・誰が・どのURLを・何件取得したか(後追い説明用)

実務でよくある判断ミス

よくある誤解 実際のところ
公開ページだから自由に使える ToS・著作権・個人情報の制約は残る
robots.txt が空なら何でもOK ToS が禁止していればスクレイピングはNG
社内利用なら問題ない 事業目的の取得は規約・不正競争の対象になりうる
1秒1回なら安全 間隔は必要条件であって十分条件ではない
APIキーなしで取れるからAPI不要 意図的な迂回とみなされリスクが高い
403ならWAF突破すればよい ToS・不正アクセス・永久ブロックリスク。停止が先
ハッシュすれば個人情報ではない 再識別可能性の評価が必要

関連記事

この記事は セキュリティ テーマの一環です。あわせて読むと理解が深まる関連記事をまとめました。

トピック記事
XSS攻撃と防御の完全ガイドXSS攻撃と防御の完全ガイド|反射型・蓄積型・DOM型の対策
CSRF対策の実装ガイドCSRF対策の実装ガイド|SameSite・Synchronizer Token・Laravel/Expressコード
Double Submit Cookie完全実装Double Submit Cookie完全実装|Synchronizer Token比較・SPA+JWT・サブドメイン攻撃
Content Security Policy (CSP) 設定ガイドContent Security Policy (CSP) 設定ガイド|XSS・クリックジャッキング対策
CSP Report-Only 段階導入ガイドCSP Report-Only 段階導入ガイド|本番を壊さずポリシーを検証する
セキュリティヘッダー一覧と設定ガイドセキュリティヘッダー一覧と設定ガイド|CSP・HSTS・Referrer-Policy・Permissions-Policy
セキュアなCookie設定ガイドセキュアなCookie設定ガイド|HttpOnly・Secure・SameSiteの使い分けとCSRF対策
CORSエラーの対処法CORSエラーの対処法|「Access-Control-Allow-Origin」で解決する
CORSプリフライトリクエストCORSプリフライトリクエスト|OPTIONSが飛ぶ条件と正しい応答
ローカル開発でCORSエラーが出る原因と3つの回避策ローカル開発でCORSエラーが出る原因と3つの回避策
OAuth2 PKCE SPA実装ガイドOAuth2 PKCE SPA実装ガイド|Authorization Code + S256 + BFFパターン
Passkeys・WebAuthn実装の基礎Passkeys・WebAuthn実装の基礎|FIDO2・Resident Key・@simplewebauthn/server

まとめ

Webスクレイピングは強力なデータ収集手段だが、robots.txt は技術的マナー、ToS と著作権・APPI が法的・事業的な境界線になる。米国CFAAと日本の不正アクセス禁止法は「公開=自由」ではなく、技術的保護の突破・ToS・契約が争点になりうる。

実装前の優先順位:

  1. ToSで禁止されていないか — 禁止なら交渉か中止
  2. 公式APIで足りないか — 迂回スクレイピングは最後
  3. 個人情報を含まないか — APPI・目的・保存期限
  4. robots.txt をコードで尊重しているか — Disallow パスへ入らない
  5. 429・403・CAPTCHAで止まれるかAnti-Bot記事 と併読

取るなら識別可能・低負荷・最小限・期限付きで設計する。どれか一つでも疑問が残ったら、コードを書く前に止まる。それが、サービスを長く運用するチームの基本だ。