Cómo hacer scraping de Shein a escala en 2026: API interna vs HTML renderizado
El scraping de Shein a escala en 2026 exige elegir entre dos rutas: parsear HTML renderizado o consumir los endpoints JSON internos que la propia página invoca desde el navegador. La segunda opción —endpoints como /api/productInfo o los feeds de categoría con parámetros goods_id y cat_id— es más eficiente, pero requiere evadir una pila anti-bot agresiva. Si tu equipo de inteligencia de precios de moda necesita scrapear Shein para miles de SKUs diarios, esta guía cubre la implementación completa con proxies residenciales rotativos.
Shein localiza moneda, precios, disponibilidad y catálogo por geolocalidad IP. Un datacenter proxy ruso verá un catálogo distinto al de un residencial en Estados Unidos. Por eso, un Shein product scraper serio necesita rotación IP con geo-targeting granular.
Contexto técnico: por qué scrapear Shein es difícil
La pila anti-bot de Shein: Akamai Bot Manager
Shein utiliza Akamai Bot Manager como su principal sistema de detección automatizada. El flujo de validación funciona así:
- Cookie
_abck: token de sesión que Akamai emite tras evaluar el entorno del navegador. Si el sensor no pasa la prueba, el valor contiene~-1~-1~-1y las peticiones posteriores reciben HTTP 403 o 412. - Cookie
bm_sz: identificador de sesión de Bot Manager, vinculado al_abck. sensor_data: telemetría del navegador (canvas fingerprint, WebGL, dimensiones de pantalla, eventos de ratón, timing de teclas) que se envía en una petición POST a/_bm/...para generar o refrescar el_abck.smdeviceid: token de dispositivo persistente que Shein asigna y espera en cada petición de producto o carrito.
Un navegador headless Chrome con Playwright o Puppeteer suele ser detectado por Akamai porque las propiedades de navigator.webdriver, los headers TLS y los fingerprints de canvas difieren de un navegador real. Según la documentación de Mozilla Developer Network sobre WebDriver, la propiedad navigator.webdriver es true por defecto en automatizaciones, lo que es una señal inmediata para los sistemas anti-bot.
Por qué el headless Chrome puro no basta
Shein bloquea headless Chrome por al menos tres razones:
- TLS fingerprinting (JA3/JA4): el handshake TLS de Chromium headless difiere del de Chrome real en extensiones y cipher suites ordenadas.
- Telemetría de sensor incompleta: sin movimiento de ratón ni eventos reales,
sensor_datano pasa la validación de Akamai. - Rate limiting por IP: aunque el navegador pase Akamai, Shein impone límites de ~30-50 peticiones/minuto por IP antes de servir
429 Too Many Requests.
La solución práctica combina impersonación TLS (con librerías como curl_cffi o tls-client) y proxies residenciales rotativos con geo-targeting.
Dónde están los datos: endpoints y blobs JSON
Endpoints internos de producto y categoría
Shein no expone una API pública documentada, pero el frontend realiza llamadas a endpoints JSON internos que puedes consumir directamente si tienes un _abck válido:
| Endpoint | Parámetros clave | Datos retornados |
|---|---|---|
/api/productInfo | goods_id, cat_id, country | retailPrice, salePrice, stock, SKU list, imágenes |
Feed de categoría (/goodsapi/...) | cat_id, page, limit, sort | Lista de goods_id, precios, descuentos, ratings |
| HTML de página de producto | URL canónica | Blob productIntroData / gbProductDetail embebido en <script> |
El blob productIntroData está dentro de un <script> tag en el HTML renderizado. Contiene el mismo payload que /api/productInfo, pero parsearlo requiere extraer el JSON con expresiones regulares o un parser HTML. El endpoint directo es más limpio.
Estructura de respuesta truncada
Una respuesta típica de /api/productInfo (truncada) se ve así:
{
"code": 0,
"info": {
"goods_id": "1234567",
"goods_sn": "swdress071901",
"cat_id": "1727",
"goods_name": "Floral Print Ruffle Dress",
"retailPrice": {"amount": "25.99", "amountWithSymbol": "$25.99"},
"salePrice": {"amount": "12.99", "amountWithSymbol": "$12.99"},
"marketPrice": {"amount": "25.99"},
"detail": {
"inventory": [
{"sku_code": "SKU_A1", "stock": 34, "size": "S", "color": "Black"},
{"sku_code": "SKU_A2", "stock": 0, "size": "M", "color": "Black"}
]
},
"productPromotionPrice": {"amount": "12.99"}
}
}Los campos críticos para Shein price data son retailPrice, salePrice, marketPrice y detail.inventory[].stock. El campo goods_id es la clave primaria para deduplicar y trackear cambios.
Rate limits reales por IP y por qué necesitas proxies residenciales
Basado en pruebas de campo y reportes de la comunidad de scraping, Shein impone estos umbrales aproximados:
- ~30-50 peticiones/minuto por IP antes de
429. - ~200-300 peticiones por IP en una ventana de 10 minutos antes de un ban temporal de 1-6 horas.
- ~1000 peticiones por IP en 24 horas antes de un ban prolongado o challenge de Akamai permanente.
Para un volumen de 10,000 productos/día con 2 peticiones por producto (detalle + inventario), necesitas al menos 20,000 peticiones/día. A 40 peticiones/minuto por IP, eso son ~8.3 horas con una sola IP. Con 20 IPs rotativas, lo reduces a ~25 minutos.
Pero hay un segundo motivo para proxies residenciales: localización geográfica. Shein muestra precios en USD para IPs de EE.UU., en EUR para IPs de Alemania, y catálogos distintos por región. Si tu análisis de competencia es para el mercado europeo, debes usar IPs del país objetivo.
Selección de tipo de proxy
| Tipo de proxy | Detección por Shein | Geo-targeting | Coste relativo | Recomendado |
|---|---|---|---|---|
| Datacenter | Alta (bloqueo frecuente) | Limitado | Bajo | No |
| Residencial rotativo | Baja | País + ciudad | Medio | Sí (catálogo y precios) |
| Móvil 4G/5G | Muy baja | País | Alto | Sí (volumen extremo) |
Los proxies residenciales rotativos de ProxyHat ofrecen geo-targeting a nivel de país y ciudad, ideal para mantener consistencia de moneda y catálogo.
Implementación práctica: Python + curl_cffi + ProxyHat
La librería curl_cffi permite impersonar el fingerprint TLS de Chrome real, lo que reduce significativamente las detecciones de Akamai comparado con requests estándar.
Paso 1: Instalación
pip install curl_cffiPaso 2: Scraper de producto con proxy residencial
from curl_cffi import requests
import json
import time
import random
PROXY_URL = "http://user-country-US:PASS@gate.proxyhat.com:8080"
def fetch_shein_product(goods_id: str, cat_id: str = "1727") -> dict:
"""
Consulta el endpoint interno /api/productInfo de Shein
con impersonación TLS de Chrome y proxy residencial de ProxyHat.
"""
url = "https://www.shein.com/api/productInfo"
params = {
"goods_id": goods_id,
"cat_id": cat_id,
"country": "US",
"currency": "USD",
"language": "en"
}
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",
"Referer": f"https://www.shein.com/p-{goods_id}.html",
"Accept": "application/json, text/plain, */*",
}
resp = requests.get(
url,
params=params,
headers=headers,
proxies={"http": PROXY_URL, "https": PROXY_URL},
impersonate="chrome120",
timeout=20
)
if resp.status_code == 412:
# _abck caducado o challenge de Akamai
raise Exception(f"Akamai challenge (412) — rotar IP y reintentar")
if resp.status_code == 429:
wait = random.uniform(30, 60)
time.sleep(wait)
return fetch_shein_product(goods_id, cat_id)
return resp.json()
# Ejemplo de uso
data = fetch_shein_product("1234567")
info = data.get("info", {})
print(f"Producto: {info.get('goods_name')}")
print(f"Precio venta: {info.get('salePrice', {}).get('amountWithSymbol')}")
print(f"Precio retail: {info.get('retailPrice', {}).get('amountWithSymbol')}")
for sku in info.get("detail", {}).get("inventory", []):
print(f" SKU {sku['sku_code']}: stock={sku['stock']}, talla={sku['size']}")Salida esperada (truncada):
Producto: Floral Print Ruffle Dress
Precio venta: $12.99
Precio retail: $25.99
SKU_A1: stock=34, talla=S
SKU_A2: stock=0, talla=MPaso 3: Scraping de categoría con paginación
def fetch_category(cat_id: str, max_pages: int = 10, country: str = "US"):
"""Scrapea un feed de categoría con rotación de sesión por página."""
all_goods = []
for page in range(1, max_pages + 1):
session_id = f"shein-cat-{cat_id}-{page}"
proxy = f"http://user-country-{country}-session-{session_id}:PASS@gate.proxyhat.com:8080"
url = f"https://www.shein.com/goodsapi/goods-list/"
params = {"cat_id": cat_id, "page": page, "limit": 40, "sort": "7"}
resp = requests.get(
url, params=params,
headers={"User-Agent": "Mozilla/5.0 ... Chrome/120.0.0.0 Safari/537.36"},
proxies={"http": proxy, "https": proxy},
impersonate="chrome120",
timeout=20
)
if resp.status_code != 200:
print(f"Página {page}: HTTP {resp.status_code} — backoff")
time.sleep(random.uniform(5, 15))
continue
goods = resp.json().get("info", {}).get("products", [])
if not goods:
break
all_goods.extend(goods)
time.sleep(random.uniform(1.5, 3.0)) # rate limit respetuoso
return all_goodsSesiones sticky y consistencia de moneda
Un error común es rotar IPs en cada petición cuando se scrapea un mismo producto o categoría. Esto causa inconsistencias: un producto puede mostrar $12.99 USD en una petición y €11.99 EUR en la siguiente si la IP cambia de país.
La solución es usar sesiones sticky en ProxyHat mediante el flag -session- en el username:
# Sesión sticky para país DE — misma IP durante ~10 minutos
http://user-country-DE-session-shein-de-batch01:PASS@gate.proxyhat.com:8080
# Sesión sticky para país US — consistencia de USD
http://user-country-US-session-shein-us-batch01:PASS@gate.proxyhat.com:8080Asigna un session_id único por lote de trabajo (ej. una categoría completa) y reutilízalo durante toda la sesión. Cuando la IP expire o recibas un 412, genera un nuevo session_id y continúa.
Backoff y lógica de refresco de _abck
Cuando Akamai detecta actividad sospechosa, el servidor responde con HTTP 412 Precondition Failed. Esto significa que el _abck actual ya no es válido. La estrategia de recuperación:
- Rotar IP inmediatamente: cambia el
session_idpara obtener una IP residencial nueva. - Backoff exponencial: espera 5s, 10s, 20s, 40s entre reintentos.
- Re-adquirir cookies: haz una petición GET a la página principal de Shein para que el servidor emita un nuevo
_abckybm_sz. - Reenviar con cookies frescas: incluye las nuevas cookies en la petición a
/api/productInfo.
def fetch_with_retry(goods_id, max_retries=3):
for attempt in range(max_retries):
try:
session = requests.Session(impersonate="chrome120")
# 1. Visitar homepage para obtener _abck
session.get("https://www.shein.com/",
proxies={"https": get_proxy()}, timeout=15)
# 2. Consultar producto con cookies de sesión
data = fetch_shein_product(goods_id)
return data
except Exception as e:
wait = 5 * (2 ** attempt)
print(f"Intento {attempt+1} fallido: {e}. Esperando {wait}s...")
time.sleep(wait)
raise Exception(f"Falló tras {max_retries} intentos para goods_id={goods_id}")Errores comunes y casos límite
1. No respetar robots.txt
Shein tiene un robots.txt que restringe ciertas rutas. Revísalo antes de scrapear. Aunque los endpoints de producto no siempre están listados, las rutas de checkout y cuenta sí suelen estar prohibidas.
2. Ignorar la localización de precios
Un Shein product scraper que mezcla precios de distintos países produce datos inservibles. Siempre documenta el país y la moneda junto a cada precio extraído.
3. No manejar productos agotados
Los productos sin stock retornan stock: 0 en todos los SKUs, pero la página sigue existiendo. No los elimines de tu base de datos; márcalos como out_of_stock y re-verifícalos periódicamente.
4. Sobrecargar con demasiada concurrencia
Más de 50 hilos concurrentes desde un mismo rango de IPs residenciales puede disparar el rate limit de ProxyHat o de Shein. Usa colas con un límite de concurrencia de 20-30 peticiones paralelas.
Configuración específica de ProxyHat
Para configurar tu Shein product scraper con ProxyHat, usa estos parámetros de conexión:
| Parámetro | Valor |
|---|---|
| Gateway HTTP | gate.proxyhat.com:8080 |
| Gateway SOCKS5 | gate.proxyhat.com:1080 |
| Geo-targeting país | user-country-US:pass |
| Geo-targeting ciudad | user-country-US-city-newyork:pass |
| Sesión sticky | user-session-abc123:pass |
| Combinado | user-country-DE-session-batch01:pass |
Consulta la documentación de ProxyHat para detalles sobre parámetros avanzados. Para ver la lista completa de ubicaciones disponibles, visita /es/locations.
Si tu caso de uso principal es web scraping de catálogos de moda, revisa nuestra guía de casos de uso de web scraping. Para tracking de resultados de búsqueda y SERP, consulta SERP tracking.
Ética, términos de servicio y alternativas
Scrapear datos públicos de productos (precio, stock, nombre, imágenes) es generalmente aceptable, pero hay límites importantes:
- No accedas a endpoints de checkout, cuenta o pago. Eso viola los términos de servicio de Shein y puede constituir acceso no autorizado bajo leyes como la Computer Fraud and Abuse Act (CFAA).
- Datos personales: no extraigas reseñas de usuarios con nombres o identificadores sin consentimiento. Bajo GDPR (Reglamento UE 2016/679), los datos personales requieren base legal para su procesamiento.
- Velocidad razonable: no satures la infraestructura de Shein. Mantén tasas de < 40 peticiones/minuto por IP.
- robots.txt: respeta las directivas de
Disallowaunque técnicamente puedas evadirlas.
Cuándo usar el feed oficial de afiliados
Shein tiene un programa de afiliados que provee feeds de productos con precios, imágenes y disponibilidad vía API o CSV. Si solo necesitas datos de producto para comparación de precios y no necesitas datos en tiempo real al minuto, el feed de afiliados es:
- Más fiable y sin riesgo de bloqueo.
- Legalmente seguro (uso autorizado).
- Actualizado diariamente o cada pocas horas.
El scraping directo es preferible cuando necesitas granularidad de stock por SKU en tiempo real, detección de cambios de precio intradía, o datos que el feed de afiliados no incluye (como rankings de búsqueda o datos de categoría paginados).
Conclusiones clave
El scraping de Shein a escala en 2026 se reduce a tres pilares: impersonación TLS con curl_cffi, proxies residenciales rotativos con geo-targeting, y sesiones sticky para consistencia de moneda. Sin los tres, tu scraper fallará en menos de 200 peticiones.
Key Takeaways
- Prefiere los endpoints JSON internos (
/api/productInfo) sobre parsear HTML renderizado. - Akamai Bot Manager valida
_abckconsensor_data; el headless Chrome puro es insuficiente. - Shein localiza precios y catálogo por IP: usa
-country-USo-country-DEen ProxyHat. - Rate limit real: ~40 peticiones/minuto por IP. Planifica concurrencia en consecuencia.
- Sesiones sticky (
-session-) garantizan que un lote completo vea la misma moneda y catálogo. - Considera el feed de afiliados si no necesitas granularidad de stock en tiempo real.
- Respecta robots.txt, evita endpoints de checkout y cumple con CFAA/GDPR.
¿Listo para construir tu pipeline de Shein price data? Empieza en el panel de ProxyHat y configura tus proxies residenciales con geo-targeting en minutos.






