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

Glassdoorの公開レビュー・給与データを収集するための実践ガイド。DataDome・Cloudflare対策、BFF GraphQLエンドポイントの活用、ProxyHatレスジデンシャルプロキシを使ったPython実装例まで網羅。

How to Scrape Glassdoor Company Reviews and Salaries in 2026 (BFF GraphQL, DataDome, and Proxies)

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

HRアナリティクスや労働市場データのエンジニアにとって、Glassdoorは企業レビューや給与情報の貴重な公開ソースです。しかし、DataDomeとCloudflare Bot Managementによる多層アンチボット対策により、単純なHTTPリクエストでは数回のアクセスでブロックされます。本記事では、Glassdoorの企業レビューと給与データのスクレイピング方法(2026年版)を実践的に解説し、curl_cffiによるTLS偽装、BFF GraphQLエンドポイントの活用、ProxyHatレスジデンシャルプロキシによるIPローテーションまでカバーします。

法的注意事項:本記事は公開データへの正当なアクセスのみを対象とします。Glassdoorの利用規約(Terms of Service)を必ず確認し、米国のComputer Fraud and Abuse Act(CFAA)およびEUのGDPRに準拠してください。ログイン壁の背後にあるデータのスクレイピングは推奨しません。公式データライセンスの取得が適切なケースもあります。

ログイン不要で取得できるデータと認証が必要なデータ

Glassdoorのデータアクセスは、公開領域と認証領域の2層に分かれています。スクレイピングを設計する前に、この境界を明確に理解することが重要です。

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

  • 企業概要ページ:企業名、業界、規模、本社所在地、設立年
  • レビュー一覧ページ/Reviews/<company>-Reviews-E<id>.htm にアクセスすると、各レビューの ratingOverall(総合評価)、pros(長所)、cons(短所)、jobTitle(職種)のトランケート版が表示される
  • 評価サマリー:星評価の平均値、カテゴリ別スコア(ワークライフバランス、給与満足度など)

認証壁の背後にあるデータ

  • 給与の詳細内訳:職種別・地域別の給与分布、ボーナス・ストックオプションの明細
  • レビューの全文:トランケートされていない完全なレビュー本文
  • 面接体験記:質問内容、面接難易度、結果

本記事では、ログイン不要で取得できる公開レビューデータの収集に焦点を当てます。給与の詳細内訳は認証壁の背後にあり、スクレイピング対象とはしません。

Glassdoorのアンチボットスタック:DataDomeとCloudflare

Glassdoorは2つの主要なボット検知システムを組み合わせています。DataDomeはIPレピュテーションスコアリングと行動分析によるリアルタイムボット検知を提供し、Cloudflare Bot ManagementはJavaScriptチャレンジとTLSフィンガープリンティングを担当します。

DataDomeのIPスコアリング

DataDomeはリクエスト元IPアドレスの属性をスコアリングし、データセンターIPを即座にフラグ付けします。AWS、GCP、AzureなどのクラウドプロバイダーIP範囲は高リスクとして分類されるため、データセンタープロキシではGlassdoorにアクセスできません。一方、ISPに登録された実際の住宅IPアドレス(レスジデンシャルプロキシ)はスコアが低く、DataDomeのチェックを通過しやすくなります。

CloudflareのTLSフィンガープリンティング

CloudflareはTLSハンドシェイクのパラメータ(暗号スイートの順序、拡張機能の構成)を分析し、ブラウザとプログラムティッククライアントを区別します。Pythonの標準 requests ライブラリが送信するTLSフィンガープリントはChromeのそれと大きく異なり、CloudflareのJSチャレンジがトリガーされます。

curl_cffiによるChrome TLS偽装

この問題を解決するために、curl_cffi ライブラリを使用します。curl_cffi はlibcurlのTLS拡張を利用し、Chrome 120の正確なTLSフィンガープリントを再現します。これにより、CloudflareのTLSベースのボット検知をバイパスできます。

pip install curl_cffi

GraphQL BFFエンドポイントとgd-csrf-token

Glassdoorは内部的にGraphQL APIを使用しており、一部のエンドポイントが公開されています。/bff/graphql エンドポイントにPOSTリクエストを送ることで、HTMLをパースする代わりに構造化JSONでレビューデータを取得できます。

このエンドポイントにアクセスするには以下が必要です:

  • gd-csrf-token ヘッダー:Glassdoorのページに埋め込まれたCSRFトークン。最初のページロード時にCookieと共に取得
  • 有効なCookie:DataDomeが発行するCookieを含む、セッションCookie一式
  • 正しいContent-Typeapplication/json

GraphQLクエリの例として、企業IDを指定してレビューリストを取得できます。各レビューノードには ratingOverallprosconsjobTitle などのフィールドが含まれます。

プロキシタイプの比較:Glassdoorスクレイピングに最適な選択

プロキシタイプDataDome検出リスク平均レイテンシ価格帯Glassdoor適性
レスジデンシャル200-500ms中〜高最適
データセンター极高50-100ms不適(即ブロック)
モバイル極低300-800ms良好(コスト高)

レスジデンシャルプロキシは、DataDomeのIPスコアリングを最も確実に通過しつつ、コストとパフォーマンスのバランスが良い選択肢です。ProxyHatのレスジデンシャルプロキシネットワークは、100以上の国と地域に対応し、99.9%の稼働率を提供します。

ProxyHatを使ったPython実装例

以下の例では、ProxyHatのゲートウェイ gate.proxyhat.com:8080 を経由し、curl_cffiでChrome TLS偽装を行い、BFF GraphQLエンドポイントにリクエストを送信します。

ステップ1:CSRFトークンとCookieの取得

from curl_cffi import requests
import re

# ProxyHat residential proxy with US geo-targeting and sticky session
proxy_url = "http://user-country-US-session-glassdoor01:YOUR_PASSWORD@gate.proxyhat.com:8080"

proxies = {"http": proxy_url, "https": proxy_url}

# Step 1: Load the reviews page to get CSRF token and cookies
page_url = "https://www.glassdoor.com/Reviews/Google-Reviews-E9079.htm"

resp = requests.get(
    page_url,
    proxies=proxies,
    impersonate="chrome120",
    timeout=30,
)

# Extract gd-csrf-token from the HTML
csrf_match = re.search(r'gd-csrf-token["\']?\s*[:=]\s*["\']([^"\']+)', resp.text)
csrf_token = csrf_match.group(1) if csrf_match else ""

# Session cookies are automatically stored in resp.cookies
print(f"CSRF token: {csrf_token[:20]}...")
print(f"Cookies: {list(resp.cookies.keys())}")

ステップ2:BFF GraphQLエンドポイントにレビューをリクエスト

# Step 2: Query BFF GraphQL for structured review data
graphql_url = "https://www.glassdoor.com/bff/graphql"

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",
    "Content-Type": "application/json",
    "gd-csrf-token": csrf_token,
    "Referer": page_url,
}

query = """
query getEmployerReviews($employerId: Long!, $page: Int!, $limit: Int!) {
  employerReviews(employerId: $employerId, page: $page, limit: $limit) {
    reviews {
      ratingOverall
      pros
      cons
      jobTitle
      date
    }
    totalPages
    currentPage
  }
}
"""

variables = {
    "employerId": 9079,  # Google's employer ID on Glassdoor
    "page": 1,
    "limit": 10,
}

resp = requests.post(
    graphql_url,
    json={"query": query, "variables": variables},
    headers=headers,
    cookies=resp.cookies,
    proxies=proxies,
    impersonate="chrome120",
    timeout=30,
)

data = resp.json()
reviews = data.get("data", {}).get("employerReviews", {}).get("reviews", [])

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

ステップ3:Node.jsでの実装例

import { ProxyAgent } from 'undici';

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

const query = `
query getEmployerReviews($employerId: Long!, $page: Int!, $limit: Int!) {
  employerReviews(employerId: $employerId, page: $page, limit: $limit) {
    reviews { ratingOverall pros cons jobTitle date }
    totalPages
  }
}`;

const response = await fetch('https://www.glassdoor.com/bff/graphql', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'gd-csrf-token': csrfToken,
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
  },
  body: JSON.stringify({
    query,
    variables: { employerId: 9079, page: 1, limit: 10 },
  }),
  dispatcher: agent,
});

const data = await response.json();
console.log(data.data.employerReviews.reviews.length, 'reviews fetched');

ページネーション、スティッキーセッション、ペースリング

Glassdoorから大量のレビューを収集する場合、以下の3つの要素が成功を左右します。

スティッキーセッションでCookieを維持

DataDomeはCookieベースのセッション追跡を行います。リクエストごとにIPが変わると、Cookieが無効になりチャレンジが再トリガーされます。ProxyHatのスティッキーセッション機能を使い、同一セッションIDで同じ出口IPを維持します。

# Sticky session: keep the same IP for up to 30 minutes
proxy_url = "http://user-country-US-session-glassdoor-abc123:YOUR_PASSWORD@gate.proxyhat.com:8080"

セッションID glassdoor-abc123 を固定することで、DataDomeのCookieが有効な間は同じIPからリクエストが送信されます。セッションが期限切れになったら、新しいセッションIDを生成してIPを切り替えます。

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

GraphQLエンドポイントは page パラメータでページネーションをサポートします。レスポンスに含まれる totalPages を確認しながら、ページを進めます。1企業あたり1500件以上のレビューがある場合、適切なペースリングが不可欠です。

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

  • リクエスト間隔:5-10秒のランダムな待機を入れ、人間らしいアクセスパターンを模倣する
  • 並行セッション:最大100の同時セッションを使用し、各セッションで異なる企業を担当させる
  • チャレンジ検知:HTTPステータス403またはDataDomeのチャレンジページが返された場合、5分間待機してから新しいセッションIDで再試行する
  • 指数バックオフ:連続してブロックされた場合、待機時間を倍増させる(30秒→60秒→120秒)
import time
import random

def scrape_all_reviews(employer_id, max_pages=50):
    all_reviews = []
    session_id = f"gd-{employer_id}-{random.randint(1000, 9999)}"
    proxy_url = f"http://user-country-US-session-{session_id}:YOUR_PASSWORD@gate.proxyhat.com:8080"
    proxies = {"http": proxy_url, "https": proxy_url}
    
    for page in range(1, max_pages + 1):
        variables = {"employerId": employer_id, "page": page, "limit": 10}
        resp = requests.post(graphql_url, json={"query": query, "variables": variables},
                            headers=headers, cookies=session_cookies,
                            proxies=proxies, impersonate="chrome120", timeout=30)
        
        if resp.status_code == 403:
            print(f"Blocked on page {page}, rotating session...")
            session_id = f"gd-{employer_id}-{random.randint(1000, 9999)}"
            proxy_url = f"http://user-country-US-session-{session_id}:YOUR_PASSWORD@gate.proxyhat.com:8080"
            proxies = {"http": proxy_url, "https": proxy_url}
            time.sleep(60)
            continue
        
        data = resp.json()
        reviews = data.get("data", {}).get("employerReviews", {}).get("reviews", [])
        if not reviews:
            break
        all_reviews.extend(reviews)
        print(f"Page {page}: {len(reviews)} reviews fetched")
        time.sleep(random.uniform(5, 10))  # Human-like pacing
    
    return all_reviews

よくある失敗とエッジケース

  • データセンタープロキシの使用:DataDomeは即座にデータセンターIPをブロックします。必ずレスジデンシャルプロキシを使用してください。
  • CSRFトークンの再利用:トークンはセッションに紐づくため、新しいセッションを開始したら新しいトークンを取得してください。
  • 過度な並行リクエスト:同じIPから短時間に大量のリクエストを送るとDataDomeの行動分析に引っかかります。
  • User-Agentの不一致impersonate="chrome120" で偽装したTLSプロファイルとUser-Agent文字列が一致していることを確認してください。
  • geo-targetingの無視:米国企業のレビューにアクセスする場合は country-US を指定し、適切な地域IPを使用してください。ProxyHatのロケーション一覧で対応国を確認できます。

倫理的スクレイピングと公式APIの利用

スクレイピングを行う前に、以下の原則を遵守してください。

集約データのみを収集

個別のレビュー投稿者を特定できるデータ(氏名、メールアドレスなど)は収集しないでください。Glassdoorのレビューは匿名性を前提としており、投稿者のプライバシーを尊重すべきです。分析には集約された統計データ(平均評価、職種別分布など)を使用してください。

GDPRを考慮したEUデータの取り扱い

EU在住の従業員が投稿したレビューデータにはGDPRが適用される可能性があります。個人データに該当する情報を収集・保存・転送する場合、データ処理の法的根拠を確認し、データ主体の権利(アクセス権、削除権など)に対応できる体制を整える必要があります。詳細はGDPR.euを参照してください。

公式データライセンスの検討

商用目的でGlassdoorデータを大規模に利用する場合、Glassdoorの公式データライセンスまたはパートナーシッププログラムの検討が適切です。スクレイピングは公開データへの技術的アクセス手段であり、公式APIやデータライセンスが利用可能な場合はそちらを優先すべきです。

robots.txtの尊重

Glassdoorの robots.txt を確認し、クロールが許可されていないパスにはアクセスしないでください。また、クロールレートの指定がある場合はそれに従ってください。

Key Takeaways(重要ポイント)

1. Glassdoorの公開レビューページはログイン不要でアクセス可能だが、給与の詳細内訳は認証壁の背後にある。

2. DataDome + Cloudflare Bot Managementの二重対策により、データセンタープロキシと標準HTTPクライアントは即座にブロックされる。

3. curl_cffiによるChrome TLS偽装とレスジデンシャルプロキシの組み合わせが、DataDomeのIPスコアリングを回避する最も確実な方法。

4. BFF GraphQLエンドポイント(/bff/graphql)とgd-csrf-tokenヘッダーを使うことで、HTMLパース不要の構造化データ取得が可能。

5. スティッキーセッションでCookieを維持し、5-10秒のペースリングと指数バックオフでブロックを回避する。

6. 倫理的スクレイピングを徹底し、集約データのみを収集。GDPRに準拠し、公式APIの利用を常に検討する。

ProxyHatのレスジデンシャルプロキシの利用を開始するには、料金プランを確認するか、公式ドキュメントで接続方法の詳細を参照してください。Webスクレイピングのユースケースページでも他のスクレイピングシナリオを紹介しています。

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

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

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