Back to Blog

Monitor TikTok Shop Ratings and Review Count Changes

Emily Chen
Emily Chen

Advanced Data Extraction Specialist

04-Sep-2026

TL;DR:

  • TikTok Shop rating monitoring needs timestamped product snapshots. A current rating alone cannot show when a change happened.
  • Rating and review count should be read together. A rating shift with no observed review-count growth needs a different review path from a shift after many new reviews.
  • Missing collection data is not an unchanged rating. Store collection status separately from product values.
  • An anomaly flag is a review queue. It does not prove a product-quality incident or identify the cause of a change.
  • The Shop actor returns aggregate rating fields, not review text. This workflow cannot perform review sentiment analysis.
  • Free to start. New Scrapeless accounts include free credit through the Scrapeless Dashboard.

Introduction: a rating becomes useful when it has history

TikTok Shop product pages expose an aggregate rating and review count at the time of collection. One snapshot describes the current page; a series of snapshots can reveal when the displayed reputation changed.

This tutorial builds TikTok Shop rating monitoring for a fixed product watchlist. It collects public rating and review_count fields, stores valid observations in SQLite, compares each product with its prior snapshot, and sends unusual changes to manual review. The workflow tracks aggregate product reputation without claiming access to review text or sentiment.

The competitive pricing pipeline guide shows how a known product watchlist supports repeatable comparisons.

Pipeline at a Glance

Stage Action Output
Watch Maintain product ID and region pairs Product watchlist
Collect Request each public product page Raw Shop snapshot
Normalize Parse rating and review count Valid observation row
Compare Join each row to its prior observation Rating-change events
Review Flag unusual changes and inspect the page Analyst review queue

This pipeline monitors values displayed in public product snapshots. It does not provide review bodies, reviewer profiles, or seller-side diagnostics.

Prerequisites

  • A Scrapeless account and API key from the Scrapeless Dashboard
  • A watchlist of known public TikTok Shop product IDs and regions
  • A collection schedule and retention policy
  • Rating-change and review-count thresholds chosen before alerting
  • SCRAPELESS_API_KEY, TIKTOK_SHOP_PRODUCT_ID, and TIKTOK_SHOP_REGION for the collection example

The collection block is a prerequisite gap because the credential and product watchlist come from the reader. The example follows the supplied Shop response shape and does not show fabricated API output.

Stage 1: Fix the Product and Region Key

Call scraper.tiktok.shop.page with a known product_id and region. Store both requested values and the returned product context. A comparison key should contain product ID and region because ratings may be observed on different market surfaces.

Do not use a product title as the primary key. Titles can change, while the string product ID is the durable reference supplied to the actor. Keep IDs as text so database conversion never changes a long identifier.

Every collection attempt also needs a run record with start time, completion status, and error detail. A failed request should create a collection-status row without copying the previous rating forward.

Stage 2: Parse Rating and Review Count Conservatively

The Shop response can return rating as a number and review_count as a string. Parse the rating as a decimal value and the review count as a nonnegative integer. Python's decimal documentation explains the exact decimal representation used for rating comparisons.

Apply these rules before inserting a valid observation:

Field Valid rule Invalid handling
rating Numeric and within the accepted product-scale range Store raw payload; mark value invalid
review_count Integer greater than or equal to zero Store raw payload; mark value invalid
product_id Nonempty string Mark collection invalid
region Nonempty normalized string Mark collection invalid

Do not convert a missing rating to zero. Zero is a value; missing is an absence of evidence.

Start Scraping with Scrapeless

Power up your web scraping and automation workflow with Scrapeless!
Sign up today and get $5 in free creditno credit card required.

Claim your free credit now in the Scrapeless Dashboard.

Stage 3: Store Product Reputation Snapshots

The database keeps collection attempts separate from valid rating observations. SQLite's CREATE TABLE documentation defines the constraints used in the example.

Note: The code below requires live SCRAPELESS_API_KEY, TIKTOK_SHOP_PRODUCT_ID, and TIKTOK_SHOP_REGION values supplied by the reader.

python Copy
import json
import os
import sqlite3
import uuid
from datetime import datetime, timezone
from decimal import Decimal, InvalidOperation
from urllib.request import Request, urlopen

ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"


def utc_now():
    return datetime.now(timezone.utc).isoformat()


def fetch_product(product_id, region):
    body = json.dumps({
        "actor": "scraper.tiktok.shop.page",
        "input": {"product_id": str(product_id), "region": region},
    }).encode()
    request = Request(
        ENDPOINT,
        data=body,
        headers={
            "content-type": "application/json",
            "x-api-token": os.environ["SCRAPELESS_API_KEY"],
        },
        method="POST",
    )
    with urlopen(request, timeout=60) as response:
        return json.load(response)


def parse_rating(value):
    try:
        rating = Decimal(str(value))
    except (InvalidOperation, TypeError, ValueError):
        return None
    return rating if Decimal("0") <= rating <= Decimal("5") else None


def parse_review_count(value):
    try:
        parsed = int(value)
    except (TypeError, ValueError):
        return None
    return parsed if parsed >= 0 else None


database = sqlite3.connect("tiktok-shop-ratings.sqlite3")
database.executescript("""
CREATE TABLE IF NOT EXISTS collection_runs (
    run_id TEXT PRIMARY KEY,
    collected_at TEXT NOT NULL,
    requested_product_id TEXT NOT NULL,
    requested_region TEXT NOT NULL,
    status TEXT NOT NULL,
    detail TEXT
);
CREATE TABLE IF NOT EXISTS rating_snapshots (
    run_id TEXT PRIMARY KEY,
    collected_at TEXT NOT NULL,
    product_id TEXT NOT NULL,
    region TEXT NOT NULL,
    rating TEXT NOT NULL,
    review_count INTEGER NOT NULL,
    raw_json TEXT NOT NULL
);
""")

run_id = str(uuid.uuid4())
collected_at = utc_now()
product_id = os.environ["TIKTOK_SHOP_PRODUCT_ID"]
region = os.environ["TIKTOK_SHOP_REGION"]

try:
    raw = fetch_product(product_id, region)
    rating = parse_rating(raw.get("rating"))
    review_count = parse_review_count(raw.get("review_count"))
    returned_product_id = str(raw.get("product_id") or product_id)
    returned_region = str(raw.get("region") or region).casefold()

    if rating is None or review_count is None:
        raise ValueError("rating or review_count is missing or invalid")

    database.execute(
        "INSERT INTO rating_snapshots VALUES (?, ?, ?, ?, ?, ?, ?)",
        (
            run_id, collected_at, returned_product_id, returned_region,
            str(rating), review_count, json.dumps(raw, ensure_ascii=False),
        ),
    )
    status, detail = "success", None
except Exception as error:
    status, detail = "failed", f"{type(error).__name__}: {error}"

database.execute(
    "INSERT INTO collection_runs VALUES (?, ?, ?, ?, ?, ?)",
    (run_id, collected_at, product_id, region, status, detail),
)
database.commit()
database.close()

The exception record preserves uncertainty without inserting a false rating observation. The watch process can surface failed runs in its quality queue.

Stage 4: Compare Each Product with Its Prior Valid Snapshot

SQLite window functions can pair each valid row with its prior observation for the same product and region. The window-function documentation defines LAG(), which is suitable for this comparison.

sql Copy
-- Illustrative query over the schema created above.
WITH ordered AS (
  SELECT
    collected_at,
    product_id,
    region,
    CAST(rating AS REAL) AS rating,
    review_count,
    LAG(CAST(rating AS REAL)) OVER (
      PARTITION BY product_id, region ORDER BY collected_at
    ) AS prior_rating,
    LAG(review_count) OVER (
      PARTITION BY product_id, region ORDER BY collected_at
    ) AS prior_review_count
  FROM rating_snapshots
)
SELECT
  *,
  rating - prior_rating AS rating_delta,
  review_count - prior_review_count AS review_count_delta
FROM ordered
WHERE prior_rating IS NOT NULL;

Calculate deltas only between valid observations. If one scheduled run failed, keep that gap visible rather than claiming the rating stayed unchanged during the missing interval.

Stage 5: Send Unusual Changes to Manual Review

An alert rule can combine absolute rating change, review-count growth, and collection quality. Choose thresholds from the team's product portfolio before reviewing results, then version those rules.

The rating-monitoring table should include:

Product Region Prior rating Current rating Rating delta New reviews observed Status
Watchlist item Market key Prior valid value Current valid value Difference Review-count delta normal or review

Open the public product page during review and check whether the product identity, region, or displayed values changed. Treat the alert as a prompt for inspection. A rating movement cannot prove a quality problem, campaign effect, listing change, or review event from aggregate fields alone.

Scrapeless provides the Shop actor through Scraping API. Check the current pricing page before setting watchlist size and collection frequency.

Interpret Rating Changes Responsibly

Collect only public product fields needed for the monitoring purpose, limit raw-payload access, and define a retention period. The NIST Privacy Framework offers general controls for data minimization and governance.

Do not label aggregate rating changes as sentiment. The actor response used here does not include review text, so a TikTok Shop rating tracker can measure displayed rating and review-count changes without explaining why they occurred.

Conclusion: preserve the difference between change and cause

TikTok Shop rating monitoring works when every comparison uses valid, timestamped product and region snapshots. Track rating beside review count, keep failed collections separate, and send unusual deltas to a human review queue. The output shows that the public listing changed; it does not establish the cause.

Ready to Monitor TikTok Shop Ratings?

Join the Scrapeless Discord or Telegram community to discuss reputation-snapshot schemas. Create an account in the Scrapeless Dashboard when the product watchlist is ready.

FAQ

Q: How can a team track TikTok Shop product ratings?

A team can track TikTok Shop product ratings by collecting timestamped rating and review-count snapshots for fixed product and region keys.

Q: Does the Shop actor return individual review text?

The Shop response used in this workflow returns aggregate rating and review count without individual review text.

Q: Can rating monitoring perform sentiment analysis?

Rating monitoring cannot perform review sentiment analysis without review text or another verified sentiment-bearing field.

Q: What does a rating-drop alert prove?

A rating-drop alert proves only that two valid public snapshots contain different aggregate values; it does not prove the cause of the change.

Q: Should a failed collection copy the last rating forward?

A failed collection should remain a quality gap because copying the prior value would turn missing evidence into an unchanged observation.

Q: Do teams need to manage TikTok Shop selectors?

The Shop actor returns structured product fields through the API. The caller manages the product watchlist, schedule, storage, anomaly rules, and manual review.

Q: Is scraping public TikTok Shop product data legal?

Legality depends on jurisdiction, market, purpose, access method, applicable terms, and the collected fields. Use public data for a permitted purpose and seek legal advice for the intended workflow.

At Scrapeless, we only access publicly available data while strictly complying with applicable laws, regulations, and website privacy policies. The content in this blog is for demonstration purposes only and does not involve any illegal or infringing activities. We make no guarantees and disclaim all liability for the use of information from this blog or third-party links. Before engaging in any scraping activities, consult your legal advisor and review the target website's terms of service or obtain the necessary permissions.

Most Popular Articles

Catalogue