For AI

How-to guides

How to collect TikTok Shop product reviews by keyword

Three endpoints, in this order: TikTok Shop product search, product detail, then product reviews page by page. The worked example below is 10 calls and costs $0.022; a failed call is not charged.

Updated

The job: you are about to sell, source or compare a product on TikTok Shop and want to know what buyers say about the listings already there. Star averages hide the useful part. The review text tells you which size runs small, which strap breaks in a week and what people were pleasantly surprised by. Here you search the shop by keyword, read the details of the listings that have the most reviews, and page through their reviews. You end with two CSVs: the products (price, units sold, rating, shop) and the reviews (stars, text, variant bought, photos, verified purchase).

TikTok's own Shop API is for sellers reading their own shop, so it does not help with other listings; TikTok Shop product data without a seller account explains the difference. These endpoints read the public listings buyers see, with an API key and no TikTok account.

Step by step

All three endpoints take a country parameter: the shop's market as an ISO country code. It defaults to US, which is also the market with the most complete data. Other markets work with their own code, with thinner coverage, so try one call first. Use the same country for all three calls, and read currency before comparing prices across markets.

Step 1: search products

TikTok Shop product search takes query and country. One call returns about 20 products for $0.004. Each has id, url, title, price, original_price, currency, sold, rating, reviews (how many reviews it has), one image and shop (ID and name). reviews is how you pick listings worth reading.

curl -G "https://api.okdata.online/v1/tiktok/shop/products/search" \
  -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'query=posture corrector' \
  --data-urlencode 'country=US'

Step 2: read each listing

TikTok Shop product detail takes the product id, or the product page link as url (for example https://www.tiktok.com/shop/pdp/1731859027465331722), plus country. For $0.002 it returns the current price and discount, units sold, rating, review count and every image. With view=full, ext adds shop_rating, shop_followers and the listing's specifications, where details such as material and size are listed.

curl -G "https://api.okdata.online/v1/tiktok/shop/products/get" \
  -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'id=1731859027465331722' \
  --data-urlencode 'country=US' \
  --data-urlencode 'view=full'

Step 3: page through the reviews

TikTok Shop product reviews takes the product id (required) and country. One call returns about 20 reviews for $0.002. Each has rating (1 to 5 stars), text, variant (the size or colour bought), images (buyer photos), verified_purchase, published_at and author_name, which the shop usually shows masked. For the next page, send page.next_cursor back as cursor; stop when page.has_more is false.

curl -G "https://api.okdata.online/v1/tiktok/shop/products/reviews/list" \
  -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'id=1731859027465331722' \
  --data-urlencode 'country=US'

Step 4: put it together in Python

The script runs the three steps for one keyword and writes shop_products.csv and shop_reviews.csv. REVIEW_PAGES caps the review pages per product, and with it the bill.

import csv
import os
import requests

API = "https://api.okdata.online"
HEADERS = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
QUERY, COUNTRY = "posture corrector", "US"
PRODUCTS = 3       # listings to read
REVIEW_PAGES = 2   # review pages per listing; each page is one call


def get(path, **params):
    body = requests.get(API + path, headers=HEADERS, params={**params, "country": COUNTRY}, timeout=60).json()
    if body["code"] == "not_found":
        return None  # delisted: not charged
    if body["code"] != "ok":
        raise RuntimeError(f"{body['code']}: {body['message']} (charged: {body['charged']})")
    return body


found = get("/v1/tiktok/shop/products/search", query=QUERY)["data"]["items"]
found = sorted(found, key=lambda p: p["reviews"] or 0, reverse=True)[:PRODUCTS]

products, reviews = [], []
for p in found:
    body = get("/v1/tiktok/shop/products/get", id=p["id"], view="full")
    if not body:
        continue
    products.append(body["data"]["item"])
    cursor = None
    for _ in range(REVIEW_PAGES):
        page = get("/v1/tiktok/shop/products/reviews/list", id=p["id"], **({"cursor": cursor} if cursor else {}))
        if not page:
            break
        reviews.extend(page["data"]["items"])
        if not page["page"]["has_more"]:
            break
        cursor = page["page"]["next_cursor"]

with open("shop_products.csv", "w", newline="", encoding="utf-8-sig") as f:
    out = csv.writer(f)
    out.writerow(["product_id", "title", "price", "original_price", "currency", "sold", "rating", "reviews", "shop", "shop_rating"])
    for p in products:
        out.writerow([p["id"], p["title"], p["price"], p["original_price"], p["currency"], p["sold"],
                      p["rating"], p["reviews"], p["shop"]["name"], p["ext"].get("shop_rating")])

with open("shop_reviews.csv", "w", newline="", encoding="utf-8-sig") as f:
    out = csv.writer(f)
    out.writerow(["product_id", "review_id", "rating", "text", "variant", "photos", "verified", "published_at"])
    for r in reviews:
        out.writerow([r["product_id"], r["id"], r["rating"], r["text"], r["variant"],
                      len(r["images"] or []), r["verified_purchase"], r["published_at"]])

With the defaults that is the worked example: 10 calls and about 120 reviews. Ten listings at 5 review pages each would be $0.124 in total.

Good to know

  • Stars without words. Some buyers leave only a rating; then text is an empty string. Filter those out before you summarise text, but keep them for the star distribution.
  • No review likes. TikTok Shop shows no likes on reviews, so likes is always null and meta.unavailable says platform.
  • Order. Reviews come in the shop's own order and there is no sort parameter. A few pages are a sample, not the whole picture; the product's rating and reviews count cover all of them.
  • Units sold. sold is the number the listing displays. Compare it day to day for a rough sales trend; it is not an order count.
  • Dates. Where the shop shows only a date, published_at is that day.
  • Public data only. GMV, traffic sources and ad spend live in the seller's back office; none of it is here.
  • Delisted products. A product that is gone answers not_found, which is free, as is every other error. Send an Idempotency-Key header to make retries safe: the same request with the same key within 24 hours returns the stored result with meta.replayed: true and no new charge.

To turn the review text into product decisions, see mining competitors' reviews. For tracking prices and units sold across a category every day, see product research.

What the example costs

One search for posture corrector in the US shop, the detail of the 3 listings with the most reviews, then 2 pages of reviews (about 40) for each

EndpointCallsPriceSubtotal
TikTok Shop product search1$0.004$0.004
TikTok Shop product detail3$0.002$0.006
TikTok Shop product reviews6$0.002$0.012
Total10$0.022

Prices in force when this page was built. A failed call costs nothing.

In your AI (MCP)

Connect the MCP server once, then say what you want. The agent finds these endpoints, reads their prices and calls them on your balance.

SaySearch the US TikTok Shop for posture corrector. Take the 3 listings with the most reviews, show me price, units sold, rating and shop for each, then read about 40 reviews per listing and sum up what buyers praise and complain about.

What the agent sends to the call tool first
{
  "endpoint": "tiktok.shop.products.search",
  "params": {
    "query": "portable coffee maker"
  },
  "idempotency_key": "<a new UUID>"
}

Set up the MCP server →

Connect once, then just ask.

Every new key comes with $0.10 to try it. One sentence connects your agent.

Start free
Connect your AI

Paste this into your agent

Read https://okdata.online/agents.md and set up okdata for me; my key is in the OKDATA_API_KEY environment variable.

Claude Code, Cursor, Codex and other agents that can open a link set themselves up from it.

MCP serverhttps://api.okdata.online/mcp