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

Guía práctica para scrapear reseñas públicas y datos salariales de Glassdoor en 2026 usando proxies residenciales rotativos, endpoints GraphQL BFF y mitigación de DataDome.

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

Aviso legal: Este artículo cubre únicamente el acceso a datos públicos de Glassdoor. Debes respetar los Términos de Servicio de Glassdoor y las leyes aplicables, incluyendo la Computer Fraud and Abuse Act (CFAA) en EE.UU. y el GDPR en la UE. No recomendamos ni cubrimos el scraping detrás de muros de autenticación. Consulta con un abogado antes de desplegar cualquier pipeline de scraping a escala.

Si construyes pipelines de analítica de RR.HH. o datos de mercado laboral, probablemente te has preguntado cómo scrapear Glassdoor de forma fiable. Glassdoor aloja millones de reseñas de empleados, datos salariales y valoraciones de empresas, pero su infraestructura anti-bot —DataDome combinado con Cloudflare— hace que el scraping naïf con requests falle en minutos. Esta guía explica qué datos son públicos, cómo funciona el stack anti-bot de Glassdoor, y cómo usar proxies residenciales rotativos con el endpoint GraphQL BFF para construir un Glassdoor reviews scraper robusto en 2026.

Cómo scrapear reseñas y salarios de Glassdoor en 2026: el panorama

Glassdoor protege activamente sus datos con múltiples capas de defensa. En 2026, el stack incluye DataDome para scoring de IP y comportamiento, Cloudflare Bot Management para challenges de JavaScript, y fingerprinting TLS para distinguir navegadores reales de scripts. Un scraper que funcione necesita tres piezas: proxies residenciales de alta confianza, impersonación TLS de navegador, y conocimiento de los endpoints GraphQL internos que devuelven JSON estructurado en lugar de HTML.

Qué es accesible sin login vs. detrás de autenticación

Antes de escribir código, es crítico entender la frontera de datos:

Tipo de datoAcceso sin loginRequiere login
Descripción general de empresa
Reseñas truncadas (pros, contras, rating)Sí (parcial)Reseña completa
Rating general (ratingOverall)
Desglose salarial completoNo
Detalles de entrevistasParcial
Fotos de oficinas

Las URLs públicas siguen el patrón /Reviews/<empresa>-Reviews-E<id>.htm. En estas páginas puedes ver reseñas truncadas con el título del puesto, rating general, y fragmentos de pros/contras. Los datos salariales de Glassdoor completos —desglose por cargo, ubicación, antigüedad— están detrás de un muro de autenticación. Esta guía se limita exclusivamente a datos públicos accesibles sin login.

El stack anti-bot de Glassdoor: DataDome + Cloudflare

Glassdoor delega su defensa a dos sistemas complementarios:

  • DataDome: analiza la reputación de IP, patrones de comportamiento, headers HTTP y fingerprints del navegador. Asigna un score a cada visita; si el score supera un umbral, devuelve un challenge o bloquea directamente. Según la documentación de DataDome, su sistema procesa decisiones en menos de 50ms usando machine learning en tiempo real.
  • Cloudflare Bot Management: añade challenges de JavaScript, fingerprinting TLS (JA3/JA4) y análisis de reputación de IP. Puedes leer más sobre su enfoque en la página oficial de Cloudflare Bot Management.

El resultado: un curl simple o requests.get() recibe un 403 o un challenge HTML en lugar de los datos. El fingerprint TLS de librerías HTTP estándar (Python requests, Node.js axios) no coincide con ningún navegador real, y DataDome lo detecta al instante.

Por qué necesitas curl_cffi

La solución es curl_cffi, una librería Python que usa curl-impersonate para reproducir el handshake TLS exacto de Chrome o Firefox. Esto significa que el JA3/JA4 fingerprint de tu petición es indistinguible del de un navegador Chrome real. Sin esto, DataDome bloqueará tus requests sin importar cuántos proxies uses.

pip install curl_cffi

El endpoint GraphQL BFF de Glassdoor

Glassdoor usa una arquitectura BFF (Backend-for-Frontend) con endpoints GraphQL que devuelven JSON estructurado. Los endpoints relevantes son:

  • https://www.glassdoor.com/bff/graphql — endpoint principal para reseñas y datos de empresa.
  • https://www.glassdoor.com/graph — endpoint GraphQL alternativo para ciertas queries.

Estos endpoints no están documentados públicamente. Para descubrir las operaciones disponibles, puedes inspeccionar el tráfico de red en las DevTools del navegador (pestaña Network, filtrar por "graphql"). Las peticiones incluyen un header gd-csrf-token que se genera en el cliente y debe acompañar cada request.

Las ventajas del endpoint GraphQL sobre el HTML scraping son significativas:

  • JSON estructurado en lugar de parsear HTML frágil.
  • Campos como ratingOverall, pros, cons, jobTitle vienen tipados.
  • Paginación mediante cursores en lugar de extraer URLs de "siguiente página".
  • Menos ancho de banda: pides solo los campos que necesitas.

Por qué los proxies residenciales rotativos vencen a DataDome

DataDome asigna scores de confianza por IP. Las IPs de datacenters (AWS, DigitalOcean, OVH) tienen scores bajísimos porque DataDome las marca como Known Bot Networks. Las IPs residenciales, en cambio, provienen de ISP reales (Comcast, AT&T, Movistar) y tienen scores de confianza altos porque DataDome las trata como usuarios legítimos.

Al rotar IPs residenciales en cada petición o sesión, distribuyes el load y evitas que una sola IP acumule suficientes requests para disparar un alerta de comportamiento. ProxyHat ofrece ubicaciones en más de 190 países con IPs residenciales reales, ideales para este caso de uso.

Implementación: scrapear reseñas con Python y ProxyHat

A continuación, un ejemplo completo en Python que consulta el endpoint BFF GraphQL de Glassdoor a través de un proxy residencial ProxyHat con impersonación TLS de Chrome.

from curl_cffi import requests
import json
import time

# Proxy residencial ProxyHat con sesión sticky y geo-targeting US
proxy_url = "http://user-country-US-session-rev001:PASSWORD@gate.proxyhat.com:8080"

headers = {
    "gd-csrf-token": "TU_CSRF_TOKEN",
    "content-type": "application/json",
    "accept": "application/json",
    "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",
    "referer": "https://www.glassdoor.com/Reviews/",
}

payload = {
    "operationName": "EmployerReviews",
    "variables": {
        "employerId": 12345,
        "limit": 10,
        "cursor": None
    },
    "query": """
        query EmployerReviews($employerId: Int!, $limit: Int, $cursor: String) {
          employer(id: $employerId) {
            reviews(limit: $limit, cursor: $cursor) {
              nodes {
                id
                ratingOverall
                pros
                cons
                jobTitle
                date
              }
              pageInfo {
                nextCursor
                hasNextPage
              }
            }
          }
        }
    """
}

def fetch_reviews(employer_id, max_pages=20):
    cursor = None
    all_reviews = []
    
    for page in range(max_pages):
        payload["variables"]["cursor"] = cursor
        payload["variables"]["employerId"] = employer_id
        
        try:
            r = requests.post(
                "https://www.glassdoor.com/bff/graphql",
                json=payload,
                headers=headers,
                proxies={"http": proxy_url, "https": proxy_url},
                impersonate="chrome",
                timeout=30,
            )
            
            if r.status_code == 403:
                print(f"Bloqueado en página {page}. Rotando IP...")
                # Nueva sesión = nueva IP residencial
                time.sleep(5)
                continue
            
            data = r.json()
            reviews = data["data"]["employer"]["reviews"]
            
            for node in reviews["nodes"]:
                all_reviews.append({
                    "id": node["id"],
                    "rating": node["ratingOverall"],
                    "pros": node["pros"],
                    "cons": node["cons"],
                    "jobTitle": node["jobTitle"],
                    "date": node["date"],
                })
            
            if not reviews["pageInfo"]["hasNextPage"]:
                break
            
            cursor = reviews["pageInfo"]["nextCursor"]
            time.sleep(2)  # Pacing: 1 request cada 2 segundos
            
        except Exception as e:
            print(f"Error en página {page}: {e}")
            time.sleep(10)
    
    return all_reviews

reviews = fetch_reviews(employer_id=12345, max_pages=20)
print(f"Total reseñas extraídas: {len(reviews)}")
print(json.dumps(reviews[0], indent=2, ensure_ascii=False))

Este script extrae reseñas truncadas públicas (rating, pros, cons, jobTitle) sin necesidad de login. La sesión sticky (session-rev001) mantiene la misma IP durante toda la paginación, preservando las cookies de DataDome. Si una petición recibe 403, el script espera y reintenta con la misma sesión o puedes cambiar el identificador de sesión para obtener una IP nueva.

Ejemplo en Node.js

Para equipos de JavaScript, aquí hay un equivalente usando undici con ProxyAgent:

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

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

async function fetchReviews(employerId, cursor = null) {
  const payload = {
    operationName: 'EmployerReviews',
    variables: { employerId, limit: 10, cursor },
    query: `query EmployerReviews($employerId: Int!, $limit: Int, $cursor: String) {
      employer(id: $employerId) {
        reviews(limit: $limit, cursor: $cursor) {
          nodes { id ratingOverall pros cons jobTitle date }
          pageInfo { nextCursor hasNextPage }
        }
      }
    }`
  };

  const res = await request('https://www.glassdoor.com/bff/graphql', {
    method: 'POST',
    headers: {
      'gd-csrf-token': 'TU_CSRF_TOKEN',
      'content-type': 'application/json',
      'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
    },
    body: JSON.stringify(payload),
    dispatcher: agent
  });

  const data = await res.body.json();
  return data.data.employer.reviews;
}

fetchReviews(12345).then(reviews => {
  console.log(`Reseñas obtenidas: ${reviews.nodes.length}`);
  console.log(reviews.nodes[0]);
});

Nota: Node.js no tiene una librería equivalente a curl_cffi tan madura. Para producción en Node.js, considera usar la documentación de ProxyHat junto con una librería de impersonación TLS como node-tls-client.

Paginación, sesiones sticky y pacing

Cursores de paginación

El endpoint GraphQL usa paginación por cursor. Cada respuesta incluye pageInfo.nextCursor y pageInfo.hasNextPage. Pasa el cursor en la siguiente petición para avanzar. No intentes paginar con offsets numéricos; los cursores son opacos y deben tratarse como strings no modificables.

Sesiones sticky para mantener cookies de DataDome

DataDome emite cookies de sesión que se asocian a una IP. Si rotas IP en cada request, DataDome ve una cookie de una IP previa en una IP nueva y puede desafiar. La solución es usar sesiones sticky: el mismo identificador de sesión en el username de ProxyHat mantiene la misma IP residencial durante un período configurable.

# Sesión sticky: misma IP durante toda la sesión
proxy_url = "http://user-country-US-session-mi-sesion-001:PASSWORD@gate.proxyhat.com:8080"

Cuando necesites rotar (por ejemplo, tras un 403), cambia el identificador de sesión:

# Nueva sesión = nueva IP residencial
proxy_url = "http://user-country-US-session-mi-sesion-002:PASSWORD@gate.proxyhat.com:8080"

Pacing y rate limiting

El pacing es crítico. Recomendaciones basadas en experiencia:

  • 1-2 requests por segundo por sesión/IP.
  • 5-10 segundos de pausa entre páginas de resultados.
  • Backoff exponencial tras errores 429 o 403: empieza en 10s, duplica hasta 120s.
  • Concurrencia limitada: no más de 5-10 sesiones simultáneas desde IPs diferentes.
  • Jitter aleatorio: añade ±0.5s a cada pausa para evitar patrones detectables.

Lógica de reintento ante challenges

import random

def retry_with_backoff(func, max_retries=5):
    for attempt in range(max_retries):
        try:
            result = func()
            if result and result.status_code != 403:
                return result
        except Exception:
            pass
        
        wait_time = min(10 * (2 ** attempt), 120) + random.uniform(0, 1)
        print(f"Reintento {attempt + 1}: esperando {wait_time:.1f}s")
        time.sleep(wait_time)
    
    return None

Errores comunes y casos límite

  • Usar proxies de datacenter: DataDome los bloquea en segundos. Usa residenciales.
  • Olvidar el header gd-csrf-token: el endpoint GraphQL devuelve 403 sin él. Inspecciona el tráfico de red para obtener uno válido.
  • No impersonar TLS: sin curl_cffi o equivalente, el JA3 fingerprint delata tu script.
  • Rotar IP en cada request dentro de una sesión: rompe las cookies de DataDome. Usa sesiones sticky.
  • Scrapear a alta velocidad: 10+ requests/segundo garantiza un bloqueo. Limita a 1-2/segundo.
  • Ignorar el robots.txt: revisa siempre https://www.glassdoor.com/robots.txt antes de empezar.
  • No manejar respuestas vacías: Glassdoor a veces devuelve JSON válido pero con nodos vacíos. Valida hasNextPage antes de continuar.

Configuración de ProxyHat

ProxyHat proporciona proxies residenciales rotativos accesibles vía gateway único. La configuración para Glassdoor:

ParámetroValor recomendado
Tipo de proxyResidencial rotativo
Gatewaygate.proxyhat.com:8080 (HTTP)
SOCKS5gate.proxyhat.com:1080
Geo-targetingUS (mayoría de empresas en Glassdoor)
SesiónSticky por empresa scrapeada
RotaciónAl detectar 403 o tras N requests
Concurrencia5-10 sesiones simultáneas

Consulta las opciones de pricing de ProxyHat para elegir el plan adecuado según tu volumen. Para casos de uso de web scraping a escala, revisa nuestra página de uso de web scraping y para tracking de SERPs, la guía de SERP tracking.

Scraping ético y cuándo usar APIs oficiales

El scraping de Glassdoor plantea consideraciones éticas y legales serias:

Principios éticos

  • Solo datos públicos: limita tu scraping a información accesible sin login. No extraigas datos detrás de autenticación.
  • Agrega, no individualices: para analítica de mercado laboral, agrega reseñas por empresa, sector o región. No publiques datos que identifiquen a individuos.
  • Respeta robots.txt: si Glassdoor prohíbe una ruta en su robots.txt, no la scrapees.
  • Limita la velocidad: tu scraper no debe degradar la experiencia de otros usuarios del sitio.
  • GDPR para datos de la UE: las reseñas de empleados pueden contener datos personales indirectamente identificables. Si procesas datos de empresas europeas, necesitas una base legal bajo el GDPR y debes evaluar si los datos constituyen información personal.

Cuándo una licencia de datos oficial es la opción correcta

Si tu caso de uso es comercial, a gran escala, o requiere datos salariales completos (que están detrás de login), una licencia de datos oficial de Glassdoor es la opción apropiada. Glassdoor ofrece programas de partnerships de datos para empresas. Las ventajas incluyen:

  • Acceso legal y conforme a los ToS.
  • Datos completos, incluyendo salarios y detalles de entrevistas.
  • Soporte y SLAs de disponibilidad.
  • Sin riesgo de bloqueos o litigios.

El scraping con proxies es ideal para prototipado, investigación, y analítica de datos públicos a escala moderada. Para producción comercial a escala, evalúa la licencia oficial.

Puntos clave

Datos públicos únicamente: Las reseñas truncadas y ratings generales son accesibles sin login en /Reviews/. Los datos salariales completos requieren autenticación y no deben extraerse vía scraping.

Stack anti-bot: DataDome + Cloudflare Bot Management usan scoring de IP, fingerprinting TLS y challenges de JS. Necesitas proxies residenciales + curl_cffi para impersonación TLS.

Endpoint GraphQL BFF: /bff/graphql devuelve JSON estructurado. Requiere header gd-csrf-token. Descubre las operaciones inspeccionando el tráfico de red.

Sesiones sticky: Mantén la misma IP durante la paginación para preservar cookies de DataDome. Rota solo tras bloqueos.

Pacing: 1-2 requests/segundo, backoff exponencial tras 403, jitter aleatorio. La paciencia vence a DataDome.

Ética: Agrega datos, no identifiques individuos, respeta robots.txt, y considera una licencia oficial para uso comercial a escala.

Conclusión

Scrapear Glassdoor en 2026 es factible si combinas las herramientas correctas: proxies residenciales rotativos de ProxyHat, impersonación TLS con curl_cffi, y el endpoint GraphQL BFF no documentado. La clave está en comportarte como un usuario real: IP residencial, fingerprint de navegador, pacing humano y sesiones persistentes. Para datos públicos de reseñas, este enfoque funciona de forma fiable. Para datos salariales completos o uso comercial a escala, la opción ética y legal es una licencia de datos oficial.

Si estás listo para empezar, explora los planes de ProxyHat y configura tu primer scraper residencial hoy. Para más guías técnicas, visita nuestra documentación completa.

¿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