Cómo scrapear reseñas y salarios de Glassdoor en 2026: BFF GraphQL, DataDome y proxies

Guía práctica para extraer reseñas públicas y datos salariales de Glassdoor usando el endpoint BFF GraphQL, TLS fingerprinting con curl_cffi y proxies residenciales rotativos de ProxyHat.

How to Scrape Glassdoor Company Reviews and Salaries in 2026: BFF GraphQL, DataDome, and Proxy Workarounds
En este artículo

Aviso legal: Esta guía cubre únicamente el acceso a datos públicos sin autenticación. Debes respetar los Términos de Servicio de Glassdoor, la Computer Fraud and Abuse Act (CFAA) en EE.UU. y el GDPR en la UE. No accedas a contenido tras un muro de login ni extraigas datos personales identificables sin consentimiento.

Si trabajas en analítica de RR.HH. o en inteligencia de mercado laboral, sabes que Glassdoor es una de las fuentes más ricas de reseñas de empleados, valoraciones culturales y datos salariales. Pero scrapear Glassdoor en 2026 no es trivial: la plataforma combina DataDome, Cloudflare Bot Management, fingerprinting TLS y challenges de JavaScript. En esta guía verás cómo scrapear reseñas y salarios de Glassdoor de forma robusta, usando el endpoint BFF GraphQL no documentado, curl_cffi para impersonación TLS y proxies residenciales rotativos de ProxyHat.

Por qué scrapear Glassdoor es difícil en 2026

Glassdoor protege su contenido con múltiples capas anti-bot. DataDome analiza la reputación IP, los headers HTTP, el fingerprint del navegador y los patrones de comportamiento. Cloudflare Bot Management añade challenges de JavaScript y fingerprinting TLS (JA3/JA4) que detectan clientes HTTP que no coinciden con un navegador real. Un requests.get() básico con una IP de datacenter recibe un HTTP 403 en menos de 5 peticiones en la mayoría de los casos.

El problema se agrava porque Glassdoor sirve parte de su contenido dinámico a través de endpoints GraphQL internos (/graph y /bff/) que requieren un gd-csrf-token válido y cookies de sesión de DataDome. Si tu cliente TLS no coincide con Chrome o Firefox, el challenge nunca se resuelve y el token no se emite.

Qué es accesible sin login vs. gated

Antes de escribir una sola línea de código, es crítico entender el límite entre lo público y lo gated:

Tipo de datoAccesible sin loginURL / Endpoint
Reseña general de empresaSí (truncada)/Reviews/<company>-Reviews-E<id>.htm
Valoración global y sub-valoracionesBFF GraphQL
Pros y contras (truncados)BFF GraphQL
Cargo del revisorSí (anonimizado)BFF GraphQL
Desglose salarial completoNoTras login
Reseñas extendidas (texto completo)NoTras login
Datos personales del revisorNoNunca scrapear

Esta guía se centra exclusivamente en los datos públicos: reseñas truncadas, valoraciones y metadatos de cargo. Los datos salariales completos están detrás de un muro de autenticación y no deben extraerse mediante scraping. Si necesitas datos salariales completos, considera una licencia de datos oficial o APIs de terceros como Glassdoor for Employers.

El stack anti-bot de Glassdoor: DataDome + Cloudflare

Glassdoor delega su protección a DataDome, un servicio anti-bot que combina heurísticas en tiempo real con scoring de IP. Según la documentación oficial de DataDome, el sistema evalúa más de 40 señales por petición, incluyendo headers, fingerprint JavaScript, reputación IP y patrones de navegación.

Cloudflare Bot Management se superpone a DataDome con fingerprinting TLS (JA3/JA4). Esto significa que incluso si envías los headers perfectos, el handshake TLS de tu cliente HTTP delata si eres requests, httpx o un navegador real. La solución es curl_cffi, una librería Python que usa libcurl-impersonate para reproducir el handshake TLS exacto de Chrome.

Por qué curl_cffi es imprescindible

La impersonación TLS de curl_cffi replica el ClientHello de Chrome 120+ incluyendo el orden de cipher suites, las extensiones y los parámetros ALPN. Sin esto, DataDome detecta tu cliente en el primer handshake y emite un challenge que un cliente no-JS no puede resolver. Con curl_cffi, la primera petición suele pasar el filtro si la IP residencial tiene buena reputación.

pip install curl_cffi

El endpoint BFF GraphQL de Glassdoor

Glassdoor sirve datos estructurados a través de un endpoint BFF (Backend-for-Frontend) en /bff/v1/graphql (la ruta exacta puede variar entre despliegues). Este endpoint devuelve JSON limpio con campos como ratingOverall, pros, cons, jobTitle, reviewDateTime y cursores de paginación, evitando el parseo de HTML.

Requisitos para usarlo:

  • Header gd-csrf-token: token CSRF que se genera en la carga inicial de la página. Debes extraerlo del HTML o de las cookies.
  • Cookies de DataDome: datadome y cookies de sesión que se establecen tras pasar el challenge inicial.
  • Body GraphQL: una query POST con el operationName, query y variables (incluyendo el ID de empresa y el cursor).
  • Headers de navegador: User-Agent, Accept, Content-Type: application/json, Origin y Referer coherentes.

El endpoint /graph es una variante legacy que devuelve datos similares pero con un esquema diferente. En 2026, la mayoría del tráfico frontend usa /bff/.

Configuración de proxies ProxyHat

Para superar el scoring de IP de DataDome necesitas proxies residenciales. Las IPs de datacenter tienen una tasa de bloqueo superior al 90% en Glassdoor según pruebas internas de la comunidad. ProxyHat ofrece proxies residenciales rotativos con geo-targeting y sesiones sticky.

Parámetros de conexión:

ParámetroValor
Gatewaygate.proxyhat.com
Puerto HTTP8080
Puerto SOCKS51080
Formato usuariouser-country-US-session-abc123

Consulta todas las ubicaciones disponibles y el detalle de planes y precios.

Ejemplo en Python: scrapear una reseña vía BFF GraphQL

A continuación, un ejemplo completo que combina curl_cffi, proxies residenciales de ProxyHat y el endpoint BFF GraphQL para extraer una reseña truncada.

import json
import time
import re
from curl_cffi import requests as cffi_requests

# --- Configuración del proxy ProxyHat (residencial, sesión sticky) ---
PROXY_USER = "user-country-US-session-glassdoor01"
PROXY_PASS = "tu_password"
PROXY_URL = f"http://{PROXY_USER}:{PROXY_PASS}@gate.proxyhat.com:8080"

GLASSDOOR_EMPLOYER_ID = "E12345"  # ID de empresa de Glassdoor
BASE_URL = "https://www.glassdoor.com"

def obtener_csrf_y_cookies():
    """Carga la página de reseñas para obtener gd-csrf-token y cookies DataDome."""
    url = f"{BASE_URL}/Reviews/empresa-Reviews-{GLASSDOOR_EMPLOYER_ID}.htm"
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/124.0.0.0 Safari/537.36",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.9",
    }
    resp = cffi_requests.get(
        url,
        headers=headers,
        proxies={"http": PROXY_URL, "https": PROXY_URL},
        impersonate="chrome124",
        timeout=30,
    )
    if resp.status_code == 403:
        raise Exception("DataDome challenge detectado — rota la sesión del proxy")

    # Extraer gd-csrf-token del HTML o de los headers
    csrf_match = re.search(r'gd-csrf-token["\']?\s*[:=]\s*["\']([^"\']+)', resp.text)
    csrf_token = csrf_match.group(1) if csrf_match else ""
    return csrf_token, resp.cookies

def scrapear_resenas_bff(csrf_token, cookies, cursor=None):
    """POST al endpoint BFF GraphQL para obtener reseñas estructuradas."""
    bff_url = f"{BASE_URL}/bff/v1/graphql"

    variables = {
        "employerId": GLASSDOOR_EMPLOYER_ID,
        "num": 10,
        "cursor": cursor,
    }

    payload = {
        "operationName": "EmployerReviews",
        "query": """
            query EmployerReviews($employerId: String!, $num: Int!, $cursor: String) {
              employer(employerId: $employerId) {
                reviews(num: $num, cursor: $cursor) {
                  edges {
                    node {
                      ratingOverall
                      pros
                      cons
                      jobTitle { title }
                      reviewDateTime
                    }
                  }
                  pageInfo { nextCursor hasNextPage }
                }
              }
            }
        """,
        "variables": variables,
    }

    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                      "AppleWebKit/537.36 (KHTML, like Gecko) "
                      "Chrome/124.0.0.0 Safari/537.36",
        "Content-Type": "application/json",
        "Accept": "application/json",
        "Origin": BASE_URL,
        "Referer": f"{BASE_URL}/Reviews/empresa-Reviews-{GLASSDOOR_EMPLOYER_ID}.htm",
        "gd-csrf-token": csrf_token,
    }

    resp = cffi_requests.post(
        bff_url,
        headers=headers,
        json=payload,
        cookies=cookies,
        proxies={"http": PROXY_URL, "https": PROXY_URL},
        impersonate="chrome124",
        timeout=30,
    )

    if resp.status_code == 403:
        raise Exception("Challenge DataDome en BFF — rota sesión y reintenta")

    return resp.json()

# --- Ejecución principal ---
csrf, cookies = obtener_csrf_y_cookies()
time.sleep(2)  # pacing entre carga inicial y API

resultado = scrapear_resenas_bff(csrf, cookies)

for edge in resultado["data"]["employer"]["reviews"]["edges"]:
    node = edge["node"]
    print(f"Cargo: {node['jobTitle']['title']}")
    print(f"Valoración: {node['ratingOverall']}/5")
    print(f"Pros: {node['pros'][:120]}...")
    print(f"Contras: {node['cons'][:120]}...")
    print(f"Fecha: {node['reviewDateTime']}")
    print("---")

Este ejemplo extrae reseñas truncadas con sus valoraciones, pros, contras y cargo del revisor (anonimizado por Glassdoor). La sesión sticky session-glassdoor01 mantiene la misma IP para conservar las cookies de DataDome durante toda la sesión de paginación.

Ejemplo en Node.js con fetch y proxy HTTP

Para equipos que prefieren Node.js, aquí hay un equivalente usando undici con proxy HTTP. Nota: Node.js no tiene impersonación TLS nativa equivalente a curl_cffi, por lo que recomendamos usar el binding node-libcurl o ejecutar curl-impersonate como subproceso.

const { ProxyAgent, fetch } = require('undici');

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

async function scrapeReviews() {
  const bffUrl = 'https://www.glassdoor.com/bff/v1/graphql';
  const payload = {
    operationName: 'EmployerReviews',
    query: `query EmployerReviews($employerId: String!, $num: Int!, $cursor: String) {
      employer(employerId: $employerId) {
        reviews(num: $num, cursor: $cursor) {
          edges { node { ratingOverall pros cons jobTitle { title } reviewDateTime } }
          pageInfo { nextCursor hasNextPage }
        }
      }
    }`,
    variables: { employerId: 'E12345', num: 10, cursor: null }
  };

  const resp = await fetch(bffUrl, {
    method: 'POST',
    dispatcher: agent,
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json',
      'Origin': 'https://www.glassdoor.com',
      'Referer': 'https://www.glassdoor.com/Reviews/empresa-Reviews-E12345.htm',
      'gd-csrf-token': process.env.GD_CSRF_TOKEN || '',
      'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
    },
    body: JSON.stringify(payload),
  });

  if (resp.status === 403) {
    throw new Error('DataDome challenge — rota sesión del proxy');
  }

  const data = await resp.json();
  for (const edge of data.data.employer.reviews.edges) {
    const n = edge.node;
    console.log(`${n.jobTitle.title} — ${n.ratingOverall}/5 — ${n.reviewDateTime}`);
  }
}

scrapeReviews().catch(console.error);

Paginación, sesiones sticky y lógica de reintento

La paginación del BFF GraphQL usa cursores opacos. Cada respuesta incluye pageInfo.nextCursor y pageInfo.hasNextPage. Debes pasar el cursor en la siguiente petición dentro de variables.cursor.

Estrategia de sesión sticky

Las cookies de DataDome están vinculadas a la IP que las generó. Si rotas la IP en cada petición, DataDome invalida la sesión y emite un challenge. La solución es usar sesiones sticky en ProxyHat:

# Misma sesión = misma IP durante toda la paginación
PROXY_USER = "user-country-US-session-glassdoor01"

Mantén la misma sesión durante toda la extracción de una empresa. Solo rota la sesión (cambia el identificador) cuando recibas un HTTP 403 o un challenge de DataDome.

Pacing y rate limiting

  • Espera entre peticiones: 1-3 segundos con jitter aleatorio. Glassdoor no publica límites públicos, pero DataDome marca como sospechosos los bursts de más de ~10 peticiones por minuto desde la misma IP.
  • Concurrencia: máx. 2-3 peticiones concurrentes por sesión sticky. Si necesitas más throughput, usa múltiples sesiones con IPs diferentes.
  • Retry con backoff exponencial: ante un 403, espera 5s, rota la sesión, re-obtén CSRF y cookies, y reintenta. Máximo 3 reintentos por cursor.
import random

def scrapear_todas_las_resenas(csrf, cookies, proxy_user_base):
    cursor = None
    todas = []
    session_id = "glassdoor01"
    reintentos = 0

    while True:
        proxy_user = f"user-country-US-session-{session_id}"
        proxy_url = f"http://{proxy_user}:tu_password@gate.proxyhat.com:8080"

        try:
            data = scrapear_resenas_bff(csrf, cookies, cursor, proxy_url)
            edges = data["data"]["employer"]["reviews"]["edges"]
            todas.extend(edges)
            reintentos = 0

            page_info = data["data"]["employer"]["reviews"]["pageInfo"]
            if not page_info["hasNextPage"]:
                break
            cursor = page_info["nextCursor"]
            time.sleep(random.uniform(1.5, 3.0))

        except Exception as e:
            reintentos += 1
            if reintentos > 3:
                print(f"Máximo de reintentos alcanzado en cursor {cursor}")
                break
            # Rotar sesión y re-obtener CSRF
            session_id = f"glassdoor{random.randint(100,999)}"
            time.sleep(5 * reintentos)
            csrf, cookies = obtener_csrf_y_cookies(proxy_url)

    return todas

Errores comunes y casos límite

  • Usar requests/httpx sin impersonación TLS: DataDome detecta el fingerprint JA3 en el primer handshake. Usa siempre curl_cffi con impersonate="chrome124".
  • Rotar IP en cada petición: invalida las cookies de DataDome. Usa sesiones sticky durante toda la paginación.
  • No extraer el gd-csrf-token: el BFF GraphQL devuelve 403 sin este header. Debes cargar la página HTML primero y extraerlo.
  • Scrapear tras login: viola los ToS de Glassdoor y potencialmente el CFAA. Esta guía cubre solo datos públicos.
  • Ignorar robots.txt: aunque Glassdoor no bloquea explícitamente /Reviews/ en robots.txt, debes revisarlo periódicamente. Consulta https://www.glassdoor.com/robots.txt.
  • No agregar datos: almacenar reseñas individuales con texto completo puede plantear problemas de GDPR si el texto contiene información personal. Agrega a nivel de empresa y elimina PII.

Scraping ético y cuándo usar APIs oficiales

El scraping de datos públicos es una herramienta legítima para la inteligencia de mercado laboral, pero tiene límites éticos y legales claros:

  1. Solo datos públicos sin login. No extraigas contenido tras el muro de autenticación. El precedente hiQ v. LinkedIn (2022) respalda el scraping de datos públicos, pero no anula los ToS de la plataforma.
  2. Agrega y anonimiza. Almacena métricas agregadas (valoración media, distribución de pros/contras por departamento) en lugar de reseñas individuales con texto completo. Esto reduce el riesgo bajo GDPR, que protege los datos personales de empleados en la UE incluso si fueron publicados voluntariamente.
  3. Respeta el GDPR para datos de empleados europeos. Una reseña que menciona un nombre, una ubicación específica o un equipo pequeño puede constituir dato personal bajo el Artículo 4 del GDPR. Aplica seudonimización y minimización de datos.
  4. Considera una licencia de datos oficial. Si necesitas datos salariales completos, coberturas históricas o acceso a gran escala, una licencia de Glassdoor for Employers o un proveedor de datos de mercado laboral es la opción legalmente segura. El coste de una licencia suele ser menor que el riesgo legal de un scraping agresivo.
  5. Usa APIs oficiales cuando existan. Algunas plataformas ofrecen APIs con rate limits razonables. Si Glassdoor ofrece una API para tu caso de uso, úsala antes de recurrir al scraping.

Para más recursos sobre scraping ético y casos de uso, consulta nuestra guía de web scraping y de SERP tracking. La documentación de ProxyHat tiene ejemplos adicionales de configuración.

Puntos clave

  • Los datos públicos de Glassdoor (reseñas truncadas, valoraciones) son accesibles sin login vía el endpoint BFF GraphQL en /bff/v1/graphql.
  • DataDome + Cloudflare Bot Management requieren impersonación TLS con curl_cffi (impersonate="chrome124") y proxies residenciales.
  • El header gd-csrf-token es obligatorio para el BFF GraphQL; se extrae de la carga HTML inicial.
  • Usa sesiones sticky de ProxyHat (session-xxx) para conservar las cookies de DataDome durante la paginación.
  • Pacing de 1-3 segundos entre peticiones, máx. 2-3 concurrentes por sesión, y lógica de reintento con rotación de sesión ante HTTP 403.
  • No scrapear tras login. Agrega y anonimiza los datos. Considera una licencia oficial para datos salariales completos.

Conclusión

Scrapear Glassdoor en 2026 es factible si combinas las herramientas adecuadas: curl_cffi para fingerprinting TLS, el endpoint BFF GraphQL para datos estructurados, y proxies residenciales rotativos con sesiones sticky de ProxyHat para evadir el scoring de IP de DataDome. El resultado es un pipeline de datos de reseñas públicas que alimenta dashboards de analítica de RR.HH. sin violar ToS ni GDPR.

El siguiente paso es configurar tu cuenta de ProxyHat, elegir proxies residenciales con geo-targeting US, y adaptar el código de ejemplo al ID de empresa que necesitas analizar. Empieza con una sola empresa, valida tu tasa de éxito (>90% sin 403), y escala gradualmente con múltiples sesiones sticky.

Preguntas frecuentes

¿Es legal scrapear reseñas públicas de Glassdoor?

Scrapear datos públicos sin login se considera generalmente permitido bajo precedentes como hiQ v. LinkedIn, pero debes respetar los Términos de Servicio de Glassdoor, el CFAA en EE.UU. y el GDPR en la UE. No extraigas datos personales identificables ni accedas tras un muro de autenticación. Agrega y anonimiza los datos antes de almacenarlos.

¿Qué proxy funciona mejor para scrapear Glassdoor?

Los proxies residenciales rotativos son la mejor opción porque DataDome puntúa la reputación IP. Las IPs de datacenter suelen ser bloqueadas en las primeras peticiones. Usa sesiones sticky para mantener las cookies de DataDome válidas durante la paginación, y rota solo cuando recibas un challenge.

¿Cómo evito los bloques de DataDome en Glassdoor?

Combina TLS fingerprinting con curl_cffi (impersonación de Chrome), proxies residenciales, sesiones sticky para conservar cookies, pacing de 1-3 segundos entre peticiones, y lógica de reintento ante challenges HTTP 403. Evita patrones de tráfico predecibles y rota la sesión si detectas un bloqueo.

¿Qué datos de Glassdoor son accesibles sin login?

Sin login puedes acceder a la página general de la empresa, reseñas truncadas en /Reviews/-Reviews-E.htm, y datos estructurados vía el endpoint BFF GraphQL. Los desgloses salariales completos y las reseñas extendidas están detrás del muro de autenticación y no deben extraerse mediante scraping.

¿Qué es el endpoint BFF GraphQL de Glassdoor?

Es un endpoint interno no documentado en /bff/ que devuelve JSON estructurado con reseñas, valoraciones y metadatos. Requiere el header gd-csrf-token y opera sobre la misma infraestructura anti-bot de DataDome y Cloudflare. Devuelve datos más limpios que el HTML renderizado.

¿Listo para empezar?

Accede a más de 50M de IPs residenciales en más de 148 países con filtrado impulsado por IA.

Ver preciosProxies residenciales
← Volver al Blog