Scrapear reseñas públicas a escala es uno de los casos de uso más comunes —y más frustrantes— para equipos de investigación de mercado y monitoreo de marca. Las plataformas de reseñas implementan rate limiting agresivo, personalización geográfica y sistemas anti-bot sofisticados que bloquean rápidamente a cualquier IP que haga demasiadas peticiones. En esta guía explicamos cómo los proxies te ayudan a scrapear datos de reseñas de Trustpilot, G2 y Google Business, con ejemplos de código ejecutables usando el gateway de ProxyHat.
Aviso legal: Este artículo cubre únicamente el acceso a datos de reseñas públicamente disponibles sin necesidad de iniciar sesión. Debes respetar los Términos de Servicio de cada plataforma, el archivo
robots.txt, las leyes aplicables (CFAA en EE. UU., GDPR en la UE) y los límites de tasa razonables. No fomentamos la recolección de PII ni el scraping de datos detrás de un muro de autenticación. Cuando una plataforma ofrezca una API oficial, úsala primero.
Por qué necesitas proxies para scrapear datos de reseñas
Las páginas de reseñas no son contenido estático neutral. Cuando solicitas la página de un negocio en Trustpilot o un producto en G2, el servidor toma decisiones basadas en tu dirección IP, tus cabeceras HTTP, tu locale y tu comportamiento de navegación. Esto crea dos problemas principales para cualquier scraper que use una sola IP:
1. Rate limiting y bloqueos por IP
La mayoría de plataformas de reseñas limitan el número de peticiones por IP en ventanas de tiempo cortas. Trustpilot, por ejemplo, puede empezar a devolver respuestas 429 (Too Many Requests) o 403 después de apenas 50–100 peticiones desde la misma IP en pocos minutos. G2, que utiliza protección anti-bot más pesada, puede bloquear una IP con tan solo 20–30 peticiones sospechosas. Una vez que tu IP está en una lista negra, a menudo permanece bloqueada durante horas o días.
2. Personalización geográfica y por locale
Google Business y Google Maps filtran y ordenan las reseñas según el país y el idioma del usuario. Si accedes desde una IP de Alemania, verás un conjunto de reseñas distinto —y potencialmente traducido— al que verías desde una IP de Estados Unidos. El parámetro hl (host language) y gl (geolocation) en las URLs de Google ayudan, pero la IP del solicitante sigue influyendo en qué reseñas aparecen. Para construir un dataset consistente, necesitas IPs que coincidan con el locale que quieres capturar.
Los proxies residenciales rotativos resuelven ambos problemas: distribuyen tus peticiones entre miles de IPs reales de ISP, evitando que ninguna sola IP reciba suficientes peticiones para activar un bloqueo, y permiten fijar el país de salida para mantener un locale consistente.
Trustpilot: scrapear reseñas desde el JSON embebido
Trustpilot renderiza sus páginas de perfil de negocio con Next.js, lo que significa que cada página incluye un bloque <script id="__NEXT_DATA__"> con todo el contenido serializado en JSON. En lugar de parsear HTML frágil con selectores CSS, puedes extraer directamente el JSON estructurado: títulos, calificaciones, fechas, texto de la reseña y autor. Esto es mucho más robusto ante cambios de diseño.
La paginación funciona con el parámetro ?page=N. Cada página muestra aproximadamente 20 reseñas. Para perfiles con cientos de reseñas, necesitarás rotar IPs en cada página para evitar rate limits.
Ejemplo en Python: Trustpilot con rotación de IPs por página
import requests
import json
import re
import time
PROXY = "http://USER:PASS@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY, "https": PROXY}
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": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
}
def scrape_trustpilot(business_slug, max_pages=10):
reviews = []
for page in range(1, max_pages + 1):
url = f"https://www.trustpilot.com/review/{business_slug}?page={page}"
try:
resp = requests.get(url, headers=HEADERS, proxies=PROXIES, timeout=30)
if resp.status_code == 429:
print(f"Rate limited on page {page}, backing off...")
time.sleep(10)
continue
if resp.status_code != 200:
print(f"Page {page}: status {resp.status_code}")
break
# Extraer __NEXT_DATA__ JSON del HTML
match = re.search(
r'<script id="__NEXT_DATA__" type="application/json">(.*?)</script>',
resp.text,
re.DOTALL
)
if not match:
print(f"No __NEXT_DATA__ found on page {page}")
break
data = json.loads(match.group(1))
# Navegar la estructura de Next.js para encontrar las reseñas
props = data.get("props", {}).get("pageProps", {})
page_reviews = props.get("reviews", [])
for r in page_reviews:
reviews.append({
"title": r.get("title", ""),
"text": r.get("text", ""),
"rating": r.get("rating", ""),
"date": r.get("dates", {}).get("publishedDate", ""),
"author": r.get("consumer", {}).get("displayName", ""),
})
print(f"Page {page}: extracted {len(page_reviews)} reviews")
time.sleep(2) # cortesía entre peticiones
except Exception as e:
print(f"Error on page {page}: {e}")
break
return reviews
# Uso:
# all_reviews = scrape_trustpilot("example-company", max_pages=20)
# print(f"Total: {len(all_reviews)} reviews")
Cada petición pasa por gate.proxyhat.com:8080, que rota automáticamente la IP residencial de salida en cada solicitud. Esto significa que cada página se solicita desde una IP distinta, reduciendo drásticamente la probabilidad de un bloqueo por rate limiting.
G2: manejo de anti-bot más agresivo
G2 tiene una postura anti-bot considerablemente más estricta que Trustpilot. Utiliza detección de headers, fingerprinting del navegador y challenges de JavaScript. Para acceder a las páginas de reseñas públicas de productos, necesitas:
- IPs residenciales (no datacenter — G2 bloquea rangos de IPs de centros de datos conocidos).
- Cabeceras HTTP realistas que imiten un navegador moderno.
- Tasas de petición conservadoras (1–2 segundos entre solicitudes mínimo).
- Manejo de respuestas 403 y 429 con backoff exponencial.
Además de las reseñas individuales, las páginas de producto de G2 muestran una distribución de estrellas (cuántas reseñas de 1, 2, 3, 4 y 5 estrellas existen). Este dato agregado es valioso para análisis de sentimiento a nivel de producto.
Ejemplo en Python: G2 con IPs residenciales y cabeceras realistas
import requests
import time
import random
PROXY = "http://user-country-US:pass@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY, "https": PROXY}
REALISTIC_HEADERS = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Connection": "keep-alive",
"Upgrade-Insecure-Requests": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
}
def scrape_g2_product(product_slug, max_reviews=50):
url = f"https://www.g2.com/products/{product_slug}/reviews"
reviews = []
page = 1
while len(reviews) < max_reviews:
page_url = f"{url}?page={page}" if page > 1 else url
try:
resp = requests.get(
page_url,
headers=REALISTIC_HEADERS,
proxies=PROXIES,
timeout=30
)
if resp.status_code == 403:
print(f"Blocked (403) on page {page}. Backing off 30s...")
time.sleep(30)
continue
if resp.status_code == 429:
wait = random.uniform(15, 45)
print(f"Rate limited. Waiting {wait:.0f}s...")
time.sleep(wait)
continue
if resp.status_code != 200:
print(f"Status {resp.status_code} on page {page}. Stopping.")
break
# Parsear HTML con BeautifulSoup en producción
# Aquí mostramos la lógica de rotación y manejo de errores
print(f"Page {page}: status {resp.status_code}, {len(resp.text)} bytes")
# ... parse HTML para extraer reseñas y distribución de estrellas ...
page += 1
time.sleep(random.uniform(2, 4)) # tasa conservadora
except requests.exceptions.RequestException as e:
print(f"Connection error: {e}")
time.sleep(10)
return reviews
# Uso:
# reviews = scrape_g2_product("slack", max_reviews=100)
Aquí usamos user-country-US en el nombre de usuario para fijar la IP residencial a Estados Unidos, lo que evita que G2 muestre versiones localizadas o redirija a otra región.
Google Business y Maps: reseñas afectadas por geo y locale
Google Business y Google Maps presentan un desafío único: las reseñas que aparecen para un negocio dependen de la ubicación del solicitante y de los parámetros hl (idioma) y gl (país) en la URL. Una búsqueda del mismo negocio desde una IP española puede mostrar un subconjunto distinto de reseñas —o las mismas reseñas traducidas— que desde una IP estadounidense.
Para construir un dataset consistente de reseñas de Google Business:
- Fija el país de la IP residencial con
user-country-US(o el país que necesites). - Incluye
&hl=en&gl=usen la URL para forzar el idioma y la región. - Usa sesiones sticky para mantener la misma IP durante toda la paginación de un negocio.
Ejemplo en Python: Google Business con sesión sticky y geo-targeting
import requests
import time
# Sesión sticky: misma IP durante toda la sesión
# Country US + session fija para consistencia de locale
PROXY = "http://user-country-US-session-googlebiz-001:pass@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY, "https": PROXY}
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",
}
def scrape_google_business_reviews(place_id, max_pages=5):
"""
Scrapea reseñas públicas de Google Business.
place_id: el identificador de lugar de Google (ChIJ...)
"""
all_reviews = []
for page in range(max_pages):
url = (
f"https://www.google.com/maps/place/?q=place_id:{place_id}"
f"&hl=en&gl=us"
)
try:
resp = requests.get(
url,
headers=HEADERS,
proxies=PROXIES,
timeout=30
)
if resp.status_code != 200:
print(f"Page {page}: status {resp.status_code}")
break
# En producción: parsear el HTML o los datos embebidos
# Google usa datos embebidos en window.APP_INITIALIZATION_STATE
print(f"Page {page}: {len(resp.text)} bytes received")
# ... extraer reseñas del contenido ...
time.sleep(3)
except Exception as e:
print(f"Error on page {page}: {e}")
break
return all_reviews
# Uso:
# reviews = scrape_google_business_reviews("ChIJN1t_tDeuEmsRUsoyG83frY4")
El flag -session-googlebiz-001 asegura que ProxyHat mantenga la misma IP residencial para todas las peticiones dentro de esa sesión. Esto es crítico para Google: si la IP cambia a mitad de la paginación, Google puede devolver un subconjunto distinto de reseñas o redirigir a otra versión localizada, corrompiendo tu dataset.
Node.js: scraper de reseñas con rotación de proxies
Para equipos que trabajan en JavaScript/TypeScript, aquí hay un ejemplo equivalente usando axios con el proxy de ProxyHat:
const axios = require('axios');
const HttpsProxyAgent = require('https-proxy-agent');
const PROXY_URL = 'http://user-country-DE:pass@gate.proxyhat.com:8080';
const agent = new HttpsProxyAgent.HttpsProxyAgent(PROXY_URL);
const HEADERS = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'de-DE,de;q=0.9,en;q=0.7',
};
async function scrapeReviews(baseUrl, maxPages = 10) {
const allReviews = [];
for (let page = 1; page <= maxPages; page++) {
const url = `${baseUrl}?page=${page}`;
try {
const resp = await axios.get(url, {
httpsAgent: agent,
headers: HEADERS,
timeout: 30000,
});
if (resp.status === 429) {
console.log(`Rate limited on page ${page}. Backing off 15s...`);
await new Promise(r => setTimeout(r, 15000));
continue;
}
console.log(`Page ${page}: ${resp.data.length} bytes`);
// Parsear resp.data según la plataforma destino
// allReviews.push(...parsedReviews);
await new Promise(r => setTimeout(r, 2000));
} catch (err) {
console.error(`Error on page ${page}: ${err.message}`);
break;
}
}
return allReviews;
}
// Uso:
// scrapeReviews('https://www.trustpilot.com/review/example-company', 15)
// .then(r => console.log(`Total: ${r.length} reviews`));
Comparación de estrategias de proxy para scraping de reseñas
| Estrategia | Ideal para | Ventajas | Desventajas |
|---|---|---|---|
| Rotación por petición (sin sesión) | Trustpilot, páginas independientes | Máxima distribución de IPs, mínimo riesgo de bloqueo por IP | No mantiene estado entre peticiones; puede ver contenido localizado distinto |
| Sesión sticky (-session-ID) | Google Business, paginación multi-página | Consistencia de locale y contenido durante toda una sesión | La misma IP acumula peticiones; requiere pausas más largas |
| Geo-targeting por país (-country-XX) | Google Maps, G2, cualquier plataforma con contenido geo-dependiente | Reseñas consistentes para la región objetivo | Menor pool de IPs por país; países pequeños pueden tener menos IPs disponibles |
| Geo-targeting por ciudad (-country-XX-city-yyy) | Casos de uso hiperlocales (reseñas de restaurantes por ciudad) | Máxima precisión geográfica | Pool de IPs aún más pequeño; mayor latencia potencial |
Errores comunes y casos límite
No respetar el rate limiting implícito
Incluso con proxies rotativos, bombardear una plataforma con 100 peticiones por segundo es contraproducente. Las plataformas detectan patrones de comportamiento anómalos más allá de la IP: timing de peticiones, ausencia de recursos secundarios (CSS, imágenes), headers inconsistentes. Mantén un delay de 2–5 segundos entre peticiones y añade jitter aleatorio.
Usar proxies datacenter para plataformas con protección avanzada
G2 y Google filtran activamente rangos de IPs de centros de datos conocidos (AWS, DigitalOcean, OVH). Una IP datacenter puede ser bloqueada antes de hacer una sola petición útil. Los proxies residenciales cuestan más, pero son la única opción fiable para estas plataformas. Consulta las recomendaciones de caching HTTP del RFC 7234 para entender cómo las plataformas gestionan respuestas a diferentes clientes.
Ignorar la estructura de datos embebidos
Trustpilot usa __NEXT_DATA__, Google usa window.APP_INITIALIZATION_STATE, y muchas plataformas modernas embebden datos en JSON dentro del HTML. Parsear selectores CSS es frágil y se rompe con cada rediseño. Extraer el JSON embebido es más robusto y te da acceso a metadatos que no están visibles en el HTML renderizado. La documentación de MDN sobre HTMLScriptElement explica cómo los navegadores procesan estos bloques.
No manejar redirecciones y contenido localizado
Si tu IP es de Alemania y solicitas una página de G2 sin fijar el locale, G2 puede redirigirte a una versión alemana del sitio. Esto cambia la estructura de la URL y potencialmente el contenido. Fija siempre el país con user-country-XX y usa los parámetros de locale en la URL cuando estén disponibles.
Configuración específica de ProxyHat
ProxyHat ofrece proxies residenciales, móviles y datacenter. Para scraping de reseñas, recomendamos residenciales por las razones explicadas arriba. La configuración es simple: todo se controla desde el nombre de usuario en la URL del proxy.
Rotación automática (cada petición usa una IP distinta)
http://user:pass@gate.proxyhat.com:8080
Geo-targeting por país
http://user-country-US:pass@gate.proxyhat.com:8080
http://user-country-DE:pass@gate.proxyhat.com:8080
http://user-country-GB:pass@gate.proxyhat.com:8080
Sesión sticky (misma IP durante toda la sesión)
http://user-session-myprofile123:pass@gate.proxyhat.com:8080
Combinar país + sesión sticky
http://user-country-US-session-biz456:pass@gate.proxyhat.com:8080
Para más detalles sobre los parámetros disponibles, consulta la documentación oficial de ProxyHat. Puedes ver todas las ubicaciones disponibles en nuestra página de ubicaciones y comparar planes en nuestra página de precios.
Si quieres profundizar en casos de uso relacionados, revisa nuestras guías sobre web scraping con proxies y seguimiento de SERPs.
Cuándo usar APIs oficiales en lugar de scraping
Antes de invertir en infraestructura de scraping, evalúa si la plataforma ofrece una API oficial:
- Google Maps Platform ofrece la Places API que incluye reseñas, con un límite gratuito de 200 USD/mes en créditos. Es la opción más fiable para reseñas de Google Business.
- Trustpilot tiene una API de negocio para empresas que gestionan su propio perfil, pero no permite acceder a reseñas de terceros.
- G2 no ofrece una API pública de reseñas; el scraping es la única vía para datos agregados de productos de terceros.
Cuando una API oficial cubre tus necesidades, úsala. Es más estable, legalmente clara y no requiere mantener infraestructura de proxies. Cuando no exista una API —o sea prohibitivamente cara— el scraping con proxies residenciales es una alternativa legítima para datos públicos, siempre que respetes los Términos de Servicio y los límites razonables.
Conclusiones clave
Key Takeaways:
- Las plataformas de reseñas implementan rate limiting por IP y personalización geográfica que hacen imposible el scraping a escala desde una sola IP.
- Trustpilot embebe datos en
__NEXT_DATA__; extraer ese JSON es más robusto que parsear HTML.- G2 requiere proxies residenciales (no datacenter) y cabeceras HTTP realistas para evitar bloqueos 403.
- Google Business muestra reseñas distintas según la IP y el locale; usa sesiones sticky con geo-targeting para datasets consistentes.
- Usa rotación por petición para páginas independientes y sesiones sticky para perfiles multi-página.
- Evalúa siempre las APIs oficiales primero; el scraping es la alternativa cuando no hay API o es inviable económicamente.






