How to scrape Temu at scale in 2026 with proxies that work
Temu is one of the harder retail targets I run. The pages are heavy, the product data loads in pieces, and the site is quick to decide a session looks wrong. Datacenter IPs tend to get a captcha or an empty shell within a few requests. If you have tried a plain requests.get() loop and got back a login wall or a page with no prices, this is for you.
This tutorial is for people who need product, price and listing data from Temu for price monitoring, catalog research or dropship sourcing, and who are comfortable running a Python script on a VPS. I run this from Singapore, so my examples use Singapore and nearby exit locations. The outcome is a working pipeline that fetches public product pages through rotating proxies, extracts the fields you need, and survives retries without burning through your IP pool.
I will not pretend this is set-and-forget. Temu changes its front end often, and anything below that depends on a CSS selector will need maintenance. I will point out which parts break first.
What you need
- a Linux VPS or home server: 2 vCPU and 4 GB RAM is enough for around 5 to 10 parallel browser contexts. Headless Chromium is the memory hog.
- Python 3.11 or newer with
playwrightandhttpxinstalled - residential or mobile proxies: this is the part that matters. I budget by GB, not by IP count, because Temu pages are heavy. Plan for roughly 1 to 3 MB per fully rendered product page unless you block images (see step 5), and check your own numbers on a test run.
- a proxy provider that supports sticky sessions and country or city targeting. Rotating per request is available from most providers, sticky sessions of 5 to 30 minutes are what you will actually use.
- somewhere to store results: SQLite is fine up to a few million rows, Postgres after that
- time to read Temu’s own robots.txt and terms before you start
A note on legality. Scraping public pages sits in a grey zone that differs by country, and terms of service can restrict automated access even when the data is public. Do not log in, do not touch anything behind an account, and do not collect personal data. This is not legal advice, so talk to a lawyer if you are building a business on this data.
If you are new to proxy types, my comparison in residential vs mobile proxies for ecommerce scraping covers the tradeoffs in more depth than I will here.
Step by step
1. Check what the robots file allows
Start by reading what the site asks crawlers to avoid. The Robots Exclusion Protocol, RFC 9309 defines how those rules work. They are not access control, but ignoring them is a choice you should make knowingly.
curl -s https://www.temu.com/robots.txt | head -50
Expected output: a list of Disallow paths for user agents. Note which paths you plan to hit (product detail pages, category listings) and which are disallowed. I skip anything under account, cart and checkout paths on principle.
If it breaks: if curl returns a 403 or an HTML challenge instead of text, your own IP is already flagged. Run it from a different network or through a proxy, which brings us to step 2.
2. Test your proxy before you scrape anything
Confirm the exit IP, country and type before you point it at Temu. A proxy that leaks your real IP or exits in the wrong country wastes the whole run.
curl -s -x "http://USER:[email protected]:PORT" https://api.ipify.org
curl -s -x "http://USER:[email protected]:PORT" https://ipinfo.io/json
Expected output: an IP that is not yours, with the country and ASN you asked for. For residential or mobile, the ASN should belong to a consumer ISP or carrier, not a hosting company.
If it breaks: a 407 means bad credentials or the format your provider expects (some want USER-country-sg style suffixes in the username). A timeout usually means you are on a port your provider has not opened for your account.
3. Pick the market and match everything to it
Temu serves different catalogs, currencies and shipping rules per country. Pick one market and make the proxy exit, Accept-Language, timezone and locale all agree. A US IP with a Singapore timezone and en-SG locale is a mismatch that costs you sessions.
For a US catalog, I use US residential exits, en-US, and America/New_York or another US timezone. For Singapore pricing, a Singapore exit and Asia/Singapore.
Expected output: a small config dict you reuse everywhere.
MARKET = {
"locale": "en-US",
"timezone": "America/New_York",
"proxy_country": "us",
}
If it breaks: if prices come back in the wrong currency, the exit country does not match what the provider thinks it is. Re-run step 2 and check the geo field.
4. Load one product page in a real browser
Temu renders most product data client side, so plain HTTP gets you a skeleton. Use Playwright with the proxy set at the context level. The Playwright network docs cover the proxy options.
from playwright.sync_api import sync_playwright
PROXY = {
"server": "http://gate.yourprovider.com:PORT",
"username": "USER-country-us-session-abc123",
"password": "PASS",
}
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
ctx = browser.new_context(
proxy=PROXY,
locale="en-US",
timezone_id="America/New_York",
viewport={"width": 1366, "height": 768},
)
page = ctx.new_page()
page.goto("https://www.temu.com/", wait_until="domcontentloaded")
page.wait_for_timeout(3000)
print(page.title())
browser.close()
Expected output: the page title for the Temu home page, not a challenge or an error page.
If it breaks: a blank title or a captcha on the very first load means the proxy IP is burned or the fingerprint looks automated. Swap the session ID for a fresh IP first. If that fails, read the fingerprint section of my notes on antidetect browsers, because stock headless Chromium leaks several signals that an antidetect profile hides.
5. Cut the bandwidth you do not need
Residential traffic is billed per GB, and most of a Temu page is images, fonts and tracking scripts. Block them at the route level.
def block_heavy(route):
if route.request.resource_type in {"image", "media", "font"}:
return route.abort()
return route.continue_()
ctx.route("**/*", block_heavy)
Expected output: the same product data with a much smaller transfer per page. Measure it by summing response sizes over 20 pages before and after. In my runs the drop is large, but treat my numbers as a prompt to measure yours.
If it breaks: if prices or variants stop appearing, you blocked too much. Allow font back first, then check whether a script you aborted was fetching price data. Do not block xhr or fetch types.
6. Extract the data from network responses, not the DOM
CSS selectors on Temu are unstable. The same data usually arrives as JSON in a background request or in an embedded script tag. Listen for responses and parse those instead.
captured = []
def on_response(resp):
ct = resp.headers.get("content-type", "")
if "json" in ct and resp.status == 200:
try:
captured.append({"url": resp.url, "data": resp.json()})
except Exception:
pass
page.on("response", on_response)
page.goto(PRODUCT_URL, wait_until="networkidle")
Expected output: a list of JSON payloads. Open them in a file and search for a known price from the visible page to find the right one. Save the endpoint pattern, then pull only the fields you need: title, price, original price, rating, review count, sold count, and variant list.
If it breaks: the JSON shape changes without notice. Log the raw payload for failures so you can see what moved. This is the first thing to break in production, so keep the parsing layer small and separate.
7. Add sessions, pacing and retries
Do not hammer. A sticky session that browses at a human pace lasts far longer than a fresh IP per request.
- keep one proxy session per browser context, 5 to 15 pages per session
- wait 4 to 10 seconds between pages, with random jitter
- on a captcha, 403 or 429, drop the session, take a fresh IP, and back off for a minute
- cap retries at 3 per URL, then park the URL in a failed table
import random, time
def polite_wait():
time.sleep(random.uniform(4, 10))
Expected output: a success rate you can read off a counter. I aim for above 90 percent on clean residential and treat anything below 70 percent as a signal to change the setup, not push harder.
If it breaks: if every request in a session fails after page 3 or 4, shorten sessions. If failures cluster on one subnet, your provider’s pool in that city is dirty, so ask for a different region.
8. Store results and dedupe
Write each result with the URL, a fetch timestamp, the proxy country and the raw payload hash. Price history is the valuable part, so never overwrite old rows.
CREATE TABLE temu_prices (
product_id TEXT,
fetched_at TEXT,
price REAL,
currency TEXT,
sold_count INTEGER,
payload_hash TEXT
);
Expected output: one new row per product per run, and a cheap diff query to find price changes.
If it breaks: duplicate rows mean you are rescraping URLs that did not change. Skip any URL fetched in the last N hours.
Common pitfalls
- using datacenter proxies and blaming the target. Datacenter ranges are the first thing most large retailers score down. Use residential or mobile for Temu.
- rotating the IP on every request. It looks unnatural, costs more, and breaks any cart or locale state. Sticky sessions behave better.
- mismatched geography. IP in one country, locale and timezone in another. Fix this before anything else.
- scraping with images on. You pay for gigabytes of product photos you never read.
- no failure logging. When Temu changes a payload, you want the raw response saved so the fix takes ten minutes, not a day.
If you run several accounts or browser profiles alongside this, the operational habits in multi-account ops carry over directly, especially around keeping sessions isolated.
Scaling this
Here is what changes as volume grows. These are my own rules of thumb, not vendor numbers.
At 10x (a few thousand pages a day), one VPS and one proxy plan handle it. Your main job is the retry logic and a failure table. Bandwidth is a rounding error on the bill.
At 100x (tens of thousands of pages a day), proxy cost becomes the biggest line item, so the image blocking in step 5 pays for itself. You will want a job queue (Redis or a Postgres table with SKIP LOCKED), several worker processes, and per-worker proxy sessions. Start tracking success rate per proxy region, because some pools are much cleaner than others.
At 1000x (hundreds of thousands of pages a day), you are in negotiated-pricing territory with providers, and you should run more than one. Add a health score per exit subnet and drop dirty ones automatically. Browser rendering gets expensive, so look hard at whether the JSON endpoints from step 6 can be called directly with httpx once you have a valid session, and use the browser only to mint and refresh sessions. That hybrid is where cost per thousand pages falls the most, and it is also the most fragile part, so budget maintenance time for it.
At any scale, respect the load you put on the site. Slow and steady gets you more data over a month than a burst that gets the whole pool flagged. Check your provider’s terms too, since some restrict certain targets.
Where to go next
- all tutorials on the blog index for the full list of target-scrape guides
- how to scrape Shein with mobile proxies for a similar target with a different anti-bot profile
- residential vs mobile proxies for ecommerce scraping to pick the right proxy type before you buy bandwidth
If you hit a specific block I did not cover, tell me what the response looked like and which step failed. That usually narrows it down quickly.
Written by Xavier Fok
disclosure: this article may contain affiliate links. if you buy through them we may earn a commission at no extra cost to you. verdicts are independent of payouts. last reviewed by Xavier Fok on 2026-10-17.