Back to blog
TutorialOctober 11, 20265 min read

Taobao and Tmall Data API Tutorial: Product Search, Details and Reviews

Search Taobao and Tmall products, retrieve details and collect reviews with Just One API. Includes price filters, review pagination and a Python example.

Connect product discovery with customer feedback

Product research on Taobao and Tmall often starts with two questions: which products fit a category and price range, and what do buyers say about them? Searching first, then retrieving details and reviews, gives you a sample for studying specifications, usage experiences, and common customer concerns.

Just One API connects these steps with one API token. This tutorial searches for “保温杯” (insulated cups) in the CNY 30–100 range, selects up to 3 products, and saves their details and up to 2 review pages each.

The keyword and price range are integration examples, not product recommendations. The returned sample should not be treated as complete market sales data or a representative survey of all customers.

Register and test a product search

Create a Just One API account, get your API token, and enter a keyword and filters in the Product Search V1 documentation. You can test APIs for free, use one token across platforms, and pay for actual usage afterward. Check your account for each endpoint's trial allowance.

All three GET endpoints below require the token query parameter:

  • /api/taobao/search-item-list/v1: discover products using a keyword and filters.
  • /api/taobao/get-item-detail/v6: retrieve a product by itemId.
  • /api/taobao/get-item-comment/v3: retrieve product reviews by itemId and page.

Check that the response body's business code is 0 before processing data; HTTP status alone is insufficient.

Step 1: Choose the keyword, price range and marketplace filter

Search requires keyword. This example uses “保温杯”, with startPrice=30 and endPrice=100. The price range includes both endpoints.

  • tmall=true restricts results to Tmall. false leaves the Tmall-only filter disabled.
  • sort=_sale sorts by sales.
  • sort=bid sorts by ascending price; sort=_bid sorts by descending price.
  • sort=_coefp selects general ranking.
  • Start at page=1 and keep filters consistent when fetching later pages.

The current public response example places products in data.model.itemList, with itemId identifying each product. The script deduplicates products from one search page rather than traversing every page automatically.

Step 2: Retrieve details and distinguish price and sales fields

Pass each product ID to Product Details V6. In the current public example, data.item contains the title, images, and price-related fields; data.seller contains shop information; data.delivery contains delivery information; and SKU data appears under skuBase and skuCore.

Keep displayed product prices, SKU prices, and coupon-adjusted prices distinct. V6 documents approximate sales, shipping information, and coupon-adjusted prices for some products. An absent coupon price is not zero, and an approximate sales label should not be converted into an exact transaction count.

For workflows focused on SKU quantities, review Product Details V8. Choose a version by required fields and test results rather than assuming the highest version is the best fit. Validate the response structure when switching.

For price monitoring, also retain the collection time and price type. Prices from different specifications or promotion conditions are not directly comparable measurements of a price change.

Step 3: Page through product reviews

Product Reviews V3 accepts itemId, page, and orderType. This example uses feedbackdate to sort by review date; general is also available.

In the current public example, reviews are in data.comments, their text is in content, their identifier is rateId, and data.hasNextPage indicates whether another page is available. Increment page while keeping the sort order unchanged.

For feedback analysis, deduplicate by product ID and review ID, then classify themes such as insulation, lid sealing, capacity, and delivery. Distinguish follow-up reviews, seller replies, and SKU descriptions rather than merging them into a buyer's original review text.

Python example: Save a product-and-review sample

Install the dependency and set your token in a macOS or Linux terminal. your_token is a placeholder; keep real tokens out of public code and logs.

bash
python3 -m pip install requests
export JUSTONEAPI_TOKEN='your_token'

Save the code as taobao_sample.py and run python3 taobao_sample.py. It makes up to 10 requests: 1 search, up to 3 detail requests, and up to 2 review pages per product. These are sample limits, not API quotas.

python
import json
import os
from datetime import datetime, timezone
from pathlib import Path

import requests

BASE_URL = "https://api.justoneapi.com"
TOKEN = os.environ.get("JUSTONEAPI_TOKEN", "")


def call_api(path, method="GET", accepted_codes=(0,), **params):
    if not TOKEN or TOKEN == "your_token":
        raise RuntimeError("Set JUSTONEAPI_TOKEN before running")
    values = {"token": TOKEN, **params}
    arguments = {"data": values} if method == "POST" else {"params": values}
    try:
        response = requests.request(
            method, BASE_URL + path, timeout=120, **arguments,
        )
    except requests.RequestException:
        raise RuntimeError("Network error or timeout") from None
    if response.status_code != 200:
        raise RuntimeError(f"HTTP {response.status_code}")
    try:
        result = response.json()
    except ValueError:
        raise RuntimeError("Response is not valid JSON") from None
    if not isinstance(result, dict) or result.get("code") not in accepted_codes:
        code = result.get("code") if isinstance(result, dict) else None
        raise RuntimeError(f"API failed: code={code}; check the docs")
    return result


def output_dir(prefix):
    stamp = datetime.now(timezone.utc).strftime("%Y%m%dT%H%M%S%fZ")
    folder = Path(prefix) / stamp
    folder.mkdir(parents=True, exist_ok=False)
    return folder


def save_json(folder, filename, value):
    (folder / filename).write_text(
        json.dumps(value, ensure_ascii=False, indent=2), encoding="utf-8",
    )


KEYWORD = "保温杯"
MAX_PRODUCTS = 3
MAX_REVIEW_PAGES = 2


def main():
    folder = output_dir("taobao-output")
    search = call_api(
        "/api/taobao/search-item-list/v1",
        keyword=KEYWORD, page=1, sort="_sale", tmall="false",
        startPrice="30", endPrice="100",
    )
    save_json(folder, "search-1.json", search)
    items = (search["data"].get("model") or {}).get("itemList") or []
    item_ids = list(dict.fromkeys(
        str(item["itemId"]) for item in items if item.get("itemId")
    ))[:MAX_PRODUCTS]
    save_json(folder, "selected-item-ids.json", item_ids)

    for index, item_id in enumerate(item_ids, start=1):
        detail = call_api("/api/taobao/get-item-detail/v6", itemId=item_id)
        save_json(folder, f"item-{index}-detail.json", detail)
        for page in range(1, MAX_REVIEW_PAGES + 1):
            reviews = call_api(
                "/api/taobao/get-item-comment/v3",
                itemId=item_id, orderType="feedbackdate", page=page,
            )
            save_json(folder, f"item-{index}-reviews-{page}.json", reviews)
            if reviews["data"].get("hasNextPage") not in (True, 1, "1"):
                break
    print(f"Saved {len(item_ids)} product samples to {folder}")


if __name__ == "__main__":
    try:
        main()
    except RuntimeError as error:
        raise SystemExit(str(error)) from None

Each run writes a separate directory under taobao-output, preserving the raw search response, selected product IDs, details, and reviews. Parsing follows the current public documentation examples; actual content depends on runtime responses. Confirm the fields meet your needs before adding CSV export or database writes.

The script stops on errors and retains successfully saved files. It does not retry automatically, and rerunning it makes new requests. For larger jobs, follow the retry guide to add checkpoints and bounded retries.

Common questions

Can I skip search if I already have a product ID?

Yes. Call details and reviews directly. Search discovers products; skipping it for known products reduces request count.

Can I retrieve products from a particular shop?

Start with the Shop Product List documentation and supply the required seller identifier. Keyword search, shop listings, and product details use different identifiers; do not substitute a shopId for an itemId.

Why might search and detail prices differ?

Request timing, product variations, promotions, and discount definitions can affect the values. Identify the price type and retain its original value before concluding that a product's price changed or that a response is wrong.

Will every review page have the same number of entries?

Not necessarily. Follow the returned list and pagination signal instead of hardcoding a page size. This example also stops after 2 pages, so its output is not a product's complete review history.

Start with a real product research question

Test your own keyword and price range for free in the Product Search documentation, then inspect details and reviews for a few products. Once you understand the price fields, review structure, and collection coverage, expand the workflow into ongoing monitoring or larger research jobs.

Continue with Just One API

Log in to the Dashboard for your token, read the full API docs, or open the MCP GitHub project for the latest configuration.