Glassdoorの企業レビューと給与データをスクレイピングする方法(2026年版)

Glassdoorの公開レビューデータをGraphQL BFFエンドポイントから取得する実装手順を解説。DataDome・Cloudflare対策、curl_cffiによるTLS偽装、ProxyHatレジデンシャルプロキシの活用まで網羅。

How to Scrape Glassdoor Company Reviews and Salaries in 2026: BFF GraphQL, DataDome, and Proxy Workarounds
この記事の内容

HRアナリティクスチームや労働市場データのエンジニアにとって、Glassdoorは企業レビュー、給与水準、面接体験など貴重な公開情報を提供するプラットフォームです。本記事では、Glassdoorの企業レビューと給与データのスクレイピングを2026年の最新アンチボット環境下で実装する方法を、実践的なコード例とともに解説します。

法的注意事項: 本記事は公開データへのアクセスのみを対象としています。Glassdoorの利用規約(Terms of Service)を遵守し、米国ではComputer Fraud and Abuse Act (CFAA)、EUではGDPRに準拠してください。ログインが必要なデータのスクレイピングは推奨しません。本記事の内容は教育目的であり、実際のスクレイピングを行う前に法的専門家に相談することを推奨します。

Glassdoorの企業レビューと給与データのスクレイピング2026 — 公開データとログイン壁の境界

Glassdoorのデータアクセシビリティは、ページタイプによって大きく異なります。スクレイピングを設計する前に、何が公開されていて何がログイン壁の後ろにあるかを正確に把握することが不可欠です。

ログインなしでアクセス可能なデータ

  • 企業概要ページ: /Overview/Working-at-<company>-EI_IE<id>.htm — 企業名、業界、規模、本社所在地など
  • レビュー一覧ページ: /Reviews/<company>-Reviews-E<id>.htm — 各レビューの評価(ratingOverall)、長所(pros)、短所(cons)、職種(jobTitle)の先頭部分が公開状態で表示されます。ただし全文は途中で切り詰められています。
  • 企業の基本スコア: 総合評価スコア、推奨率、CEO支持率などがHTML内に埋め込まれています。

ログイン壁の後ろにあるデータ

  • 給与の詳細内訳: 職種別、地域別、経験年数別の給与分布はログインが必要です。
  • レビュー全文: 切り詰められた部分以降の本文は、ログイン後にのみ表示されます。
  • 面接体験の詳細: 面接の質問内容やプロセスの詳細はログイン壁の後ろにあります。

本記事では、ログインなしでアクセス可能な公開レビューデータの取得に焦点を当てます。給与の詳細内訳にはアクセスせず、公開範囲のデータのみを対象とします。

Glassdoorのアンチボットスタック — DataDome + Cloudflare Bot Management

Glassdoorは2026年時点で多層防御のアンチボットスタックを採用しています。主要なコンポーネントは以下の通りです。

DataDome — IPスコアリングと行動分析

DataDomeは、IPレピュテーション、リクエスト頻度、ブラウザフィンガープリントを組み合わせてbotトラフィックを検出します。データセンターIPからのリクエストは、DataDomeのIPスコアリングにより80%以上の確率でブロックされます。一方、レジデンシャルIPからのリクエストははるかに高い通過率を示します。

Cloudflare Bot Management — JSチャレンジとTLSフィンガープリンティング

Cloudflare Bot Managementは、JavaScriptチャレンジとTLSフィンガープリンティングを組み合わせて、非ブラウザクライアントを検出します。標準的なPythonのrequestsライブラリが送信するTLSハンドシェイクは、Chromeのそれとは異なる暗号スイートの順序と拡張機能を持つため、Cloudflareによって即座に識別されます。

なぜcurl_cffiが必要なのか

curl_cffiは、ChromeのTLSハンドシェイクを忠実に再現するPythonライブラリです。impersonate="chrome120"パラメータを指定することで、実際のChromeブラウザと同一のTLSフィンガープリントを送信し、CloudflareのTLSベースの検査を通過できます。標準のrequestsライブラリではこの偽装は不可能です。

クライアントTLSフィンガープリントDataDome通過率Cloudflare JS通過
Python requestsPython/OpenSSL低(約15%)不可
curl_cffi (Chrome偽装)Chrome 120高(約90%)可能
Playwright/Puppeteer実際のChrome最高(95%+)可能

GraphQL BFFエンドポイントの発見と活用

GlassdoorのフロントエンドはReactベースのSPAであり、データ取得にGraphQLを使用しています。ブラウザのDevToolsでネットワークタブを確認すると、以下のエンドポイントが見つかります。

  • /bff/graphql — BFF(Backend for Frontend)層のGraphQLエンドポイント
  • /graph — 内部GraphQLエンドポイント(一部のクエリで使用)

これらのエンドポイントは、HTMLをパースする代わりに構造化JSONを直接返すため、スクレイピングの効率と信頼性が大幅に向上します。

必須ヘッダー — gd-csrf-token

GraphQLエンドポイントにPOSTリクエストを送信する際、gd-csrf-tokenヘッダーが必須です。このトークンは、初期ページアクセス時にHTML内またはCookieに埋め込まれています。最初のGETリクエストでページをロードし、レスポンスからCSRFトークンを抽出した後、それを用いてGraphQLエンドポイントにPOSTリクエストを送信するという2段階のアプローチが必要です。

なぜローテーション型レジデンシャルプロキシがDataDomeに勝るのか

DataDomeのIPスコアリングは、データセンターIP範囲を即座にフラグ付けします。レジデンシャルプロキシは実際のISPに割り当てられたIPアドレスを使用するため、DataDomeのIPレピュテーションチェックを通過します。ProxyHatのレジデンシャルプロキシネットワークは、世界中のISPベースのIPを提供し、Geoターゲティングもサポートしています。

Python実装例 — ProxyHat + curl_cffiでBFF GraphQLにPOST

以下は、ProxyHatのレジデンシャルプロキシを経由して、GlassdoorのBFF GraphQLエンドポイントにPOSTリクエストを送信し、公開レビューデータを取得する完全なPython例です。

from curl_cffi import requests
import json
import re
import time

# ProxyHat レジデンシャルプロキシ(US geo、スティッキーセッション)
proxy_url = "http://user-country-US-session-gd001:PASSWORD@gate.proxyhat.com:8080"
proxies = {"http": proxy_url, "https": proxy_url}

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                  "AppleWebKit/537.36 (KHTML, like Gecko) "
                  "Chrome/120.0.0.0 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9",
}

# ステップ1: 初期ページにGETしてCSRFトークンを取得
review_url = "https://www.glassdoor.com/Reviews/Example-Co-Reviews-E12345.htm"
resp = requests.get(
    review_url,
    headers=headers,
    proxies=proxies,
    impersonate="chrome120",
    timeout=30
)

# HTMLから gd-csrf-token を抽出
csrf_match = re.search(r'gd-csrf-token["\s:=]+([A-Za-z0-9_-]+)', resp.text)
csrf_token = csrf_match.group(1) if csrf_match else ""
print(f"CSRF Token extracted: {csrf_token[:20]}...")

# ステップ2: GraphQL BFF エンドポイントにPOST
graphql_query = {
    "query": """
    query EmployerReviews($employerId: ID!, $cursor: String) {
        employerReviews(employerId: $employerId, after: $cursor) {
            reviews {
                id
                ratingOverall
                pros
                cons
                jobTitle { text }
            }
            pageInfo { hasNextPage endCursor }
        }
    }
    """,
    "variables": {
        "employerId": "E12345",
        "cursor": None
    }
}

graphql_headers = {
    **headers,
    "Content-Type": "application/json",
    "gd-csrf-token": csrf_token,
    "Origin": "https://www.glassdoor.com",
    "Referer": review_url,
}

time.sleep(3)  # ペース調整

graphql_resp = requests.post(
    "https://www.glassdoor.com/bff/graphql",
    json=graphql_query,
    headers=graphql_headers,
    proxies=proxies,
    impersonate="chrome120",
    timeout=30
)

data = graphql_resp.json()
reviews = data["data"]["employerReviews"]["reviews"]

for r in reviews:
    print(f"Rating: {r['ratingOverall']}")
    print(f"Title: {r['jobTitle']['text']}")
    print(f"Pros: {r['pros'][:120]}")
    print(f"Cons: {r['cons'][:120]}")
    print("---")

page_info = data["data"]["employerReviews"]["pageInfo"]
print(f"Has next page: {page_info['hasNextPage']}")
print(f"End cursor: {page_info['endCursor']}")

このコードは、まず公開レビューページにGETリクエストを送信してCSRFトークンを抽出し、次にそのトークンを使ってGraphQLエンドポイントにPOSTリクエストを送信します。impersonate="chrome120"により、Chrome 120のTLSフィンガープリントが再現されます。

curlコマンドラインでの確認

コードを書く前に、curlでエンドポイントの動作を確認することも可能です。

curl -x "http://user-country-US-session-gd001:PASSWORD@gate.proxyhat.com:8080" \
  -H "Content-Type: application/json" \
  -H "gd-csrf-token: YOUR_CSRF_TOKEN" \
  -H "Origin: https://www.glassdoor.com" \
  -H "Referer: https://www.glassdoor.com/Reviews/" \
  -d '{"query":"{ employerReviews(employerId:\"E12345\") { reviews { ratingOverall pros cons } } }"}' \
  "https://www.glassdoor.com/bff/graphql"

ページネーション、スティッキーセッション、ペース調整

Glassdoorのレビューデータを複数ページにわたって取得する場合、以下の3つの要素が成功の鍵を握ります。

ページネーションカーソル

GraphQLのレスポンスにはpageInfoオブジェクトが含まれ、hasNextPageendCursorが返されます。次のリクエストでは、variables.cursorに前回のendCursorを渡すことで、次のページのレビューを取得できます。

cursor = None
all_reviews = []

while True:
    graphql_query["variables"]["cursor"] = cursor
    resp = requests.post(
        "https://www.glassdoor.com/bff/graphql",
        json=graphql_query,
        headers=graphql_headers,
        proxies=proxies,
        impersonate="chrome120",
        timeout=30
    )
    
    data = resp.json()
    page_reviews = data["data"]["employerReviews"]["reviews"]
    all_reviews.extend(page_reviews)
    
    page_info = data["data"]["employerReviews"]["pageInfo"]
    if not page_info["hasNextPage"]:
        break
    
    cursor = page_info["endCursor"]
    time.sleep(5)  # 5秒のペース調整

print(f"Total reviews scraped: {len(all_reviews)}")

DataDomeはCookieベースのセッション追跡を行います。リクエストごとにIPが変わると、DataDomeのCookieが無効になり、再チャレンジが発生する可能性があります。ProxyHatのスティッキーセッション機能(-session-フラグ)を使用すると、同一セッションIDの間は同じ出口IPを維持できます。

# 同一セッションで同じIPを維持
proxy_url = "http://user-country-US-session-gd001:PASSWORD@gate.proxyhat.com:8080"

セッションIDは企業ごとに一意にすることを推奨します。例えばsession-glassdoor-E12345のように命名すれば、企業ごとに異なるIPが割り当てられ、同一企業内ではIPが安定します。50〜100並行セッション程度であれば、DataDomeのレート制限に引っかかることなく安定してデータを取得できます。

ペース調整とチャレンジリトライ

各リクエストの間に3〜5秒の遅延を入れることで、DataDomeの行動分析に引っかかるリスクを大幅に減らせます。また、HTTP 403または429ステータスコードを受け取った場合は、指数バックオフでリトライを実装します。

import random

def fetch_with_retry(url, max_retries=3, **kwargs):
    for attempt in range(max_retries):
        resp = requests.post(url, **kwargs)
        if resp.status_code == 200:
            return resp
        elif resp.status_code in (403, 429):
            wait = (2 ** attempt) + random.uniform(0, 1)
            print(f"Blocked ({resp.status_code}), retrying in {wait:.1f}s...")
            time.sleep(wait)
        else:
            resp.raise_for_status()
    raise Exception(f"Max retries ({max_retries}) exceeded")

Node.js実装例

Node.js環境では、undiciのProxyAgentと組み合わせて実装できます。ただし、Node.js標準のTLSスタックはChromeと異なるため、本格的なスクレイピングにはnode-libcurlまたはPuppeteerの使用を推奨します。

import { ProxyAgent } from 'undici';

const proxyUrl = 'http://user-country-US-session-gd001:PASSWORD@gate.proxyhat.com:8080';
const agent = new ProxyAgent(proxyUrl);

const query = {
  query: `query EmployerReviews($employerId: ID!, $cursor: String) {
    employerReviews(employerId: $employerId, after: $cursor) {
      reviews { id ratingOverall pros cons jobTitle { text } }
      pageInfo { hasNextPage endCursor }
    }
  }`,
  variables: { employerId: 'E12345', cursor: null }
};

const response = await fetch('https://www.glassdoor.com/bff/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'gd-csrf-token': csrfToken,
    'Origin': 'https://www.glassdoor.com',
    'Referer': 'https://www.glassdoor.com/Reviews/',
  },
  body: JSON.stringify(query),
  dispatcher: agent,
});

const data = await response.json();
data.data.employerReviews.reviews.forEach(r => {
  console.log(`Rating: ${r.ratingOverall}, Title: ${r.jobTitle.text}`);
});

プロキシタイプ比較 — Glassdoorスクレイピング向け

GlassdoorのDataDome + Cloudflare環境において、各プロキシタイプの性能を比較します。

プロキシタイプDataDome通過率平均レイテンシコスト推奨用途
レジデンシャル高(約90%)200〜500msGlassdoorレビューの通常スクレイピング
モバイル最高(95%+)300〜800ms高難度ターゲット・大量取得
データセンター低(約15%)50〜100ms開発・テスト環境のみ

Glassdoorのスクレイピングには、ProxyHatのレジデンシャルプロキシが最適なバランスを提供します。コストパフォーマンスとDataDome通過率の両立が可能で、GeoターゲティングによりUS向けコンテンツに確実にアクセスできます。

倫理的スクレイピング — 集計データのみ、ログイン壁越えなし

Glassdoorからデータを取得する際は、以下の倫理的ガイドラインを遵守することを強く推奨します。

集計・非個人データのみを対象とする

個別のレビュー投稿者を特定できるデータ(氏名、メールアドレスなど)は収集しないでください。レビューの評価スコア、職種、長所・短所のテキストなど、企業分析に必要な集計データのみを抽出し、個人を特定できる情報は除外します。

ログイン壁の後ろのデータはスクレイピングしない

ログインが必要な給与の詳細内訳やレビュー全文は、本記事の対象範囲外です。ログイン壁を越えてデータを取得することは、CFAAやGlassdoorの利用規約に違反する可能性が高いです。

GDPRにおけるEU従業員データの取り扱い

EUの従業員によって投稿されたレビューは、GDPRの「個人データ」に該当する可能性があります。レビューのテキストから投稿者を特定できる情報を抽出・保存する場合、GDPRのデータ保護要件が適用されます。集計分析のみを行い、個人レベルのデータ保存を避けることで、リスクを軽減できます。詳細についてはGDPR.euを参照してください。

公式データライセンスを選択すべきタイミング

大規模なデータ収集や商用利用を計画している場合、Glassdoorの公式データライセンスまたはAPIの利用を検討してください。公式ライセンスは法的リスクを排除し、データの品質と更新頻度も保証されます。スクレイピングは小規模な研究やプロトタイピングに留め、本番環境では公式チャネルを優先すべきです。

Key Takeaways

  • 公開データのみを対象: /Reviews/ページの切り詰められたレビューと基本評価は公開されていますが、給与の詳細内訳とレビュー全文はログイン壁の後ろにあります。
  • TLS偽装が必須: CloudflareのTLSフィンガープリンティングを通過するには、curl_cffiimpersonate="chrome120"を使用します。標準のrequestsでは不十分です。
  • GraphQL BFFエンドポイントを活用: /bff/graphqlにPOSTリクエストを送信し、gd-csrf-tokenヘッダーを含めることで、HTMLパース不要の構造化データを取得できます。
  • レジデンシャルプロキシでDataDomeを回避: データセンターIPはDataDomeによって80%以上ブロックされます。レジデンシャルプロキシは約90%の通過率を達成します。
  • スティッキーセッションでCookieを維持: -session-フラグで同一IPを維持し、DataDomeのCookieベースセッションを安定させます。
  • ペース調整は3〜5秒: リクエスト間隔を空け、指数バックオフでリトライを実装することで、ブロックリスクを最小化します。
  • 倫理と法令遵守: 集計データのみを収集し、ログイン壁を越えず、GDPR/CFAAを遵守してください。大規模利用には公式データライセンスを検討しましょう。

Glassdoorのスクレイピング実装についてさらに詳しい情報が必要な場合は、ウェブスクレイピングのユースケースおよびProxyHatドキュメントを参照してください。SERPトラッキングのユースケースも、検索結果ページからのデータ抽出に役立つ参考情報を提供しています。

よくある質問

Glassdoorのレビューと給与データのスクレイピングとは何ですか?

Glassdoorのスクレイピングは、同プラットフォーム上の公開企業レビュー、評価スコア、給与概要などのデータをプログラム的に取得する手法です。2026年では、HTMLのパースではなくGraphQL BFFエンドポイント(/bff/graphql)へのPOSTリクエストにより構造化JSONデータを直接取得するアプローチが主流です。ただし、ログイン壁の後ろにある給与の詳細内訳やレビュー全文は対象外であり、公開データのみにアクセスすることが重要です。

なぜプロキシユーザーにとってGlassdoorのスクレイピングが重要なのですか?

GlassdoorはDataDomeとCloudflare Bot Managementによる多層アンチボット防御を採用しており、データセンターIPからのアクセスは80%以上の確率でブロックされます。レジデンシャルプロキシを使用することで、実際のISP IPアドレスからリクエストを送信し、DataDomeのIPスコアリングを通過できます。HRアナリティクスや労働市場データのエンジニアにとって、プロキシはGlassdoorから安定してデータを取得するための必須インフラです。

Glassdoorのスクレイピングに最適なプロキシタイプは何ですか?

Glassdoorのスクレイピングには、レジデンシャルプロキシが最適です。データセンターIPはDataDomeによって高確率でブロックされ、モバイルプロキシは通過率が最も高いもののコストが高額です。レジデンシャルプロキシは約90%のDataDome通過率と200〜500msのレイテンシを提供し、コストパフォーマンスのバランスが最も優れています。Geoターゲティング機能により、US向けコンテンツへの確実なアクセスも可能です。

Glassdoorのスクレイピングでブロックを回避するにはどうすればよいですか?

ブロック回避には4つの要素が重要です。第一に、curl_cffiのimpersonate="chrome120"でChrome TLSフィンガープリントを再現します。第二に、レジデンシャルプロキシでDataDomeのIPスコアリングを通過します。第三に、スティッキーセッション(-session-フラグ)で同一IPを維持し、DataDomeのCookieセッションを安定させます。第四に、リクエスト間に3〜5秒のペース調整を行い、指数バックオフでリトライを実装します。

始める準備はできましたか?

AIフィルタリングで148か国以上、5,000万以上のレジデンシャルIPにアクセス。

料金を見るレジデンシャルプロキシ
← ブログに戻る