Scrapear Temu en 2026 es un desafío de ingeniería, no un simple ejercicio de parsing. La plataforma de e-commerce de PDD Holdings no expone una API pública, lo que te obliga a elegir entre dos caminos: parsear tarjetas HTML volátiles o golpear los endpoints JSON internos como /api/poppy/v1/search y los de detalle de producto. En esta guía explicamos cómo scrapear datos de productos y precios de Temu en 2026 sorteando Cloudflare Turnstile, el header firmado anti_content y el fingerprinting TLS/HTTP2 que detecta IPs de datacenter al instante.
Por qué scrapear Temu es distinto a scrapear Amazon o Walmart
Temu opera con un stack anti-bot agresivo heredado en parte de la infraestructura de Pinduoduo. A diferencia de Amazon, donde un requests.get con headers razonables suele devolver HTML parseable, Temu combina tres capas de defensa que filtran la mayoría de bots desde el primer request:
- Cloudflare Turnstile: el challenge invisible de Cloudflare que evalúa señales del navegador sin interacción del usuario. Según la documentación oficial de Turnstile, el sistema analiza cientos de señales de entorno para decidir si el cliente es humano.
- Header
anti_contentfirmado: un token generado client-side mediante JavaScript ofuscado que codifica señales del navegador (canvas, WebGL, timing). Sin un token válido, el servidor devuelve 403 o un JSON vacío. - Fingerprinting TLS/HTTP2: Temu usa JA3/JA4 y fingerprints HTTP/2 para detectar clientes que no sean navegadores reales. Un
requests.Sessionestándar tiene un fingerprint TLS de Python/urllib3 que se bloquea en milisegundos.
El resultado: las IPs de datacenter se filtan tan rápido que un scraper con proxies de centro de datos puede ver tasas de éxito inferiores al 5% en menos de 50 requests. Los proxies residenciales no son opcionales; son un requisito de línea base.
Trade-off: parsear HTML vs. consumir el JSON interno
Temu renderiza su catálogo con Next.js. Cada página de búsqueda o detalle contiene un blob de estado incrustado en un tag <script id="__NEXT_DATA__"> (o una variante similar con window.__INITIAL_STATE__). Tienes dos opciones:
| Enfoque | Ventajas | Desventajas |
|---|---|---|
| Parsear HTML (tarjetas de producto) | Sin necesidad de reproducir tokens anti_content; funciona con HTML estático | Selectores CSS frágiles (clases hash como _2f7b8c); se rompe en cada deploy; datos incompletos |
JSON interno (/api/poppy/v1/search, goods-detail) | Datos estructurados completos: SKU, precios por variante, stock, shipping | Requiere token anti_content válido y fingerprint TLS correcto |
Para price intelligence serio, el JSON interno es la única opción sostenible. El HTML cambia con cada release (a veces semanalmente), mientras que la estructura del JSON de la API interna se mantiene más estable porque alimenta las apps móviles de Temu, que no se actualizan al mismo ritmo.
Localizar los datos: el JSON detrás del grid
El blob de estado incrustado
En una URL de búsqueda como https://www.temu.com/search?q=laptop+stand, el HTML incluye:
<script id="__NEXT_DATA__" type="application/json">
{"props":{"pageProps":{"searchResult":{"data":[
{"goods_id":"1020939012","goods_name":"...",
"min_normal_price":{"amount":12.99,"currency":"USD"},
"sale_price":{"amount":8.99,"currency":"USD"},
"sku_list":[...]}
]}}}}</script>
Este blob es la fuente más accesible si solo necesitas el listing básico. Extrae el contenido del tag, parsea el JSON y navega props.pageProps.searchResult.data.
Los endpoints JSON internos
Para datos más completos —incluyendo detalle de SKU, opciones de envío y precios por variante— Temu usa endpoints como:
https://www.temu.com/api/poppy/v1/search— búsqueda paginada con filtros.https://www.temu.com/api/poppy/v1/review/goods-detail— detalle de producto congoods_id.
Estos endpoints requieren los headers anti_content y search_params firmados. Sin ellos, obtendrás un 403 o un payload vacío. La generación de anti_content implica ejecutar el JavaScript ofuscado de Temu en un contexto de navegador real o emulado (por ejemplo, con Playwright + stealth).
Selectores CSS y atributos data-uniqid
Si optas por el camino del HTML, las tarjetas de producto usan clases hash que cambian entre deploys. Lo más estable es localizar por atributos semánticos:
// XPath para tarjetas de producto
//div[contains(@data-uniqid, 'goods')]
// CSS para el precio (frágil, verificar cada semana)
span[data-testid='price']
El atributo data-uniqid es más estable que las clases hash, pero no está garantizado en todas las versiones del front.
Rate limits y por qué los proxies residenciales son obligatorios
Temu no publica umbrales oficiales de rate limiting, pero pruebas empíricas muestran que:
- Una sola IP de datacenter recibe un challenge de Cloudflare después de aproximadamente 10-30 requests en menos de un minuto.
- Con una IP residencial bien rotada, puedes sostener 1-2 requests/segundo por IP antes de que aparezcan CAPTCHAs intermitentes.
- El rate limiting es por IP, no por sesión ni por cookie, lo que hace que la rotación de IP sea la palanca principal.
Además, los precios y las opciones de envío en Temu varían por región. Un producto puede mostrar envío gratis en un ZIP code de California y un coste de envío de $5.99 en otro estado. Esto significa que necesitas geo-targeting a nivel de país como mínimo, y idealmente a nivel de ciudad o región para price intelligence preciso.
Por eso, los proxies residenciales con geo-targeting por país (por ejemplo, -country-US) son obligatorios. Los proxies de datacenter no solo se bloquean, sino que devuelven precios que no reflejan lo que un usuario real ve en su ubicación.
Implementación en Python con curl_cffi y ProxyHat
El fingerprinting TLS de Temu bloquea requests y httpx estándar. La solución más práctica en Python es curl_cffi, una librería que usa libcurl con impersonación de navegador (Chrome, Safari, Firefox). Esto replica el fingerprint TLS/HTTP2 de un navegador real.
Instalación
pip install curl_cffi beautifulsoup4 lxml
Fetch de página de producto con ProxyHat
Aquí tienes un ejemplo completo que usa el gateway de ProxyHat con geo-targeting US y una sesión sticky:
from curl_cffi import requests as cffi_requests
import json
# ProxyHat residential proxy with US geo-targeting and sticky session
proxy_url = "http://user-country-US-session-temu_prod_01:pass@gate.proxyhat.com:8080"
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",
"Accept-Encoding": "gzip, deflate, br",
}
product_url = "https://www.temu.com/some-product-p-1020939012.html"
response = cffi_requests.get(
product_url,
headers=headers,
proxies={"http": proxy_url, "https": proxy_url},
impersonate="chrome124",
timeout=30,
)
print(f"Status: {response.status_code}")
# Extract __NEXT_DATA__ blob
from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, "lxml")
next_data_script = soup.find("script", id="__NEXT_DATA__")
if next_data_script:
data = json.loads(next_data_script.string)
product = data["props"]["pageProps"]["goodsDetail"]
print(json.dumps({
"goods_id": product.get("goods_id"),
"goods_name": product.get("goods_name"),
"min_normal_price": product.get("min_normal_price"),
"sale_price": product.get("sale_price"),
"sku_count": len(product.get("sku_list", [])),
}, indent=2))
else:
print("__NEXT_DATA__ not found — possible CAPTCHA or block")
Respuesta JSON truncada de ejemplo
El output del código anterior se vería así (datos ilustrativos, estructura real puede variar):
{
"goods_id": "1020939012",
"goods_name": "Adjustable Aluminum Laptop Stand",
"min_normal_price": {"amount": 12.99, "currency": "USD"},
"sale_price": {"amount": 8.99, "currency": "USD"},
"sku_count": 3,
"sku_list": [
{"sku_id": "sku_001", "sku_name": "Silver", "price": {"amount": 8.99}},
{"sku_id": "sku_002", "sku_name": "Black", "price": {"amount": 9.49}},
{"sku_id": "sku_003", "sku_name": "Space Gray", "price": {"amount": 9.99}}
]
}
Fetch del endpoint JSON interno
Para golpear el endpoint de búsqueda directamente, necesitas reproducir el anti_content. Esto requiere ejecutar el JS de Temu en un navegador headless. Aquí hay un patrón híbrido con Playwright para generar el token y curl_cffi para los requests masivos:
from curl_cffi import requests as cffi_requests
import json
proxy_url = "http://user-country-US-session-temu_search_01:pass@gate.proxyhat.com:8080"
# anti_content generado previamente via Playwright/stealth
anti_content_token = "GENERATED_TOKEN_FROM_BROWSER_CONTEXT"
api_url = "https://www.temu.com/api/poppy/v1/search"
payload = {
"keyword": "laptop stand",
"pageNum": 1,
"pageSize": 50,
"anti_content": anti_content_token,
}
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",
"Origin": "https://www.temu.com",
"Referer": "https://www.temu.com/search?q=laptop+stand",
}
response = cffi_requests.post(
api_url,
json=payload,
headers=headers,
proxies={"http": proxy_url, "https": proxy_url},
impersonate="chrome124",
timeout=30,
)
result = response.json()
items = result.get("data", {}).get("items", [])
print(f"Items returned: {len(items)}")
for item in items[:3]:
print(f" {item['goods_id']}: ${item['sale_price']['amount']} - {item['goods_name'][:50]}")
Sesiones sticky, reintentos y paginación
Sesiones sticky con ProxyHat
Para mantener consistencia entre requests relacionados (por ejemplo, cargar una página de producto y luego consultar el carrito o las opciones de envío), usa el flag -session- en el username de ProxyHat. Esto asegura que todos los requests dentro de la misma sesión salgan por la misma IP residencial:
# Sticky session: misma IP para todos los requests de esta sesión
proxy_sticky = "http://user-country-US-session-temu_cart_abc123:pass@gate.proxyhat.com:8080"
# Sin sticky: nueva IP en cada request (ideal para listing masivo)
proxy_rotating = "http://user-country-US:pass@gate.proxyhat.com:8080"
La regla práctica: usa rotación por request para scraping de catálogo masivo (búsqueda, listing) y sticky sessions para flujos multi-paso (detalle → carrito → shipping).
Estrategia de reintentos
import time
import random
from curl_cffi import requests as cffi_requests
def fetch_with_retry(url, max_retries=3, base_delay=2):
for attempt in range(max_retries):
# Nueva IP en cada reintento (sin sticky)
proxy = f"http://user-country-US-session-retry_{attempt}:pass@gate.proxyhat.com:8080"
try:
resp = cffi_requests.get(
url,
proxies={"http": proxy, "https": proxy},
impersonate="chrome124",
timeout=30,
)
if resp.status_code == 200:
return resp
elif resp.status_code == 403:
print(f"403 on attempt {attempt+1} — rotating IP")
time.sleep(base_delay * (attempt + 1) + random.uniform(0, 1))
else:
print(f"Status {resp.status_code} on attempt {attempt+1}")
time.sleep(base_delay)
except Exception as e:
print(f"Error on attempt {attempt+1}: {e}")
time.sleep(base_delay * 2)
return None
Paginación
Temu usa paginación basada en cursor en sus endpoints JSON. El campo típicamente es lastGoodsId o pageNum. Incrementa pageNum hasta que items devuelva un array vacío o nulo. Mantén un delay de 1-2 segundos entre páginas para evitar triggers de rate limiting.
Errores comunes y edge cases
- Usar
requestssin impersonación TLS: el fingerprint JA3 de Python se bloquea instantáneamente. Usacurl_cfficonimpersonate="chrome124"o similar. - Olvidar el header
anti_content: sin este token, los endpoints JSON devuelven 403 o un payload vacío. Necesitas generarlo en un contexto de navegador real. - Proxies de datacenter: incluso con fingerprint perfecto, la IP de datacenter activa el challenge de Cloudflare. Solo proxies residenciales o móviles pasan.
- No rotar entre requests de listing: si usas una sticky session para paginar 50 páginas, la IP se quemará. Usa rotación para listing y sticky solo para flujos multi-paso.
- Ignorar la variación regional de precios: si tu proxy está en DE pero comparas precios del mercado US, los datos no son comparables. Usa
-country-USpara el mercado americano. - No respetar
robots.txt: revisa siempre https://www.temu.com/robots.txt antes de scrapear. Aunque no es legalmente vinculante, es una buena práctica ética.
Configuración específica con ProxyHat
ProxyHat ofrece proxies residenciales, móviles y de datacenter. Para Temu, recomendamos exclusivamente residenciales o móviles con geo-targeting por país. La configuración es directa vía el gateway:
| Caso de uso | Configuración de username | Puerto |
|---|---|---|
| Scraping de catálogo (US) | user-country-US:pass | 8080 |
| Detalle + carrito (sticky) | user-country-US-session-cart_abc:pass | 8080 |
| Geo-targeting por ciudad | user-country-US-city-new_york:pass | 8080 |
| SOCKS5 para mayor anonimato | socks5://user-country-US:pass@gate.proxyhat.com:1080 | 1080 |
Consulta nuestras tarifas de proxies y la documentación oficial de ProxyHat para detalles de integración. También puedes explorar nuestros casos de uso de web scraping y la lista de ubicaciones disponibles para geo-targeting.
Consideraciones éticas y legales
Scrapear Temu —o cualquier e-commerce— requiere cuidado ético y legal:
- Solo datos públicos del catálogo: precios, títulos, imágenes, disponibilidad. No scrapees datos de cuentas de usuario, reseñas con PII, ni información de checkout.
- CFAA (EE.UU.) y GDPR (UE): en EE.UU., el Computer Fraud and Abuse Act puede aplicarse al acceso no autorizado a sistemas. En la UE, el GDPR protege datos personales. Scrapear precios de catálogo público es generalmente aceptable; scrapear datos de usuarios no lo es. Consulta la guía del FTC sobre CFAA para contexto.
- Términos de servicio: revisa los ToS de Temu. Muchos e-commerce prohíben el scraping automatizado en sus términos. La enforceabilidad varía por jurisdicción, pero ignorar los ToS tiene riesgo.
- Rate limiting respetuoso: no satures la infraestructura de Temu. Mantén 1-2 req/seg por IP y respeta los backoffs.
- Cuando preferir el feed oficial: si eres un merchant o partner autorizado de Temu, el merchant feed oficial (vía Temu Seller Center) te da datos de producto y pricing sin necesidad de scraping. Si tienes acceso, úsalo. Es más fiable, legal y rápido.
Key Takeaways
- Temu no tiene API pública; el JSON interno (
/api/poppy/v1/search) es la fuente más rica pero requiere el tokenanti_contentfirmado.- El fingerprinting TLS/HTTP2 bloquea
requestsestándar; usacurl_cfficonimpersonate="chrome124".- Los proxies de datacenter se bloquean en menos de 30 requests; los residenciales con geo-targeting (
-country-US) son obligatorios.- Usa sesiones sticky (
-session-) para flujos multi-paso y rotación per-request para listing masivo.- Los precios varían por región; sin geo-targeting correcto, tus datos de price intelligence son incorrectos.
- Si tienes acceso al merchant feed oficial de Temu, prefíerelo sobre el scraping.
FAQ
¿Qué es scrapear datos de productos y precios de Temu?
Es la extracción automatizada del catálogo público de Temu —títulos, precios, SKUs, disponibilidad y opciones de envío— usando bots o scripts. Como Temu no ofrece API pública, se hace parseando el HTML o consumiendo los endpoints JSON internos como /api/poppy/v1/search, sorteando Cloudflare Turnstile y el fingerprinting TLS.
¿Por qué importa scrapear Temu para usuarios de proxies?
Temu bloquea IPs de datacenter en menos de 30 requests mediante fingerprinting TLS/HTTP2 y Cloudflare. Solo los proxies residenciales o móviles con geo-targeting por país permiten acceder a datos precisos de precios, que varían por región. Sin proxies residenciales, el scraping es inviable a escala.
¿Qué tipo de proxy funciona mejor para scrapear Temu?
Los proxies residenciales son la opción óptima. Ofrecen IPs de ISPs reales que pasan los challenges de Cloudflare y reflejan precios regionales correctos. Los proxies móviles también funcionan pero son más caros. Los de datacenter se bloquean casi instantáneamente. Con ProxyHat, usa user-country-US:pass@gate.proxyhat.com:8080 para el mercado americano.
¿Cómo evitas bloqueos al scrapear Temu?
Usa curl_cffi con impersonación de Chrome para replicar el fingerprint TLS, proxies residenciales con geo-targeting por país, rotación de IP por request para listing masivo, sesiones sticky para flujos multi-paso, delays de 1-2 segundos entre requests, y genera el token anti_content en un navegador headless con Playwright/stealth.
¿Es legal scrapear Temu?
Scrapear datos públicos del catálogo (precios, títulos) es generalmente aceptable, pero los ToS de Temu pueden prohibirlo. El CFAA en EE.UU. y el GDPR en la UE aplican restricciones. No scrapees datos de cuentas de usuario ni PII. Si eres merchant autorizado, usa el feed oficial del Seller Center en lugar de scraping.






