Por qué scrapear Google Shopping en 2026 sigue siendo necesario
Si has intentado obtener precios competitivos de Google Shopping, ya sabes el primer obstáculo: la Content API for Shopping de Google solo devuelve los productos del propio comerciante. No hay un endpoint oficial que te diga qué precio tiene tu competidor en un producto específico. Para inteligencia competitiva, monitoreo de precios y análisis de mercado, la única vía práctica es parsear el HTML público de las páginas de resultados de Google Shopping o las fichas de producto.
Scrapear Google Shopping en 2026 significa extraer datos de la SERP de tbm=shop: títulos de producto, precios, vendedores, valoraciones, número de reseñas y enlaces a ofertas. Es un trabajo técnico exigente porque Google ha endurecido su stack anti-bot, pero con proxies residenciales bien configurados y selectores actualizados, es completamente factible a escala.
En esta guía cubrimos el flujo completo: desde el trade-off API vs HTML, los selectores CSS reales que funcionan hoy, el anti-bot que vas a encontrar, la geo-localización de precios y código Python listo para ejecutar con ProxyHat.
API vs HTML: el trade-off fundamental
Google ofrece varias APIs relacionadas con Shopping, pero ninguna resuelve el caso de uso competitivo:
- Content API for Shopping: gestiona el inventario propio del comerciante. No expone productos de terceros.
- Shopping Ads API: para gestionar campañas publicitarias, no para extraer datos orgánicos.
- Custom Search JSON API: permite buscar en la web general, pero no soporta
tbm=shopy tiene un límite de 100 consultas/día en el tier gratuito.
Esto deja el scraping del HTML como la opción realista. La URL base para resultados de Shopping es:
https://www.google.com/search?tbm=shop&q=QUERY&gl=US&hl=en
El parámetro tbm=shop activa la pestaña de Shopping. Los parámetros gl (geolocalización del país) y hl (idioma) controlan qué resultados y precios ves. Una búsqueda sin estos parámetros devuelve resultados basados en la IP del solicitante, lo que puede ser útil o problemático según tu caso.
Para fichas de producto individuales con comparativa de vendedores, Google usa URLs del patrón:
https://www.google.com/shopping/product/PRODUCT_ID/reviews
https://www.google.com/shopping/product/PRODUCT_ID
Estas páginas de detalle contienen el panel de ofertas de vendedores (seller offers), donde aparecen todos los retailers que venden el mismo producto con sus precios individuales.
El stack anti-bot de Google: qué vas a encontrar
Google protege sus SERPs con múltiples capas. Entenderlas es esencial para diseñar un scraper que no muera a los 50 requests.
1. Rate limits agresivos por IP
Google no publica umbrales oficiales, pero la experiencia práctica muestra que una IP datacenter que hace más de 20-30 peticiones por minuto a /search recibe un bloqueo temporal o un desafío CAPTCHA. Las IPs residenciales toleran más volumen porque Google las trata como usuarios reales, pero incluso estas tienen límites si el patrón de acceso es claramente automatizado.
2. Redirección sorry/index (soft-block)
Antes de un CAPTCHA explícito, Google suele redirigir a URLs como https://www.google.com/sorry/index?continue=... o devuelve una página con un mensaje de "tráfico inusual". Esta es la señal de soft-block: aún no hay CAPTCHA, pero si sigues pidiendo desde la misma IP, lo habrá. Un scraper bien diseñado detecta esta redirección y cambia de IP inmediatamente.
3. reCAPTCHA Enterprise
Google integra reCAPTCHA Enterprise en sus SERPs. Cuando se activa, la página contiene un iframe de recaptcha/api2 o un formulario de validación. Resolver reCAPTCHA de Google desde un scraper es impracticable y caro; la estrategia correcta es nunca llegar a este punto rotando IPs y controlando la frecuencia.
4. Fingerprinting del navegador
Google analiza headers, TLS fingerprint, orden de cabeceras y comportamiento JavaScript. Un requests.get() con headers mínimos es sospechoso. Usar curl_cffi o Playwright con fingerprints realistas mejora significativamente la tasa de éxito.
Selectores CSS y XPath para Google Shopping
Los selectores de Google cambian con frecuencia. Los siguientes son los que funcionan a inicios de 2026, pero siempre debes verificarlos contra el HTML actual antes de desplegar en producción.
Página de resultados (tbm=shop)
| Dato | Selector CSS | Notas |
|---|---|---|
| Contenedor de resultados | .sh-dgr__content | Envuelve cada producto en la grilla |
| Resultados de producto | .sh-pr__product-results | Lista principal de productos |
| Título del producto | h3.sh-t__title o .tAxDx | Puede variar entre layouts A/B |
| Precio | .a8Pemb | Texto con símbolo de moneda |
| Vendedor | .aULzUe o [aria-label*="sold by"] | Nombre del retailer |
| Valoración | .Rsc7Yb | Texto numérico (ej: "4.5") |
| Número de reseñas | .qz2Rmb | Texto entre paréntesis |
| Enlace al producto | a.sh-btn__contain | URL a /shopping/product/ |
Página de detalle (/shopping/product/)
| Dato | Selector CSS | Notas |
|---|---|---|
| Panel de ofertas | .sh-o__offers-list | Lista de vendedores con precios |
| Precio por vendedor | .O2FWRc | Una entrada por retailer |
| Nombre del vendedor | .dVZi6d | Texto del retailer |
| Coste de envío | .OkVind | Puede ser "Gratis" o un importe |
Consejo práctico: Google sirve diferentes layouts según el país, el dispositivo (mobile vs desktop) y el experimento A/B activo. Siempre parsea con selectores y fallbacks con regex. No dependas de un único selector.
Por qué los precios localizados exigen proxies residenciales con geo-ciudad
Un comprador en Estados Unidos y un comprador en Alemania ven vendedores, precios y monedas diferentes en Google Shopping para el mismo producto. Esto no es solo por el parámetro gl: Google también usa la IP del solicitante para inferir ubicación y servir resultados localizados. Si haces la petición desde una IP datacenter de Frankfurt con gl=US, Google puede ignorar el parámetro o servir resultados híbridos.
Para obtener precios auténticos por mercado necesitas:
- IPs residenciales del país objetivo: que la IP esté asignada por un ISP real del país.
- Geo-targeting a nivel ciudad cuando sea relevante: precios y disponibilidad pueden variar dentro de un mismo país.
- Parámetros
glyhlconsistentes con la ubicación de la IP.
Con ProxyHat, esto se configura directamente en el username del proxy:
# Comprador en EE.UU.
http://user-country-US:pass@gate.proxyhat.com:8080
# Comprador en Berlín, Alemania
http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080
# Sesión pegajosa para mantener la misma IP entre peticiones
http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080
El parámetro session-abc123 mantiene la misma IP para todas las peticiones con ese identificador, lo que es útil cuando necesitas paginar resultados sin que Google detecte un cambio de IP sospechoso entre páginas.
Puedes ver todas las ubicaciones disponibles en nuestra página de ubicaciones de proxies.
Implementación en Python: scraper de Google Shopping con ProxyHat
A continuación, un ejemplo completo que hace una petición a Google Shopping a través de ProxyHat, parsea un bloque de resultado truncado y extrae título, precio, vendedor y valoración.
import requests
from bs4 import BeautifulSoup
import random
import time
import urllib.parse
# Configuración del proxy ProxyHat (residencial, EE.UU.)
PROXY_HOST = "gate.proxyhat.com"
PROXY_PORT = "8080"
PROXY_USER = "user-country-US"
PROXY_PASS = "tu_password"
PROXY_URL = f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}"
proxies = {
"http": PROXY_URL,
"https": PROXY_URL,
}
# Headers realistas (desktop Chrome en EE.UU.)
HEADERS = {
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/121.0.0.0 Safari/537.36"
),
"Accept-Language": "en-US,en;q=0.9",
"Accept": (
"text/html,application/xhtml+xml,application/xml;"
"q=0.9,image/webp,*/*;q=0.8"
),
}
def build_shop_url(query, gl="US", hl="en"):
q = urllib.parse.quote(query)
return f"https://www.google.com/search?tbm=shop&q={q}&gl={gl}&hl={hl}"
def detect_soft_block(response):
"""Detecta redirección a sorry/index o página de bloqueo."""
if "sorry/index" in response.url:
return True
if "unusual traffic" in response.text.lower():
return True
if "recaptcha" in response.text.lower():
return True
return False
def parse_shopping_results(html):
soup = BeautifulSoup(html, "html.parser")
results = []
# Contenedores de producto
containers = soup.select(".sh-dgr__content")
for container in containers:
item = {}
# Título
title_el = container.select_one("h3.sh-t__title") or \
container.select_one(".tAxDx")
item["title"] = title_el.get_text(strip=True) if title_el else None
# Precio
price_el = container.select_one(".a8Pemb")
item["price"] = price_el.get_text(strip=True) if price_el else None
# Vendedor
seller_el = container.select_one(".aULzUe")
item["seller"] = seller_el.get_text(strip=True) if seller_el else None
# Valoración
rating_el = container.select_one(".Rsc7Yb")
item["rating"] = rating_el.get_text(strip=True) if rating_el else None
if item["title"] and item["price"]:
results.append(item)
return results
def scrape_google_shopping(query, gl="US", hl="en"):
url = build_shop_url(query, gl, hl)
try:
response = requests.get(
url,
headers=HEADERS,
proxies=proxies,
timeout=30,
allow_redirects=True,
)
if detect_soft_block(response):
print(f"[SOFT-BLOCK] Detectado en query: {query}")
print(f"URL final: {response.url}")
return []
if response.status_code != 200:
print(f"[HTTP {response.status_code}] Query: {query}")
return []
results = parse_shopping_results(response.text)
print(f"[OK] {len(results)} productos para: {query}")
return results
except requests.exceptions.RequestException as e:
print(f"[ERROR] {e}")
return []
# Ejemplo de uso
if __name__ == "__main__":
query = "wireless headphones bose"
results = scrape_google_shopping(query, gl="US", hl="en")
for r in results[:5]:
print(f" Título: {r['title']}")
print(f" Precio: {r['price']}")
print(f" Vendedor: {r.get('seller', 'N/A')}")
print(f" Rating: {r.get('rating', 'N/A')}")
print(" ---")
Salida truncada esperada:
[OK] 23 productos para: wireless headphones bose
Título: Bose QuietComfort Wireless Headphones
Precio: $349.00
Vendedor: Bose
Rating: 4.6
---
Título: Bose SoundLink Around Ear Wireless Headphones II
Precio: $199.00
Vendedor: Amazon
Rating: 4.5
---
Este ejemplo usa el gateway HTTP de ProxyHat en gate.proxyhat.com:8080. Si prefieres SOCKS5 para mayor compatibilidad con ciertos entornos, el puerto es 1080:
socks5://user-country-US:tu_password@gate.proxyhat.com:1080
Scraping desde Alemania: ejemplo con geo-ciudad
Para obtener precios en euros desde el mercado alemán, cambia el país en el username y los parámetros gl/hl:
PROXY_USER = "user-country-DE-city-berlin"
PROXY_PASS = "tu_password"
PROXY_URL = f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}"
# En la llamada:
results = scrape_google_shopping(
"kabellose kopfhörer bose",
gl="DE",
hl="de",
)
Aquí la IP residencial de Berlín, combinada con gl=DE y hl=de, asegura que Google sirva resultados con vendedores europeos y precios en euros. La consulta también está en alemán para maximizar la relevancia.
Paginación, batching y gestión de rate limits
Un scraper de Google Shopping a escala necesita más que una sola petición. Estas son las prácticas que funcionan en producción.
Paginación
Google Shopping pagina con el parámetro start (offset de resultados). Para la página 2: &start=20, página 3: &start=40. El número de resultados por página suele ser 20-40. No todas las queries tienen la misma profundidad; algunas terminan en la página 3-4.
def scrape_all_pages(query, max_pages=5, gl="US", hl="en"):
all_results = []
for page in range(max_pages):
start = page * 20
url = build_shop_url(query, gl, hl) + f"&start={start}"
response = requests.get(
url, headers=HEADERS, proxies=proxies, timeout=30
)
if detect_soft_block(response):
print(f"Soft-block en página {page+1}. Rotando IP...")
# Cambiar sesión rota la IP en ProxyHat
time.sleep(random.uniform(10, 20))
continue
page_results = parse_shopping_results(response.text)
if not page_results:
break # No hay más resultados
all_results.extend(page_results)
time.sleep(random.uniform(3, 8)) # Delay aleatorio
return all_results
Rotación de IPs por petición
Para rotar IPs en cada petición, omite el flag session en el username. ProxyHat asignará una nueva IP residencial automáticamente:
# Rotación automática (nueva IP por petición)
http://user-country-US:pass@gate.proxyhat.com:8080
# Sesión pegajosa (misma IP mientras dure la sesión)
http://user-country-US-session-sess01:pass@gate.proxyhat.com:8080
La estrategia recomendada es: sesión pegajosa para paginar una query (para que Google no detecte cambios de IP entre páginas 1 y 5) y rotación entre queries diferentes (cada nueva búsqueda desde una IP distinta).
Delays aleatorios
Los delays deterministicos son detectables. Usa una distribución aleatoria entre 3 y 8 segundos entre peticiones, con picos ocasionales de 15-30 segundos para simular pausas humanas. Un patrón como time.sleep(5) fijo es una firma clara de bot.
Detección de soft-blocks antes del CAPTCHA
La función detect_soft_block() del ejemplo anterior es tu primera línea de defensa. Cuando detecta una redirección a sorry/index, debes:
- Detener inmediatamente las peticiones desde esa IP/sesión.
- Rotar a una nueva sesión (nueva IP residencial).
- Esperar 30-60 segundos antes de reintentar.
- Registrar el incidente para ajustar tu tasa de peticiones global.
Si ignoras los soft-blocks, Google escala a reCAPTCHA en menos de 10 peticiones adicionales, y a partir de ahí la IP queda inutilizable durante horas.
Límites de concurrencia
Mantén un máximo de 5-10 peticiones simultáneas por IP de proxy. Si usas 100 IPs residenciales concurrentes, puedes sostener ~500-1000 peticiones simultáneas totales, pero monitoriza la tasa de soft-blocks para ajustar a la baja si es necesario.
Scraping de fichas de producto y comparativa de vendedores
La página de resultados de Shopping te da el precio principal, pero el valor real para inteligencia competitiva está en la página de detalle del producto, donde aparecen todos los vendedores con sus precios, costes de envío y disponibilidad.
def scrape_product_offers(product_id, gl="US", hl="en"):
url = f"https://www.google.com/shopping/product/{product_id}"
params = {"gl": gl, "hl": hl}
response = requests.get(
url, headers=HEADERS, proxies=proxies,
params=params, timeout=30
)
if detect_soft_block(response):
return []
soup = BeautifulSoup(response.text, "html.parser")
offers = []
offer_items = soup.select(".sh-o__offers-list .O2FWRc")
for offer in offer_items:
seller = offer.select_one(".dVZi6d")
price = offer.select_one(".a8Pemb")
shipping = offer.select_one(".OkVind")
offers.append({
"seller": seller.get_text(strip=True) if seller else None,
"price": price.get_text(strip=True) if price else None,
"shipping": shipping.get_text(strip=True) if shipping else None,
})
return offers
Para obtener el product_id, extráelo del enlace a.sh-btn__contain en la página de resultados. El ID aparece en la URL como /shopping/product/1234567890.
Errores comunes y casos extremos
1. Depender de un único selector
Google cambia selectores con frecuencia. Si tu scraper usa solo .a8Pemb para el precio y Google lo renombra a .b8Pemb, pierdes todos los datos. Usa siempre fallbacks y regex como respaldo.
2. No configurar gl y hl
Sin gl y hl, Google infiere la ubicación de la IP. Si tu IP residencial es de España pero quieres precios de EE.UU., debes pasar gl=US&hl=en. Sin embargo, si la IP y el gl no coinciden (IP de España + gl=US), Google puede servir resultados híbridos. Lo ideal es alinear IP, gl y hl.
3. Ignorar el layout mobile vs desktop
Google Shopping sirve HTML diferente para mobile y desktop. Los selectores no son los mismos. Si usas un User-Agent de desktop, asegúrate de que tus selectores corresponden al layout desktop. Para mobile, cambia el User-Agent y ajusta los selectores.
4. No respetar robots.txt
Google Shopping permite crawling en ciertas rutas según su robots.txt, pero el acceso a /search está restringido para bots genéricos. Revisa siempre el robots.txt y evalúa el contexto legal de tu scraping.
5. Sobrecargar con concurrencia
Lanzar 50 peticiones concurrentes desde una sola IP es garantía de bloqueo. La concurrencia debe distribuirse entre múltiples IPs de proxy, no concentrarse en una.
Consideraciones éticas y legales
El scraping de Google Shopping opera en una zona legal compleja. Aquí los puntos clave:
- Datos públicos únicamente: extraer precios visibles públicamente sin autenticación es diferente a acceder a datos protegidos. No intentes scrapear cuentas de comerciante ni áreas que requieran login.
- CFAA (EE.UU.): La Computer Fraud and Abuse Act se ha interpretado en casos como hiQ Labs v. LinkedIn de manera que el scraping de datos públicos no constituye acceso no autorizado, pero la jurisprudencia no es uniforme. Consulta con asesoría legal.
- GDPR (UE): Los precios de productos no son datos personales, pero si recolectas datos de vendedores individuales o reseñas con identificadores, puede aplicarse el GDPR. Evita almacenar datos personales innecesarios.
- Términos de servicio de Google: Los ToS de Google prohíben el scraping automatizado. Violentarlos puede resultar en bloqueos de IP y, en casos extremos, acciones legales. Evalúa el riesgo según tu volumen y uso.
- Ruta compliance: Si tu caso de uso es de alto volumen o enterprise, considera los socios oficiales de Google Shopping/SERP que ofrecen datos de Shopping mediante acuerdos comerciales. Es más caro pero elimina el riesgo legal.
Para más contexto sobre scraping ético, consulta nuestra guía de casos de uso de web scraping.
Configuración de ProxyHat para Google Shopping
ProxyHat ofrece proxies residenciales, móviles y datacenter. Para Google Shopping, la configuración recomendada es:
| Parámetro | Valor recomendado | Razón |
|---|---|---|
| Tipo de proxy | Residencial | IPs de ISPs reales, indetectables |
| Rotación | Por petición (sin sesión) o sesión pegajosa para paginación | Equilibra stealth vs consistencia |
| Geo-targeting | País + ciudad según mercado objetivo | Precios localizados auténticos |
| Concurrencia | 5-10 por IP, hasta 100 IPs concurrentes | Evita soft-blocks por IP |
| Protocolo | HTTP (8080) o SOCKS5 (1080) | HTTP para requests, SOCKS5 para entornos específicos |
Consulta nuestra página de precios para planes de proxies residenciales con geo-targeting, y la documentación de ProxyHat para detalles técnicos completos.
Para casos de uso relacionados como tracking de SERPs, visita nuestra página de SERP tracking.
Key Takeaways
- La Content API no sirve para competencia: solo expone tus propios productos. Para precios de competidores, el scraping del HTML de
tbm=shopes la vía práctica. - Los selectores cambian:
.sh-dgr__content,.a8Pemby.sh-o__offers-listfuncionan en 2026, pero usa siempre fallbacks y regex. - La geo-localización importa: precios y vendedores varían por país y ciudad. Usa proxies residenciales con
country-USocountry-DE-city-berlincombinados conglyhl. - Detecta soft-blocks antes del CAPTCHA: la redirección a
sorry/indexes tu señal para rotar IP inmediatamente. - Controla la frecuencia: delays aleatorios de 3-8 segundos, máximo 5-10 peticiones concurrentes por IP, rotación entre queries.
- Evalúa el riesgo legal: datos públicos solo, respeta robots.txt, considera socios oficiales para alto volumen.
FAQ
¿Qué es scrapear Google Shopping y por qué importa en 2026?
Scrapear Google Shopping significa extraer precios, vendedores, valoraciones y datos de productos de las páginas de resultados de Google Shopping (tbm=shop). En 2026 sigue siendo relevante porque la Content API for Shopping solo sirve los productos del propio comerciante, no los de la competencia. Para inteligencia competitiva y monitoreo de precios, el scraping del HTML público es la única vía práctica.
¿Por qué importa scrapear Google Shopping para los usuarios de proxies?
Google aplica rate limits agresivos por IP, redirecciones sorry/index y reCAPTCHA. Sin proxies residenciales rotativos con geo-localización a nivel ciudad, un scraper recibe bloqueos tras unas pocas decenas de peticiones. Los proxies permiten distribuir peticiones entre miles de IPs reales, simular compradores en distintas ubicaciones y acceder a precios localizados que varían según país y ciudad.
¿Qué tipo de proxy funciona mejor para scrapear Google Shopping?
Los proxies residenciales son la mejor opción para Google Shopping porque usan IPs de dispositivos reales asignadas por ISPs, lo que los hace indistinguibles de usuarios genuinos. Los datacenter proxies son detectados y bloqueados rápidamente. Para precios localizados, se necesita geo-targeting a nivel país y ciudad (por ejemplo, country-US o country-DE-city-berlin), algo que los proxies residenciales de ProxyHat soportan nativamente.
¿Cómo evitas bloqueos al scrapear Google Shopping?
Para evitar bloqueos usa proxies residenciales rotativos con sesiones pegajosas cuando necesites consistencia, rota IPs por petición, añade delays aleatorios entre 3 y 8 segundos, configura los parámetros gl y hl según el país objetivo, detecta redirecciones a sorry/index como soft-blocks antes de que escalen a CAPTCHA, y limita la concurrencia a 5-10 peticiones simultáneas por IP.
¿Es legal scrapear Google Shopping?
El scraping de datos públicamente visibles sin autenticación se considera generalmente legal en EE.UU. según jurisprudencia reciente como hiQ v. LinkedIn, pero los ToS de Google prohíben el scraping automatizado. En la UE, el GDPR aplica si recolectas datos personales, aunque los precios de productos no lo son. Para alto volumen, considera socios oficiales de Google como ruta de compliance. Consulta siempre con asesoría legal.






