Taobao and Tmall API in Python: Search, SKUs, Q&A, and Reviews

Build a Taobao and Tmall product-research workflow in Python with sales and price filters, SKU details, buyer Q&A, review pagination, costs, and safe normalization.

Dark Taobao and Tmall research console connecting filtered search, SKU details, buyer questions and review evidence

Sorting by sales is easy. Deciding what that sales-ranked list means is not. A Taobao search can narrow a market by keyword, price band, and Tmall status, but it cannot tell you whether the cheapest visible offer matches the SKU you need or whether review language belongs to the same variant. The new Taobao endpoints become useful only when search, product detail, buyer questions, and reviews are joined with explicit provenance.

This guide builds that pipeline in Python. It is for developers working on assortment research, merchandising, competitor monitoring, or shopping agents. The examples use live calls made on November 1, 2026 and distinguish documented inputs from observed-only response fields.

Key takeaway (TL;DR)

  • SandBase lists five Taobao endpoints covering Taobao and Tmall search, item detail, shop catalogs, buyer questions, and product reviews.
  • Search supports documented sales/price sorting, Tmall-only filtering, price bounds, and page pagination.
  • Live page prices ranged from $0.0208 to $0.0278 per completed call on November 1, 2026.
  • The live payload shapes differ: search used model.itemList, detail used item / seller / delivery, and reviews used comments plus hasNextPage.
  • Normalize these into your own schema and attach item ID, page, request, run ID, and observation time before an agent sees the data.

The five-endpoint toolkit

The Taobao API catalog on SandBase covers both Taobao and Tmall product research:

EndpointReader taskLive page price on 2026-11-01
/v1/api/taobao/search/itemsKeyword search, sorting, price range, Tmall filter$0.0278
/v1/api/taobao/item/detailProduct title, images, price, SKUs, delivery, seller$0.0208
/v1/api/taobao/shop-item-listBrowse a known shop with sorting and pagination$0.0278
/v1/api/taobao/item/questionsPage through buyer questions and answers$0.0208
/v1/api/taobao/item/reviewsPage through latest or default review order$0.0278

Taobao API catalog listing search, detail, shop, Q&A and review endpoints The Taobao catalog showed five endpoints on November 1, 2026. The directory establishes available routes; it does not guarantee that every product has Q&A or review data.

Taobao provides the underlying marketplace data. SandBase supplies one bearer-authenticated Platform API surface and a common completion envelope. The response inside outputs[0].data remains an upstream structure and must be parsed defensively.

Design the search before writing code

A useful search request records the decision you are trying to make. For example: “Find non-Tmall Bluetooth headphones between CNY 100 and 300, ordered by sales, then inspect the top ten unique item IDs.” That is reproducible. “Find popular headphones” is not.

The search endpoint documents these inputs:

  • required keyword;
  • sort: _sale, _bid, bid, or _coefp;
  • tmall: boolean;
  • startPrice and endPrice: inclusive string price bounds;
  • page: integer page number.

Taobao Product Search endpoint showing sort, Tmall and price filters The search reference exposes six inputs and the production route POST /v1/api/taobao/search/items. Captured November 1, 2026; enum meanings beyond the page labels should not be guessed.

The enum names are terse. _sale is labelled as a supported sort value, but do not invent a semantic description for every code unless the page documents it or a controlled test proves it. A production UI should expose friendly labels only for meanings you have verified.

Python
import os
import requests

BASE = "https://api.sandbase.ai/v1/api/taobao"
HEADERS = {
    "Authorization": f"Bearer {os.environ['SANDBASE_API_KEY']}",
    "Content-Type": "application/json",
}

def call_taobao(path: str, payload: dict) -> dict:
    response = requests.post(
        f"{BASE}/{path}", headers=HEADERS, json=payload, timeout=60
    )
    response.raise_for_status()
    body = response.json()
    outputs = body.get("outputs") or []
    if body.get("status") != "completed" or not outputs:
        raise RuntimeError(
            f"Taobao call did not complete: {body.get('status')} {body.get('error')}"
        )
    data = outputs[0].get("data")
    if not isinstance(data, dict):
        raise RuntimeError("Taobao call completed without an object payload")
    return {"run_id": body.get("id"), "data": data}

search = call_taobao("search/items", {
    "keyword": "蓝牙耳机",
    "page": 1,
    "sort": "_sale",
    "tmall": False,
})

The business fields below were observed in live calls on November 1, 2026 (UTC+8). They are illustrative, not documented guarantees. Search run 7f6d1a89-ab65-4147-875c-ff4001a08553 returned a top-level code, extraMap, and model; the observed product list lived at model.itemList.

That nesting is why a generic “every commerce API returns products” helper is a bad abstraction. Write a Taobao adapter that accepts upstream variation and emits a stable internal record.

Python
def iter_search_items(data: dict):
    model = data.get("model") or {}
    items = model.get("itemList") or []
    if not isinstance(items, list):
        return []
    return items

def normalize_search_item(item: dict, run_id: str, request: dict) -> dict:
    return {
        "marketplace": "taobao",
        "item_id": item.get("itemId") or item.get("nid") or item.get("id"),
        "title": item.get("title"),
        "price_cny_raw": item.get("price"),
        "sales_raw": item.get("sold") or item.get("sales"),
        "shop_name": item.get("shopName") or item.get("nick"),
        "query": request,
        "observed_run_id": run_id,
        "observed_at": "2026-11-01",
    }

Alternative field names in that adapter are fallbacks, not claims that every response contains them. Log which path was used and alert when the record lacks an item ID.

Join detail by item ID, not by title

Titles are marketing copy. They change and often pack multiple compatible devices or promotional terms into one line. Join search to detail with the product’s item ID.

The detail endpoint takes one itemId. In live run 0668ca74-5f26-42b3-8ba5-d6d1d591619d, the observed payload had three top-level objects: item, seller, and delivery. The item contained a title and five image URLs in the trimmed sample; delivery exposed area_id, delivery_fee, from, and to. Those field names are observed-only.

Python
detail = call_taobao("item/detail", {"itemId": "920640959876"})

def normalize_detail(data: dict, run_id: str, requested_item_id: str) -> dict:
    item = data.get("item") or {}
    seller = data.get("seller") or {}
    delivery = data.get("delivery") or {}
    return {
        "marketplace": "taobao",
        "item_id": item.get("itemId") or requested_item_id,
        "title": item.get("title"),
        "images": (item.get("images") or [])[:8],
        "sku_source": item.get("skuBase"),
        "seller_id": seller.get("sellerId"),
        "shop_id": seller.get("shopId"),
        "delivery_fee_raw": delivery.get("delivery_fee"),
        "delivery_from": delivery.get("from"),
        "delivery_to": delivery.get("to"),
        "observed_run_id": run_id,
        "requested_item_id": requested_item_id,
    }

Pass the same requested ID into the adapter; the live evidence did not establish that item.itemId is always present, so the request is the authoritative join-key fallback. Do not compare a search-card price with a detail SKU without resolving the selected variant. A visible “from” price, a coupon price, and a specific color/capacity SKU are different business facts.

Use Q&A and reviews for different questions

Buyer Q&A and reviews are not interchangeable. Q&A reveals uncertainty before purchase: compatibility, sizing, included accessories, delivery, or usage. Reviews describe reported experience after purchase, with all the familiar sampling and authenticity limitations.

The Q&A endpoint accepts itemId and integer page. The reviews endpoint accepts itemId, integer page, and orderType of feedbackdate or general. Use only those documented pagination controls.

Taobao Product Reviews endpoint showing orderType and page inputs The review route supports latest/default ordering and integer page pagination. Captured November 1, 2026; review content remains user-generated evidence, not a verified product claim.

Review run 23dc11fa-d632-47ea-b54a-8bb34a3333ba observed currentPageNum: 1, hasNextPage: true, total: 20000, a comments list, and keyword labels such as “good sound quality.” These are response observations, not a promise that every item returns the same fields or that label counts represent unique verified buyers.

Python
reviews = call_taobao("item/reviews", {
    "itemId": "920640959876",
    "page": 1,
    "orderType": "feedbackdate",
})

def review_page(data: dict) -> dict:
    comments = data.get("comments") or []
    return {
        "page": data.get("currentPageNum"),
        "has_next": bool(data.get("hasNextPage")),
        "comments": [
            {
                "date": row.get("date"),
                "content": row.get("content"),
                "variant": row.get("auction"),
                "photos": row.get("photos") or [],
            }
            for row in comments
        ],
    }

Stop when hasNextPage is false, the next page is empty, or your declared sampling budget is reached. Do not crawl an unbounded review history merely because the API exposes another page.

Three workflows and their costs

Prices below were observed on November 1 and can change.

1. Daily category scan

Search 30 keyword/price-band combinations and enrich 40 candidates: 30 × $0.0278 + 40 × $0.0208 = $1.666 per run. At 30 runs, that is $49.98. Cache detail records and re-fetch only when an item remains in the shortlist.

2. Tmall assortment monitor

Search 20 Tmall-only queries, then walk one page for 10 known shops: 20 × $0.0278 + 10 × $0.0278 = $0.834 per run. This measures the observed catalog, not sales performance or stock certainty.

3. Voice-of-customer sample

For 25 products, fetch detail, one Q&A page, and two review pages: 25 × ($0.0208 + $0.0208 + 2 × $0.0278) = $2.43. State that the study sampled two review pages per item; do not generalize it to the full review corpus.

The agent boundary

An agent should not receive an entire raw commerce payload and improvise joins. Give it a bounded evidence packet:

JSON
{
  "item_id": "920640959876",
  "search_observation": {"query": "蓝牙耳机", "page": 1},
  "detail_observation": {"title": "...", "delivery_fee_raw": "..."},
  "review_sample": {"pages": 2, "latest_first": true},
  "limits": ["price may be variant-dependent", "review sample is incomplete"]
}

Then ask for a narrow output: flag missing evidence, group observed complaint themes, or propose follow-up questions. Do not ask it to choose the “best product” from incomplete public data.

Limits

Search sorting reflects the platform response at a moment in time. Sales and review numbers may be formatted or aggregated by the upstream interface. Tmall filtering changes the candidate pool but does not certify product authenticity. A review sample can overrepresent recent, incentivized, or variant-specific experiences. Delivery depends on destination. SKU prices must be resolved at the variant level. Finally, original payload fields can change even while the common completion envelope remains stable.

For wholesale MOQ and supplier signals, use the 1688 Product Finder guide instead. For a retailer with a simpler search/detail/comment path, compare the architecture in the JD.com API guide.

FAQ

Does this API cover both Taobao and Tmall?

The endpoint descriptions explicitly cover Taobao and Tmall. Search includes a documented tmall boolean for Tmall-only filtering, while detail, Q&A, reviews, and shop lists operate on the relevant item or shop identifiers.

Do I need a Taobao developer key?

The SandBase pages authenticate these routes with a SandBase bearer key and do not ask for a separate Taobao developer key.

Which review order should I use?

Use feedbackdate when recency is the declared sampling goal; use general for the endpoint’s default/general ordering. Record the choice because changing it changes the evidence set.

No. A ranked search response is not a complete transaction dataset. It can support discovery and a bounded catalog comparison, but not defensible market-share estimation.

Bottom line

The five Taobao endpoints provide the pieces for serious product research: controllable discovery, item-level detail, shop catalogs, pre-purchase questions, and post-purchase reviews. Their value appears when those pieces are joined by ID and observation time, not when every raw field is poured into a prompt.

Treat search, detail, Q&A, and reviews as separate evidence types. Normalize each one, retain its run ID and request, and make sample limits visible. That gives a shopping or merchandising agent enough context to assist without pretending incomplete public marketplace data is ground truth.