Il dilemma API vs HTML: come raschiare dati prodotto e prezzo Temu nel 2026
Temu non offre un'API pubblica per il suo catalogo. Se devi raschiare dati prodotto e prezzo Temu nel 2026, ti trovi di fronte a una scelta fondamentale: parsare l'HTML delle pagine (volubile, ricco di classi CSS hashate) oppure colpire gli endpoint JSON interni che alimentano la griglia prodotti. La seconda opzione è quasi sempre preferibile per team di price intelligence, ma richiede di gestire un anti-bot stack aggressivo.
Il trade-off è netto. L'HTML renderizzato contiene tutto ciò che vedi nel browser — titolo, prezzo, immagini, recensioni — ma le classi CSS sono hashate (es. _3df5b2c), cambiano ad ogni deploy e i selettori si rompono settimanalmente. Gli endpoint JSON come /api/poppy/v1/search e il goods-detail restituiscono invece dati strutturati e stabili: goods_id, price, liste SKU, attributi. Il prezzo è un JSON parsing vs un fragile scraping HTML.
La sfida reale non è trovare i dati — è arrivarci. Temu è protetto da Cloudflare Turnstile, fingerprinting TLS/HTTP2 e un header anti_content firmato che funge da token anti-bot. Senza proxy residenziali con geo-targeting città, anche la richiesta più ben formata viene bloccata in meno di 200ms.
Perché raschiare Temu è tecnicamente difficile
Temu è costruito su un'architettura Next.js-like con rendering ibrido. Le pagine di listing e prodotto caricano un blob di stato iniziale embedded (simile a __NEXT_DATA__) che contiene già i dati del prodotto in JSON serializzato. Questo blob è visibile nell'HTML sorgente, ma è anche accessibile tramite chiamate API dirette agli endpoint interni.
Il problema è che Temu non serve lo stesso contenuto a tutti. I prezzi, le opzioni di spedizione e persino la disponibilità variano in base alla regione geografica dell'IP del richiedente. Un utente con IP statunitense vede prezzi in USD e spedizione dal New Jersey; lo stesso prodotto richiesto da un IP tedesco mostra prezzi in EUR e magazzini europei. Questo rende i proxy datacenter non solo rischiosi per il blocco, ma anche inaffidabili per la qualità dei dati.
Lo stack anti-bot di Temu
Temu implementa tre strati di difesa che devi superare:
- Cloudflare Turnstile: un CAPTCHA invisibile che analizza comportamento del browser, fingerprint JS e segnali ambientali. Non richiede interazione utente, ma rifiuta richieste con fingerprint incoerenti.
- Header
anti_contentfirmato: un token generato lato client da codice JS offuscato. Contiene dati di sessione e una firma. Senza un token valido, l'endpoint JSON restituisce 403 o un payload vuoto. - Fingerprinting TLS/HTTP2: il JA3/JA4 fingerprint della connessione TLS viene confrontato con quello dichiarato dall'User-Agent. Un IP datacenter con UA Chrome ma JA3 di Python
requestsviene flaggato istantaneamente.
Quest'ultimo punto è critico: librerie come requests o httpx standard hanno un fingerprint TLS diverso da Chrome, Firefox o Safari. Cloudflare lo rileva e blocca. Per approfondire il fingerprinting TLS, la documentazione su Wikipedia offre un buon contesto tecnico.
Trovare i dati: endpoint JSON e stato embedded
Quando carichi una pagina prodotto Temu, il browser esegue diverse chiamate XHR. Le due più importanti per il data scraping sono:
# Endpoint di ricerca (listing grid)
GET https://www.temu.com/api/poppy/v1/search?
search_key=&page_id=1&limit=20
&anti_content={token_firmato}
# Endpoint dettaglio prodotto
GET https://www.temu.com/api/poppy/v1/goods-detail?
goods_id=509999999999999&anti_content={token_firmato}
Questi endpoint restituiscono JSON strutturato. Alternativamente, puoi estrarre il blob di stato iniziale dall'HTML della pagina, che contiene già i dati del primo render:
<script id="__NEXT_DATA__" type="application/json">
{"props":{"pageProps":{"goods":{
"goods_id":"509999999999999",
"goods_name":"...",
"price":{"price":"12.99","currency":"USD"},
"sku_list":[...]
}}}}</script>
Per il parsing HTML, le classi CSS sono hashate e cambiano frequentemente. Usa attributi data-uniqid e data-pid quando presenti — sono più stabili delle classi. Ad esempio:
# Selettore CSS fragile (classi hashate)
div._3df5b2c > span._1a2b3c4
# Selettore più stabile (attributi data)
[data-uniqid="price"]
[pid="509999999999999"]
La strategia raccomandata per un Temu price scraper di produzione è: estrarre goods_id dal blob embedded, poi colpire l'endpoint goods-detail per dati completi e aggiornati. Questo combina stabilità (goods_id dal server-render) con freschezza (prezzo live dall'API).
Rate limit e perché il geo-targeting città è obbligatorio
Temu non pubblica rate limit ufficiali, ma da test empirici i threshold sono approssimativamente questi:
| Scenario | Threshold osservato | Risposta |
|---|---|---|
| Richieste per IP, endpoint search | ~30-50 req/min | 429 Too Many Requests |
| Richieste per IP, goods-detail | ~60-80 req/min | 429 o 403 con challenge Turnstile |
| IP datacenter (qualsiasi ASN noto) | 1 richiesta | 403 immediato o challenge |
| IP residenziale, UA incoerente | 5-10 richieste | Challenge Turnstile crescente |
Il limite pratico per uno scraper affidabile è 1-2 richieste per secondo per IP residenziale, con rotazione IP tra le richieste per distribuire il carico. A 2 req/sec con 100 IP residenziali concorrenti, puoi raccogliere circa 17.000 prodotti all'ora — sufficiente per monitorare un catalogo di categoria media.
Ma il rate limit è solo metà del problema. L'altra metà è la geolocalizzazione. I prezzi Temu variano per regione: lo stesso goods_id può costare $12.99 negli Stati Uniti e €14.99 in Germania, con spedizione gratuita sopra soglie diverse. Se il tuo Temu product data API deve alimentare un sistema di price intelligence che confronta prezzi tra mercati, ogni richiesta deve uscire da un IP della regione corretta.
Ecco perché il geo-targeting a livello di paese non è sufficiente — serve quello a livello di città. Le variazioni di prezzo tra stati US (es. California vs Texas) o regioni europee possono differire del 5-15% su prodotti con spedizione calcolata dinamicamente.
Proxy residenziali vs datacenter vs mobile per Temu
| Tipo proxy | Tasso di blocco Temu | Coerenza geo | Costo relativo | Caso d'uso |
|---|---|---|---|---|
| Datacenter | 95%+ (blocco immediato) | N/D | Basso | Non raccomandato |
| Residenziale rotante | 5-15% | Paese + città | Medio | Catalog scraping, price monitoring |
| Residenziale sticky | 5-15% | Paese + città | Medio | Carrello, spedizione, paginazione |
| Mobile | 2-8% | Paese (limitato città) | Alto | Volume alto, bypass anti-bot |
I proxy mobile hanno il tasso di blocco più basso perché gli IP mobili sono considerati legittimi da Cloudflare, ma il geo-targeting città è limitato e il costo è superiore. Per la maggior parte dei team di e-commerce intelligence, i residenziali con geo-targeting città offono il miglior rapporto costo/affidabilità.
Implementazione pratica: Python, curl_cffi e ProxyHat
Per superare il fingerprinting TLS, usa curl_cffi, una libreria Python che usa curl con impersonazione TLS di browser reali. Questo garantisce che il JA3/JA4 fingerprint corrisponda all'User-Agent dichiarato.
Ecco un esempio completo che usa ProxyHat come proxy residenziale con geo-targeting US:
from curl_cffi import requests as cffi_requests
import json
import time
import random
# Configurazione ProxyHat — proxy residenziale US, rotazione per richiesta
PROXYHAT_USER = "user-country-US-city-chicago"
PROXYHAT_PASS = "tua_password"
PROXY_URL = f"http://{PROXYHAT_USER}:{PROXYHAT_PASS}@gate.proxyhat.com:8080"
HEADERS = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/131.0.0.0 Safari/537.36",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "en-US,en;q=0.9",
"Referer": "https://www.temu.com/",
# anti_content va generato lato client o estratto da una sessione browser
"anti_content": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
}
def fetch_product(goods_id, session_id=None):
"""Fetch dettaglio prodotto da endpoint JSON interno Temu."""
# Sessione sticky opzionale per coerenza carrello/spedizione
user = f"user-country-US-city-chicago"
if session_id:
user += f"-session-{session_id}"
proxy_url = f"http://{user}:{PROXYHAT_PASS}@gate.proxyhat.com:8080"
url = "https://www.temu.com/api/poppy/v1/goods-detail"
params = {"goods_id": goods_id}
try:
resp = cffi_requests.get(
url,
params=params,
headers=HEADERS,
proxies={"http": proxy_url, "https": proxy_url},
impersonate="chrome131",
timeout=15,
)
if resp.status_code == 200:
return resp.json()
elif resp.status_code == 429:
time.sleep(random.uniform(3, 7))
return fetch_product(goods_id, session_id)
else:
print(f"Errore {resp.status_code} per goods_id={goods_id}")
return None
except Exception as e:
print(f"Eccezione: {e}")
return None
# Esempio di utilizzo
data = fetch_product("509999999999999")
if data and "goods" in data:
goods = data["goods"]
print(f"ID: {goods['goods_id']}")
print(f"Nome: {goods['goods_name']}")
print(f"Prezzo: {goods['price']['price']} {goods['price']['currency']}")
Risposta JSON troncata di esempio dall'endpoint goods-detail:
{
"goods": {
"goods_id": "509999999999999",
"goods_name": "Wireless Bluetooth Earbuds Pro",
"cat_id": 152,
"price": {
"price": "12.99",
"market_price": "29.99",
"currency": "USD",
"price_symbol": "$"
},
"sku_list": [
{
"sku_id": "sku_001",
"sku_name": "Black",
"price": "12.99",
"stock": 3421
},
{
"sku_id": "sku_002",
"sku_name": "White",
"price": "13.49",
"stock": 1820
}
],
"shipping_info": {
"free_shipping": true,
"shipping_fee": "0.00",
"estimated_days": "3-7"
},
"sales": {
"sales_count": 15432,
"review_count": 2891
}
}
}
Nota l'uso di impersonate="chrome131" in curl_cffi: questo fa sì che la connessione TLS usi lo stesso cipher suite, estensioni e ordine di Chrome 131, producendo un JA3/JA4 fingerprint coerente con l'User-Agent.
Generazione dell'header anti_content
L'header anti_content è la parte più complessa. È un token JWT-like generato da codice JavaScript offuscato lato client. Contiene dati di sessione, timestamp e una firma HMAC. Per un scraper di produzione hai tre opzioni:
- Estrarlo da una sessione browser headless: usa Playwright o Puppeteer per caricare la pagina una volta, catturare il token da una richiesta XHR, e riutilizzarlo per le chiamate API successive (ha una validità di circa 10-30 minuti).
- Reverse-engineering del codice JS: complesso, fragile, si rompe ad ogni aggiornamento Temu. Non raccomandato a meno che tu non abbia un team dedicato.
- Usare un servizio di risoluzione CAPTCHA/anti-bot che gestisce Turnstile e genera token validi. Costoso ma affidabile per volumi alti.
Per la maggior parte dei team, l'opzione 1 è il compromesso migliore: una richiesta browser ogni N minuti per rinfrescare il token, poi N chiamate API via curl_cffi + proxy per i dati effettivi.
Sessioni sticky, retry e paginazione
Per scenari che richiedono coerenza di stato — calcolo spedizione, flusso carrello, o paginazione che dipende da una sessione server — usa sessioni sticky ProxyHat. Il flag -session- mantiene lo stesso IP per la durata della sessione:
# Sessione sticky: stesso IP per tutto il flusso
SESSION_ID = "temu_cart_abc123"
proxy_user = f"user-country-US-city-newyork-session-{SESSION_ID}"
proxy_url = f"http://{proxy_user}:{PROXYHAT_PASS}@gate.proxyhat.com:8080"
# Tutte le richieste in questo flusso usano lo stesso IP
# → il server Temu vede una sessione coerente
# → prezzi e spedizione rimangono stabili
Per la paginazione del catalogo, alterna tra rotazione (per distribuire il carico) e sticky breve (per coerenza dei risultati di ricerca):
def scrape_category(search_key, max_pages=20):
results = []
for page in range(1, max_pages + 1):
# Rotazione IP per ogni pagina — distribuisce il carico
session = f"page_{page}_{int(time.time())}"
data = search_temu(search_key, page, session_id=session)
if data and "items" in data:
results.extend(data["items"])
# Rate limit: 1-2 req/sec
time.sleep(random.uniform(0.5, 1.5))
else:
# Retry con backoff esponenziale
for attempt in range(3):
wait = 2 ** attempt + random.uniform(0, 1)
time.sleep(wait)
data = search_temu(search_key, page, session_id=session)
if data and "items" in data:
results.extend(data["items"])
break
return results
Il pattern di retry con backoff esponenziale (2s, 4s, 8s con jitter) è essenziale. Il 429 da Temu è spesso transitorio — un IP diverso o un'attesa breve risolve il problema. Non ritentare immediatamente: peggiora solo la situazione.
Configurazione ProxyHat per Temu
ProxyHat offre proxy residenziali con geo-targeting paese e città, ideali per raschiare Temu. La configurazione avviene interamente tramite il formato username — nessun software aggiuntivo richiesto.
Per iniziare, consulta la documentazione ufficiale ProxyHat e la pagina prezzi per i piani residenziali. Per casi d'uso specifici, vedi le pagine web scraping e SERP tracking.
Parametri chiave per Temu:
- Geo-targeting paese:
-country-US,-country-DE,-country-FR— obbligatorio per prezzi coerenti per mercato. - Geo-targeting città:
-country-US-city-chicago— per variazioni regionali di prezzo e spedizione. - Sessione sticky:
-session-temu_cart_001— per flussi carrello e paginazione coerente. - Rotazione per richiesta: ometti il flag session per ruotare IP ad ogni richiesta.
Controlla la copertura completa delle posizioni proxy per verificare la disponibilità di città specifiche.
Esempi di formato URL:
# HTTP — residenziale US, rotazione
http://user-country-US-city-chicago:pass@gate.proxyhat.com:8080
# HTTP — residenziale DE, sessione sticky
http://user-country-DE-city-berlin-session-tmu01:pass@gate.proxyhat.com:8080
# SOCKS5 — per ambienti che preferiscono SOCKS
socks5://user-country-US:pass@gate.proxyhat.com:1080
Errori comuni e casi limite
1. Usare requests invece di curl_cffi
La libreria requests standard ha un fingerprint TLS Python, non Chrome. Cloudflare lo rileva e blocca nel 90%+ dei casi, anche con proxy residenziali. Usa sempre curl_cffi con impersonate o un browser headless.
2. Ignorare il geo-targeting città
Raschiare prezzi Temu con IP US generici quando il tuo sistema di price intelligence confronta prezzi tra stati porta a dati incoerenti. Lo stesso prodotto può mostrare prezzi diversi a New York vs Los Angeles a causa di logiche di spedizione regionali.
3. Rate limit troppo aggressivi
Anche con 100 IP residenziali, 10 req/sec per IP porta a blocchi rapidi. Mantieni 1-2 req/sec per IP, distribuisci con rotazione, e usa backoff esponenziale sui 429.
4. Token anti_content scaduto
Il token ha una validità limitata (10-30 minuti stimati). Se riutilizzi un token scaduto, ottieni 403 o payload vuoto. Implementa un refresh automatico del token ogni N minuti.
5. Non gestire i redirect regionali
Temu reindirizza gli utenti tra domini regionali (temu.com, temu.it, temu.de). Assicurati che il tuo scraper gestisca i redirect 302 e mantenga la coerenza del dominio con il geo-targeting del proxy.
Etica, Termini di Servizio e considerazioni legali
Raschiare dati pubblici del catalogo Temu — prezzi, titoli, disponibilità — è generalmente considerato lecito negli Stati Uniti sulla base del precedente hiQ Labs v. LinkedIn, dove la Corte ha stabilito che l'accesso a dati pubblicamente accessibili non viola il Computer Fraud and Abuse Act. Tuttavia, zone grigie rimangono:
- Termini di Servizio: i ToS di Temu possono vietare lo scraping automatizzato. La violazione dei ToS può comportare la chiusura dell'account, ma la applicabilità legale è contestata.
- GDPR e CCPA: non raschiare dati personali — recensioni con nomi utente, dati account, informazioni di spedizione. Limitati al catalogo pubblico anonimo.
- robots.txt: rispetta le direttive di
robots.txtdi Temu. Se un percorso è disallow, non raschiarlo. - Volume e impatto: non saturare i server di Temu. Usa rate limit conservativi e distribuisci il carico nel tempo.
Non raschiare aree autenticate: carrelli, account, ordini, wishlist. Questi richiedono credenziali e contengono dati personali — il rischio legale è significativamente superiore.
Per volumi elevati o dati che devono essere legalmente defensible, considera il feed merchant ufficiale di Temu o API partner. Se sei un venditore o un partner autorizzato, Temu offre accesso ai dati catalogo tramite canali ufficiali — più stabile, più veloce e senza rischio di blocco.
Punti chiave (Key Takeaways)
- Endpoint JSON > HTML parsing: colpire
/api/poppy/v1/goods-detaile/api/poppy/v1/searchrestituisce dati strutturati e più stabili del parsing HTML con classi hashate.- Proxy residenziali con geo-targeting città sono obbligatori: i proxy datacenter vengono bloccati istantaneamente dal fingerprinting TLS; i prezzi variano per regione, quindi
-country-US-city-chicagoè necessario per dati coerenti.- curl_cffi con impersonazione Chrome: risolve il problema del fingerprint TLS che fa fallire
requestsstandard.- Header
anti_content: estrailo da una sessione browser headless e rinfrescalo ogni 10-30 minuti.- Rate limit: 1-2 req/sec per IP, con rotazione e backoff esponenziale sui 429.
- Sessioni sticky per carrello/spedizione/paginazione; rotazione per catalog scale.
- Solo dati pubblici del catalogo: niente account, niente dati personali, rispetto di robots.txt e ToS.
Conclusione e prossimi passi
Raschiare dati prodotto e prezzo Temu nel 2026 è fattibile ma richiede disciplina tecnica: endpoint JSON invece di HTML, curl_cffi per il fingerprint TLS, proxy residenziali con geo-targeting città per prezzi coerenti, e gestione attenta del token anti_content. La combinazione di ProxyHat residenziali con geo-targeting -country-US-city-* e sessioni sticky -session-* copre il 90% degli scenari di e-commerce intelligence.
Per iniziare, configura un piano residenziale ProxyHat, testa con 10-20 richieste verso un singolo endpoint goods-detail, e misura il tasso di successo. Se è superiore all'85%, scala gradualmente aggiungendo IP concorrenti. Se è inferiore, il problema è quasi sempre il token anti_content o il fingerprint TLS — non il proxy.
Per approfondire casi d'uso correlati, leggi la nostra guida sul web scraping con proxy residenziali e sul tracking SERP. Per la copertura completa delle geolocalizzazioni disponibili, consulta le posizioni proxy.






