Temu Produkt- und Preisdaten scrapen: API vs. HTML – die zentrale Entscheidung
Temu ist einer der am schnellsten wachsenden E-Commerce-Marktplätze und hat laut Reuters im Jahr 2024 über 50 Milliarden USD Bruttowarenvolumen verzeichnet. Für Preis-Intelligence-Teams ist das ein enormer Datenpool – doch Temu bietet keine öffentliche API an. Wer Temu Produkt- und Preisdaten scrapen will, muss sich zwischen zwei Wegen entscheiden:
- HTML-Parsing: Die Produkt-Listing-Seiten und Detailseiten laden via Next.js/React. Die DOM-Struktur enthält gehashte CSS-Klassen (z. B.
_2c1f3d), die sich bei jedem Build ändern. Daten finden sich in einem eingebetteten__NEXT_DATA__-ähnlichen State-Blob im<script id="__NEXT_DATA__">-Tag. - Interne JSON-Endpunkte: Das Listing-Grid lädt Daten asynchron von Endpunkten wie
/api/poppy/v1/searchund/api/poppy/v1/goods/detail. Diese liefern strukturiertes JSON mitgoods_id,price,sku_listund mehr – deutlich stabiler als HTML, aber mit Anti-Bot-Schutz versehen.
Die Empfehlung für einen Temu Preis Scraper: Nutzen Sie die JSON-Endpunkte als primäre Datenquelle und HTML nur als Fallback. JSON ist strukturierter, weniger volatil und schneller zu parsen. Der Preis dafür ist ein höherer Anti-Bot-Aufwand – was uns zum nächsten Punkt bringt.
Temus Anti-Bot-Stack: Warum Datacenter-IPs sofort scheitern
Temu setzt eine mehrschichtige Anti-Bot-Infrastruktur ein, die ähnlich wie bei Cloudflare Turnstile funktioniert. Die drei wichtigsten Hürden:
1. Cloudflare Turnstile und JavaScript-Challenges
Beim ersten Aufruf von temu.com wird ein Turnstile-Challenge-Token generiert. Dieses Token wird in nachfolgenden API-Requests als anti_content-Header oder als Teil der Request-Signatur erwartet. Ohne gültigen Token gibt der Server HTTP 403 oder eine leere Response zurück.
2. Signed anti_content-Header
Die internen JSON-Endpunkte verlangen einen anti_content-Parameter, der aus einer Kombination von Browser-Fingerprint-Daten, Zeitstempel und einem geheimen Signatur-Algorithmus berechnet wird. Dieser Algorithmus ist obfuskiert und ändert sich gelegentlich. Praktisch bedeutet das: Sie müssen entweder einen Headless-Browser verwenden, der die Challenge nativ löst, oder den Signatur-Algorithmus reverse-engineeren – was extrem wartungsintensiv ist.
3. TLS/HTTP2-Fingerprinting
Temu prüft nicht nur die IP, sondern auch den TLS-Handshake. Ein Python requests-Aufruf hat einen anderen JA3/JA4-Fingerprint als ein echter Chrome-Browser. Datacenter-IPs mit nicht übereinstimmendem TLS-Fingerprint werden innerhalb von 2–5 Requests geblockt. Hier kommt curl_cffi ins Spiel – eine Bibliothek, die den TLS-Fingerprint von Chrome, Safari oder Firefox nachahmt.
Regel: Datacenter-Proxies sind für Temu praktisch nutzlos. Die Kombination aus Datacenter-IP + Python-TLS-Fingerprint wird sofort erkannt. Sie benötigen Residential Proxies mit echten ISP-IPs.
Daten lokalisieren: JSON-Endpunkte und eingebettete State-Blobs
Der __NEXT_DATA__-State-Blob
Temu nutzt Next.js. Auf jeder Produktseite finden Sie einen Script-Tag mit id="__NEXT_DATA__", der ein großes JSON-Objekt mit der gesamten Seiten-State enthält. Die relevante Struktur sieht vereinfacht so aus:
// Im HTML: <script id="__NEXT_DATA__" type="application/json">
{
"props": {
"pageProps": {
"goods": {
"goods_id": "601234567890",
"goods_name": "Wireless Earbuds Pro",
"salePrice": { "amount": 12.99, "currency": "USD" },
"sku_list": [
{ "sku_id": "sku_001", "spec": "Black", "price": 12.99 },
{ "sku_id": "sku_002", "spec": "White", "price": 13.49 }
],
"shipping_info": { "free_shipping": true, "estimated_days": 7 }
}
}
}
}
Um diesen Blob zu extrahieren, suchen Sie nach dem Script-Tag mit querySelector oder BeautifulSoup und parsen Sie den JSON-Inhalt. Die gehashten CSS-Klassen (_2c1f3d, _a8b9c2) sind für diesen Ansatz irrelevant – Sie arbeiten direkt mit dem JSON.
Interne JSON-Endpunkte
Die Listing-Seite lädt Produktdaten asynchron. Wenn Sie die Network-Requests im DevTools analysieren, finden Sie Aufrufe an:
GET /api/poppy/v1/search?keyword=laptop&page=1&pageSize=50– SuchergebnissePOST /api/poppy/v1/goods/detailmit Body{"goods_id": "601234567890"}– ProduktdetailsGET /api/poppy/v1/review/list?goods_id=...&page=1– Bewertungen
Diese Endpunkte erfordern den anti_content-Header und einen gültigen Cookie-Set aus der initialen Seitenladung. Die Response ist strukturiertes JSON:
// GET /api/poppy/v1/search (truncated)
{
"data": {
"list": [
{
"goods_id": "601234567890",
"goods_name": "Wireless Earbuds Pro",
"salePrice": { "amount": 12.99, "currency": "USD" },
"image_url": "https://img.temu.com/...",
"sold": 15234,
"rating": 4.6
}
],
"total": 3402,
"page": 1
},
"success": true,
"errCode": 0
}
Hashed CSS-Klassen und data-uniqid
Wenn Sie trotzdem HTML parsen müssen (z. B. als Fallback), achten Sie auf data-uniqid-Attribute, die Temu an Produkt-Karten vergibt. Diese sind stabiler als die gehashten Klassen. Ein XPath-Selector könnte so aussehen:
// Produktkarte: //*[@data-uniqid]
// Preis: //*[contains(@class, '_price')] oder //*[@data-uniqid]//*[contains(text(),'$')]
// Titel: //*[@data-uniqid]//a[contains(@href, '/goods/')]
Rate-Limits und warum City-Level-Geo zwingend ist
Temu hat keine offiziellen Rate-Limit-Dokumente veröffentlicht, aber aus praktischer Erfahrung gelten folgende Schwellenwerte:
| Szenario | Beobachtete Schwelle | Reaktion |
|---|---|---|
| Requests pro IP / Sekunde | ~5–10 Requests/s | HTTP 429 + 30s Cooldown |
| Requests pro IP / Stunde | ~500–800 Requests/h | Soft-Block (CAPTCHA-Challenge) |
| Requests pro IP / Tag | ~2.000–3.000 Requests/d | Hard-Block (IP-Ban, 24h+) |
Mit ProxyHat Residential Proxies und IP-Rotation pro Request können Sie diese Limits umgehen, da jede Anfrage von einer anderen IP kommt. Die empfohlene Rate liegt bei 3–5 Requests pro Sekunde mit Rotation, um natürliches Verhalten zu simulieren.
Geo-abhängige Preise und Versandkosten
Das ist der wichtigste Grund für City-Level-Geo-Targeting: Temu zeigt unterschiedliche Preise je nach Standort des Nutzers. Ein Produkt, das in New York $12.99 kostet, kann in Los Angeles $14.99 kosten – aufgrund von Versandkosten, lokalen Steuern und regionalen Promotions. Wenn Sie mit einer deutschen IP scrapen, sehen Sie möglicherweise gar keine US-Preise, sondern Euro-Preise mit EU-Versand.
ProxyHat erlaubt Geo-Targeting auf Länder- und Stadtebene direkt im Username:
# US-Preise aus New York
http://user-country-US-city-newyork:pass@gate.proxyhat.com:8080
# US-Preise aus Los Angeles
http://user-country-US-city-losangeles:pass@gate.proxyhat.com:8080
# Deutsche Preise aus Berlin
http://user-country-DE-city-berlin:pass@gate.proxyhat.com:8080
Für einen vollständigen Temu Preis Scraper sollten Sie mehrere Regionen parallel abfragen und die Ergebnisse in Ihrer Datenbank mit Geo-Tag versehen. So erkennen Sie regionale Preisunterschiede und dynamische Pricing-Strategien.
Python-Beispiel: curl_cffi + ProxyHat für Temu-Scraping
Hier ist ein vollständiges Beispiel, das curl_cffi (für TLS-Fingerprint-Mimikry) mit ProxyHat Residential Proxies kombiniert. Es ruft eine Temu-Produktseite ab und extrahiert den __NEXT_DATA__-Blob:
from curl_cffi import requests as cffi_requests
import json
import re
from bs4 import BeautifulSoup
# ProxyHat Residential Proxy mit US-Geo-Targeting
PROXY = "http://user-country-US-city-newyork:PASSWORD@gate.proxyhat.com:8080"
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",
"Referer": "https://www.temu.com/",
}
def fetch_temu_product(goods_id: str):
url = f"https://www.temu.com/goods-{goods_id}.html"
# curl_cffi ahmt Chrome-TLS-Fingerprint nach
response = cffi_requests.get(
url,
headers=HEADERS,
proxies={"http": PROXY, "https": PROXY},
impersonate="chrome120",
timeout=30,
)
if response.status_code != 200:
print(f"Fehler: HTTP {response.status_code}")
return None
# __NEXT_DATA__ Blob extrahieren
soup = BeautifulSoup(response.text, "html.parser")
script_tag = soup.find("script", id="__NEXT_DATA__")
if not script_tag:
print("__NEXT_DATA__ nicht gefunden")
return None
data = json.loads(script_tag.string)
goods = data.get("props", {}).get("pageProps", {}).get("goods", {})
# Relevante Felder extrahieren
result = {
"goods_id": goods.get("goods_id"),
"goods_name": goods.get("goods_name"),
"price": goods.get("salePrice", {}).get("amount"),
"currency": goods.get("salePrice", {}).get("currency"),
"sku_count": len(goods.get("sku_list", [])),
"skus": [
{"sku_id": s.get("sku_id"), "spec": s.get("spec"), "price": s.get("price")}
for s in goods.get("sku_list", [])[:5] # Truncated
],
"free_shipping": goods.get("shipping_info", {}).get("free_shipping"),
}
return result
# Beispielaufruf
product = fetch_temu_product("601234567890")
print(json.dumps(product, indent=2))
Die Ausgabe (truncated) sieht so aus:
{
"goods_id": "601234567890",
"goods_name": "Wireless Earbuds Pro",
"price": 12.99,
"currency": "USD",
"sku_count": 8,
"skus": [
{"sku_id": "sku_001", "spec": "Black", "price": 12.99},
{"sku_id": "sku_002", "spec": "White", "price": 13.49},
{"sku_id": "sku_003", "spec": "Blue", "price": 12.99}
],
"free_shipping": true
}
curl-Beispiel für schnelle Tests
curl -x "http://user-country-US:PASSWORD@gate.proxyhat.com:8080" \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
-H "Accept: text/html,application/xhtml+xml" \
-H "Accept-Language: en-US,en;q=0.9" \
"https://www.temu.com/goods-601234567890.html"
Weitere Proxy-Konfigurationen finden Sie in der ProxyHat-Dokumentation und auf der Preisseite.
Sticky Sessions: Konsistenz für Cart- und Shipping-Daten
Wenn Sie einen Workflow haben, der mehrere Requests benötigt (z. B. Produkt aufrufen → SKU auswählen → Shipping-Optionen prüfen), müssen alle Requests von derselben IP kommen. Andernfalls sieht Temu unterschiedliche Standorte und liefert inkonsistente Daten.
ProxyHat bietet sticky Sessions über das -session--Flag im Username:
# Sticky Session für 10+ Requests von derselben IP
http://user-country-US-city-newyork-session-abc123:PASSWORD@gate.proxyhat.com:8080
Die Session-ID abc123 hält die IP für die Dauer der Session stabil. Wenn die IP geblockt wird, ändern Sie einfach die Session-ID und erhalten eine neue IP.
Retries mit Backoff
import time
import random
def fetch_with_retry(url, max_retries=3, session_id=None):
for attempt in range(max_retries):
sid = session_id or f"retry-{attempt}-{random.randint(1000,9999)}"
proxy = f"http://user-country-US-session-{sid}:PASSWORD@gate.proxyhat.com:8080"
try:
response = cffi_requests.get(
url, headers=HEADERS,
proxies={"http": proxy, "https": proxy},
impersonate="chrome120", timeout=30
)
if response.status_code == 200:
return response
elif response.status_code == 429:
wait = 30 + random.uniform(5, 15)
print(f"429 – warte {wait:.0f}s")
time.sleep(wait)
else:
print(f"HTTP {response.status_code} – Retry {attempt+1}")
time.sleep(5)
except Exception as e:
print(f"Fehler: {e} – Retry {attempt+1}")
time.sleep(10)
return None
Pagination
Für Suchergebnisse paginieren Sie über den page-Parameter. Mit Rotation pro Request können Sie bis zu 50 Seiten abrufen, bevor die IP erschöpft ist:
def scrape_search(keyword: str, max_pages=20):
results = []
for page in range(1, max_pages + 1):
sid = f"search-{keyword}-p{page}-{random.randint(1000,9999)}"
proxy = f"http://user-country-US-session-{sid}:PASSWORD@gate.proxyhat.com:8080"
url = f"https://www.temu.com/api/poppy/v1/search?keyword={keyword}&page={page}&pageSize=50"
response = cffi_requests.get(
url, headers=HEADERS,
proxies={"http": proxy, "https": proxy},
impersonate="chrome120", timeout=30
)
if response.status_code == 200:
data = response.json()
items = data.get("data", {}).get("list", [])
if not items:
break # Keine weiteren Ergebnisse
results.extend(items)
time.sleep(random.uniform(0.5, 2.0)) # Natürliche Pause
else:
print(f"Seite {page}: HTTP {response.status_code}")
time.sleep(10)
return results
Ethik, TOS und rechtliche Hinweise
Beim Temu scrapen müssen Sie rechtliche und ethische Grenzen beachten:
- Nur öffentliche Katalogdaten: Scrapen Sie nur Daten, die ohne Login sichtbar sind – Produkttitel, Preise, Bilder, Bewertungen. Keine kontobasierten Daten, keine Bestellhistorie, keine personenbezogenen Daten.
- CFAA und Computer-Fraud: In den USA kann das Umgehen von Zugriffskontrollen unter den Computer Fraud and Abuse Act (CFAA) fallen. Scrapen Sie nicht hinter Login-Walls und umgehen Sie keine Bezahl-Schranken.
- GDPR (DSGVO): In der EU gilt die Datenschutz-Grundverordnung. Bewertungs-Texte könnten personenbezogene Daten enthalten. Speichern Sie nur aggregierte Metadaten (Sterne, Anzahl), nicht den vollen Text, wenn Nutzer identifizierbar sind.
- Temu TOS: Die Nutzungsbedingungen von Temu verbieten wahrscheinlich automatisiertes Scraping. Ein Verstoß kann zum IP-Ban oder rechtlichen Schritten führen. Prüfen Sie die Temu Terms of Service vor dem Einsatz.
- robots.txt: Prüfen Sie
https://www.temu.com/robots.txtund respektieren Sie die Disallow-Regeln. - Offizielle Merchant-Feeds: Wenn Sie ein Temu-Händler sind, nutzen Sie den offiziellen Merchant Feed oder die Open Platform API, sofern verfügbar. Das ist rechtlich sicherer und technisch stabiler.
Wichtiger Hinweis: Dieser Artikel dient ausschließlich Bildungszwecken. ProxyHat fördert nicht das Scrapen von Websites gegen deren Nutzungsbedingungen. Verwenden Sie diese Techniken nur für legitim zugängliche öffentliche Daten und konsultieren Sie einen Rechtsberater für Ihren konkreten Anwendungsfall.
Proxy-Typ-Vergleich für Temu-Scraping
| Proxy-Typ | Erfolgsrate bei Temu | Latenz | Preis | Empfehlung |
|---|---|---|---|---|
| Datacenter | <10% (sofort geblockt) | ~50ms | niedrig | Nicht empfohlen |
| Residential (rotierend) | 85–95% | ~200–500ms | mittel | Beste Wahl für Listings |
| Residential (sticky) | 90–98% | ~200–500ms | mittel | Beste Wahl für Detail-Sequenzen |
| Mobile | 95–99% | ~500–1000ms | hoch | Für hochsensible Abrufe |
ProxyHat bietet alle drei Proxy-Typen. Residential Proxies mit City-Level-Geo sind der Sweet-Spot für Temu. Siehe verfügbare Standorte und Preise.
Key Takeaways
- JSON-Endpunkte über HTML bevorzugen:
/api/poppy/v1/searchund/api/poppy/v1/goods/detailliefern strukturierte Daten, die stabiler sind als gehashte CSS-Klassen. - curl_cffi statt requests: TLS-Fingerprint-Mimikry ist zwingend – Temu blockt Python-Standard-Fingerprints innerhalb von 2–5 Requests.
- Residential Proxies mit City-Geo: Preise und Versandkosten variieren regional.
-country-US-city-newyorkliefert andere Daten als-country-DE-city-berlin. - Sticky Sessions für Workflows: Verwenden Sie
-session--IDs für mehrstufige Abrufe (Produkt → SKU → Shipping), um IP-Konsistenz zu gewährleisten. - Rate-Limits respektieren: Max. 3–5 Requests/s mit Rotation, Backoff bei HTTP 429, Session-Wechsel bei Hard-Blocks.
- Nur öffentliche Daten: Kein Account-Scraping, keine personenbezogenen Daten, robots.txt und TOS beachten.
Bereit loszulegen? ProxyHat Residential Proxies sind in über 190 Ländern verfügbar. Lesen Sie mehr über Web-Scraping-Anwendungsfälle oder SERP-Tracking mit ProxyHat.






