# Taobao Product Feed Scraper (`dami_studio/taobao-product-feed-scraper`) Actor

A Taobao product discovery feed: title, price in CNY, image, product URL, seller and shop IDs, from Taobao's own recommendation module. No account, no Chinese IP, no browser. $1.95 per 1,000 products, flat on every plan. Feed, not keyword search.

- **URL**: https://apify.com/dami\_studio/taobao-product-feed-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Taobao Product Feed Scraper

Reads the product feed behind the 猜你喜欢 ("guess you like") strip on the taobao.com homepage and
hands it back as rows. Product ID, title, price in CNY, image, clean product URL, seller ID, shop ID
and two levels of category ID.

No login. No cookies to paste. No API key. No browser, so nothing to babysit. It talks to Taobao's
own mobile JSON gateway over plain HTTP through rotating datacenter addresses.

**Read this before you buy: there is no keyword box.** This is a discovery firehose, not a search
engine. See [What this does not do](#what-this-does-not-do).

***

### What you get

One run with `maxItems: 800` returned 800 distinct products from 49 calls in 78 seconds. Coverage
below is measured on exactly that run, not estimated:

| Field | Coverage | Example |
|---|---|---|
| `productId` | 100% | `1050937490916` |
| `title` | 100% | `三顿半|快饮速溶咖啡拿铁美式超即溶冷萃无蔗糖冻干黑咖啡粉60颗` |
| `price` | 100% | `299` |
| `currency` | 100% | `CNY` (always) |
| `productUrl` | 100% | `https://item.taobao.com/item.htm?id=1050937490916` |
| `imageUrl` | 100% | `https://img.alicdn.com/bao/uploaded/...jpg` |
| `sellerId` | 100% | `3519432762` |
| `shopId` | 100% | `66539736` |
| `categoryId` | 100% | `50002256` (leaf category) |
| `rootCategoryId` | 100% | `50026316` (level-1 category) |
| `similarItemsUrl` | 100% | Taobao's "find similar" page for the item |
| `trackedUrl` | 100% | the feed's original link, with its `scm` / `pvid` attribution intact |
| `skuId` | **82%** | `6279287258491` — Taobao only puts a SKU on some cards |
| `promotionBadgeImageUrl` | **33%** | the promo ribbon image Taobao draws on the tile |
| `feedPage`, `feedPosition`, `scrapedAt` | 100% | where in the feed the row came from |

Spread, re-measured on 2026-08-09 across 1,021 distinct products (two 600-product runs): 745 distinct
shops, 371 distinct leaf categories, 77 level-1 categories, prices from **¥0.01 to ¥99,999 with a
median of ¥19.9** — 95% of rows under ¥200 and 99% under ¥1,000. The ¥99,999 row is a single real
phone listing; the next highest was ¥5,000. Products are deduplicated by `productId` within a run —
0 duplicates in either 600-row run.

***

### What this does not do

Being blunt about this is cheaper for both of us than a refund.

- **No keyword search.** There is no query parameter and there is no way to add one. Taobao's search
  API (`mtop.taobao.wsearch.appsearch`) answers `RGV587_ERROR::SM` and redirects to
  `login.taobao.com/member/login.jhtml?...&from=sm`. That is an authentication demand, not a captcha,
  and it was re-tested from a home address, two datacenter addresses, a rented static-ISP address and
  a mainland-China address, at four API versions, over GET and POST, on four Alibaba hosts and under
  three different referers. Every combination fails identically. If you need keyword search, this is
  not the actor.
- **No product detail.** Same wall: `mtop.taobao.detail.getdetail`, `getdesc` and
  `mtop.taobao.rate.detaillist.get` are all behind it. So there is no description, no stock, no
  shipping, no attributes, no variants and no reviews here. The feed is card-level data only.
- **No sales volume.** The raw card has a `month_sale` field. It was an empty string on 480 out of
  480 rows and on every row since, so this actor does not emit it. A "monthly sales" column built
  out of that field would be fiction.
- **No list price / discount.** The card also carries an `originUmpPrice:1320^1500` pair that reads
  like a was/now price. On 139 of 480 rows neither number matched the price actually charged, and on
  352 of 480 the two numbers were identical. Publishing it as a discount would be making one up.
- **No control over which products appear.** Taobao decides. You can narrow the results by price
  after the fact, and that is all.
- **Not a stable catalogue.** The same product IDs do not come back run after run. This is a live
  merchandising feed.

***

### Limits, measured

**Depth.** The response advertises `pageTotal: 12` and `itemTotal: 300`. Both are cosmetic and both
are wrong — `pageNum` keeps working past 200 and single runs have pulled 1,580 distinct products.
`pageSize` is ignored outright: the server returns exactly 20 cards whatever you ask for (tested at
20, 40, 50, 100 and 200). So depth comes from the feed reshuffling between calls, not from paging.

**Yield.** About 13 new products per call, averaged over 120 calls. It decays as a run accumulates
IDs: roughly 16/call over the first twenty calls, about 8/call by the hundredth. Real runs — 5
products in 1 call, 400 in 23 calls (46 s), 800 in 49 calls (78 s), 1,000 in 61 calls, 1,580 in 120
calls. Asking for a lot more than ~1,500 in one run means a long tail of calls for very few new
rows, so the actor stops on its own after 12 consecutive calls that return nothing new and tells you
why. It also stops cleanly before the run timeout rather than being killed mid-walk.

**Rate limit.** This is the real constraint, and it is a call *count* per exit address, not a rate.
About 50 calls per address, then Taobao answers `FAIL_SYS_USER_VALIDATE` with an `x5secdata` cookie
and stays that way for that address. Measured first block at call #52, #52, #54 and #55 on four
independent addresses. There is no burst limit at all — 25 back-to-back calls with zero delay were
25/25 successful. The actor rotates its exit address every 40 calls, which recovers instantly and
means a normal run never sees a block. Roughly 1 in 5 fresh datacenter addresses arrives already
flagged; the actor throws those away on sight and takes another rather than reporting a failure.

**Transient errors.** Roughly 1 call in a few hundred comes back with Alibaba's own
`TppErrorCode-[SOLUTION_EXECUTE_TIMEOUT]` (their internal 999 ms RPC timeout). The actor retries in
place instead of rotating, because the address is fine.

**Proxies.** Plain Apify datacenter addresses are enough. No Chinese IP, no residential bandwidth, no
ISP pool. A 120-call run over datacenter addresses had zero blocks. If you want to use your own proxy
servers, there is a field for it under Advanced, but nothing about this endpoint requires it. Not all
addresses answer at the same speed — one 1,000-product run drew an address that took ~10 s per call
where the first took ~1.6 s — so the actor watches its own latency and swaps a slow address out.

**Stability.** The feed this actor reads is one Taobao publishes for its own home-page modules, and
Alibaba can retire or renumber it at any time, without notice — there is nothing anyone can do about
that. If it happens, this actor writes an uncharged `FEED_UNAVAILABLE` row saying exactly what
Taobao answered, and fails loudly. It will not quietly return zero rows and bill you for the run.

***

### Input

| Field | Type | Notes |
|---|---|---|
| `maxItems` | integer 1–5000 | How many distinct products to return. You are charged once per product. Leave it empty and the run returns one free sample row instead of scraping. |
| `minPriceCny` | integer | Optional. Drop anything under this many yuan. |
| `maxPriceCny` | integer | Optional. Drop anything over this many yuan. |
| `maxRequests` | integer | Optional ceiling on calls to Taobao. Left empty, the actor sizes it from `maxItems`. |
| `proxyConfiguration` | object | Optional. Your own proxy servers, if you would rather use them. |

```json
{
  "maxItems": 500
}
```

Price filtering runs locally, after Taobao has answered, because the feed has no price parameter.
Rows dropped by a filter are **not charged** — but they do cost requests, so a narrow window makes a
run slower and may not fill the order. A real run asking for 30 products between ¥150 and ¥900 made
20 calls, returned 19 products and threw away 361 that fell outside the window; you were charged for
19\. If a window matches almost nothing, the run stops early and says so rather than grinding.

***

### Output

```json
{
  "productId": "949545269284",
  "title": "butterfly香水小样泰国小众沉香木与安息香泥中水牛月桂叶",
  "price": 27,
  "currency": "CNY",
  "productUrl": "https://item.taobao.com/item.htm?id=949545269284",
  "imageUrl": "https://img.alicdn.com/bao/uploaded/i4/.../O1CN...-item_pic.png",
  "skuId": "6279287258491",
  "sellerId": "3519432762",
  "shopId": "385530380",
  "categoryId": "50010815",
  "rootCategoryId": "50050359",
  "promotionBadgeImageUrl": null,
  "similarItemsUrl": "https://www.taobao.com/market/lu/findgoods_router.php?id=949545269284",
  "trackedUrl": "https://item.taobao.com/item.htm?id=949545269284&scm=...&pvid=...",
  "feedPage": 3,
  "feedPosition": 11,
  "scrapedAt": "2026-08-09T17:20:41.006Z"
}
```

Titles are Chinese, because Taobao is a Chinese marketplace. Prices are yuan.

***

### What it is good for

- **Trend and assortment sampling.** A few thousand rows a day is a rolling read of what Taobao is
  actively merchandising, with category IDs attached.
- **Price benchmarking by category.** `rootCategoryId` plus `price` over a few runs gives a real
  distribution instead of a guess.
- **Seller and shop discovery.** 625 distinct shops in one 800-row run, each with `sellerId` and
  `shopId` you can key on.
- **Product-image and title corpora** for training, search or classification work.
- **Seeding another pipeline.** `productId` is the id every other Taobao tool expects.

It is not for "find me every red dress under ¥50". Taobao puts keyword search behind a logged-in
account, and this actor does not use one.

***

### FAQ

**Can I search Taobao by keyword with this?**
No. It has no keyword input. Taobao's keyword search API requires a logged-in account, and this actor
does not use one.

**Can I scrape a specific Taobao product by ID or URL?**
No. Taobao's product-detail API is behind the same login wall as search. This actor only returns what
the homepage feed hands out.

**Do I need a Taobao account, cookies, or a Chinese IP address?**
None of the three. Plain datacenter addresses work.

**Are the titles in English?**
No, Chinese. The feed returns what Taobao stores. Run them through a translator if you need English.

**How many products can I get in one run?**
1,580 distinct products in one 120-call run is the highest measured. Up to about 800 the yield is
close to linear (800 rows in 49 calls, 78 seconds). Past ~1,500 you are paying for a lot of calls to
find a few new items.

**How much does it cost?**
$1.95 per 1,000 products, plus a $0.001 start fee. It is a flat rate: the same $1.95 on the free plan
as on any paid one, with no volume tiers, no minimum spend and no add-on fees. A 1,000-product
discovery run costs $1.951 whether it takes one minute or five.

Its sibling Taobao Category Products Scraper returns product rows at the same $1.95 per 1,000, on a
$0.002 start fee instead of $0.001. Pick this one when you want a broad discovery feed across the
whole catalogue; pick that one when you know which category you want and would rather page through
it deterministically.

**Will I get the same products if I run it twice?**
Some overlap, not the same set. The feed reshuffles constantly and Taobao decides what is in it.

**Does it include sales volume, reviews, or stock?**
No. See [What this does not do](#what-this-does-not-do). The feed does not carry them, and the APIs
that do are behind a login wall.

**What happens if a run gets blocked?**
It writes an uncharged `BLOCKED` row with the exact response Taobao gave and how many products it had
returned before that point. You are charged for products, never for failures.

**What am I charged for?**
One event per product row. Sample rows, diagnostic rows, filtered-out rows and failed runs are all
free.

***

### Charging

Pay per event: **$1.95 per 1,000 products** ($0.00195 each), plus a $0.001 actor start fee. One
`product` event per product row written to the dataset. Nothing else is charged:

- an empty input returns one labelled sample row and charges nothing,
- rows dropped by `minPriceCny` / `maxPriceCny` charge nothing,
- `BLOCKED`, `NO_RESULTS`, `FEED_UNAVAILABLE` and `RUN_FAILED` diagnostic rows charge nothing.

# Actor input Schema

## `maxItems` (type: `integer`):

Number of distinct Taobao products to collect (1-5000). You are charged once per product returned. There is no keyword input: this reads Taobao's own homepage recommendation feed, which reshuffles on every call, so a bigger number simply means a longer walk through it. Leave this empty and the run returns one free sample row instead of scraping anything.

## `minPriceCny` (type: `integer`):

Optional. Drop products cheaper than this many yuan. The feed has no price parameter, so this is applied after the fetch and dropped rows are never charged — expect the run to make more requests for the same number of results.

## `maxPriceCny` (type: `integer`):

Optional. Drop products more expensive than this many yuan. Measured across 1,021 distinct products (two 600-product runs, 2026-08-09): 0.01 to 99,999 CNY, median 19.9 - 95% of rows under 200 CNY and 99% under 1,000 CNY.

## `maxRequests` (type: `integer`):

Optional hard ceiling on how many calls the run makes to Taobao. Each call returns 20 cards, about 13 of which are products the run has not seen yet (measured over 120 calls; the rate falls to about 8 by the hundredth call). Leave empty and the actor sizes the budget from "maxItems".

## `proxyConfiguration` (type: `object`):

Optional. The actor already rotates Apify datacenter addresses on its own, which is all this endpoint needs — no Chinese IP and no residential bandwidth. Set this only if you want the run to go through your own proxy servers.

## Actor input object example

```json
{
  "maxItems": 200,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

One row per product from Taobao's homepage recommendation feed: product ID, title, CNY price, product and image URLs, SKU, seller ID, shop ID and category IDs, plus the feed page and position the item came back on so you can tell where in the feed it sat. This is a discovery feed, not keyword search — you get what Taobao is recommending, not what you searched for. If the gateway blocks the run or returns no feed, you get a labelled diagnostic row saying which, and it is not charged.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "maxItems": 200,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/taobao-product-feed-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "maxItems": 200,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/taobao-product-feed-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "maxItems": 200,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call dami_studio/taobao-product-feed-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,dami_studio/taobao-product-feed-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Jk2pqSY9mrgReeoSj/builds/vH8htaYLVxGvd2xcI/openapi.json
