TikTok Shop Reviews Scraper & Change Monitor (US) avatar

TikTok Shop Reviews Scraper & Change Monitor (US)

Pricing

from $3.00 / 1,000 review results

Go to Apify Store
TikTok Shop Reviews Scraper & Change Monitor (US)

TikTok Shop Reviews Scraper & Change Monitor (US)

Monitor TikTok Shop US review changes. Pass a previous run ID to receive only newly observed or edited reviews, with the fields that changed. Unchanged reviews have no result charge. First run collects a baseline. One product, up to 99 recent reviews per run.

Pricing

from $3.00 / 1,000 review results

Rating

0.0

(0)

Developer

jy-labs

jy-labs

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

0

Monthly active users

3 days ago

Last modified

Share

See what changed in your TikTok Shop US reviews. Pass a previous successful run's ID to receive only newly observed or edited reviews, with the fields that changed. Use the results to spot rating changes, follow buyer feedback, or feed your own alerts without writing review-comparison logic.

Your first run collects a baseline. Later comparisons omit unchanged reviews and charge only for the review rows delivered. Start and platform usage charges still apply, including when nothing changed.

No login, no cookies, no proxy setup, no TikTok account of any kind.

Unofficial. Not affiliated with, endorsed by, or operated by TikTok.

See the difference in three runs

Illustrative example for one product with a 30-review window. These numbers explain the workflow; they are not a live result or a promise of how many reviews will change.

RunWhat you provideWhat you receiveReview result charge
First collectionProduct URL; leave previous run ID blank30 reviews, marked baseline$0.090
Next comparisonSame product and limit, plus the first run ID2 newly observed reviews + 1 edited review; 27 unchanged reviews omitted$0.009
Next comparison, nothing changedSame settings, plus the second run ID0 rows; summary status noChanges$0.000

The table excludes start and platform usage charges. An edited review is labelled edited_observed; if its rating changed, changedFields contains ["rating"]. This identifies the changed field, not the previous rating value.

Monitoring scope: one US product and up to 99 recent reviews per run. "Newly observed" means absent from the previous checked window, not necessarily newly written. Deletions and edits outside that window are not detected. To keep monitoring, pass each successful run's ID into the next run; a schedule alone does not update it.

Who uses this

  • Brand monitoring — catch new reviews on your own listing the day they land, with star rating and verified-purchase status. You see the newest maxReviews reviews, so if more than that many arrive between two runs, the oldest of them fall outside the window.
  • Competitor tracking — follow a rival product's feedback over weeks and read the drift, not the backlog.
  • Review-drop alerts — schedule a daily run and fire a webhook only when the dataset is non-empty.
  • Dropshipping product research — check what buyers actually say before you commit inventory.
  • Sentiment datasets — build a dated corpus of review text and ratings for classification or model evaluation.
  • Agency reporting — pipe a per-product review feed into a client dashboard without maintaining a scraper of your own.

Quick start

  1. Paste a product URL into TikTok Shop US product URL, for example https://shop.tiktok.com/us/pdp/catnip-chew-toy/1731791261654290596.
  2. Set Recent reviews to check (1-99). The default is 30. Leave Track changes - previous run ID (optional) blank for the first collection.
  3. Click Save & Run, then open the Dataset tab.

That first run is your baseline: seeing baseline rows is expected. To activate change monitoring, open that successful run, copy its run ID, and paste it into Track changes - previous run ID (optional) next time:

{
"productUrl": "https://shop.tiktok.com/us/pdp/catnip-chew-toy/1731791261654290596",
"maxReviews": 30,
"previousRunId": "PASTE_PREVIOUS_RUN_ID"
}

On that comparison run, the scraper delivers only newly observed or edited reviews. Open Review changes in the dataset and check Change type and Changed fields. Keep the same product and the same maxReviews, or the comparison is rejected rather than silently reset. The guard matches on product ID, so a differently written URL for the same product is fine.

An empty result can be the expected answer. Open Change summary - including no changes and check for status: "noChanges" with comparison.mode: "comparison". This means the checked window has no tracked changes; an empty dataset by itself is not enough to tell. For the next comparison, use this successful run's ID even when it returned zero rows. See Scheduled runs and webhooks to connect this loop to your own alerts.

Sample TikTok Shop reviews output

One row per review. This is a real row from a run on the catnip chew toy above:

{
"deliveryId": "1777d8c9abfa6f306225e69893a1cc9157383434dd8a6862bc603f5061a0cb0a",
"sourceUrl": "https://shop.tiktok.com/us/pdp/catnip-chew-toy/1731791261654290596",
"productId": "1731791261654290596",
"productTitle": "Potaroma Interactive Catnip Chew Toy with Organic Sisal for Indoor Cats - TikTok Shop",
"productTotalReviews": 3467,
"productOverallRating": 4.6,
"observedAt": "2026-09-08T08:34:21.599Z",
"reviewId": "7682830511550514957",
"text": "My Willow loves this",
"rating": 5,
"reviewedAt": "2026-09-07T16:26:18.000Z",
"isVerifiedPurchase": true,
"reviewCountry": "US",
"changeType": "baseline",
"changedFields": [],
"firstSeenAt": "2026-09-08T08:34:21.599Z",
"lastSeenAt": "2026-09-08T08:34:21.599Z",
"requestedSort": "newest",
"observedDescendingOrder": true,
"fullReviewCoverage": false,
"newestVerified": false,
"browserQaPerformed": false
}

Fields

FieldExampleWhat it means
reviewId7682830511550514957Stable TikTok review ID. Use it as your primary key.
textMy Willow loves thisThe review body. Empty when the buyer left stars only.
rating5Star rating, 1 to 5.
reviewedAt2026-09-07T16:26:18.000ZWhen the review was written, in UTC.
isVerifiedPurchasetrueTikTok's verified-purchase flag.
reviewCountryUSTwo-letter country shown on the review.
productTitlePotaroma Interactive Catnip Chew Toy…Product name as served on the page. null when no name was served.
productTotalReviews3467The product's total review count, not how many you received. null when the source served no total.
productOverallRating4.6The product's star average. null when the source served no rating.
changeTypebaselineWhy this row was delivered. See below.
changedFields["rating"]On an edited review, which of text, rating, date, verified flag, or country changed.
firstSeenAt / lastSeenAt2026-09-08T08:34:21.599ZWhen your run chain first and last saw this review.
observedAt2026-09-08T08:34:21.599ZWhen this run started.
sourceUrl, productId, deliveryIdThe URL you asked for, TikTok's product ID, and a per-row delivery fingerprint.
requestedSortnewestAlways newest. Records what was asked of TikTok, not proof of what arrived.
observedDescendingOrdertrueWhether dates really came back newest-first. null when fewer than two reviews were selected. false only reaches you with allowSourceOrderWarnings on, because the default stops the run with sourceOrderMismatch instead.
fullReviewCoveragefalseAlways false. A bounded window of recent reviews, never a complete archive.
newestVerifiedfalseAlways false. Nothing proves these are globally the newest reviews.
browserQaPerformedfalseAlways false. Pages load in a real browser, but nothing checks them visually.

The last three are false in every run, by design, so no downstream system mistakes a recent-reviews window for a full review history. Three more fields appear only in special cases: sourceOrderWarning, productAvailability, and productTitleSource, all described below.

What changeType tells you

ValueIn plain words
baselineYour first run for this product. Everything the scraper saw is delivered, so you have something to compare against.
newly_observedNew since your previous run. This review was not in the previous window.
edited_observedEdited since your previous run. The review existed before, and its text, rating, date, verified flag, or country changed. changedFields names which.

Reviewer names, user IDs, and profile pictures are never collected.

Change monitoring

Run once with no previous run ID. Every review comes back as baseline. Keep that run's ID.

Pass it as previousRunId next time and you get only newly_observed and edited_observed rows. Unchanged reviews are neither delivered nor charged, and a run where nothing changed succeeds with zero rows, reported as noChanges in the run's OUTPUT record.

Chain runs by always passing the previous run's ID forward, and keep maxReviews fixed across the chain. Changing the product, the limit, or the account starts a different comparison, and the mismatched prior snapshot is rejected rather than silently accepted.

Pricing

This scraper uses pay-per-event pricing:

  • $0.003 per review row delivered. Baseline, new, and edited rows all count. Zero rows, zero review charges.
  • $0.00005 per Actor start, per GB. Runs use 2 GB for the browser, so a start costs $0.0001.
  • Apify platform usage, compute plus US residential proxy traffic, is metered by Apify and billed to your account on top: roughly $0.02 per run. Apify covers that usage for Free-plan accounts, so the platform column below applies to paid plans.
RunResult chargesStart chargePlatform usageTotal
30 reviews (default)$0.090$0.0001≈ $0.02$0.11
99 reviews (maximum)$0.297$0.0001≈ $0.02$0.32
Nothing changed, or no reviews (0 rows)$0.00$0.0001≈ $0.02$0.02

An empty run costs you only the start fee plus platform usage. That is what makes daily monitoring cheap: most days nothing changed, so most days you pay about two cents. A failed run also charges the start event and the platform usage it consumed, but never review rows.

Integrations

Apify API. Two HTTP calls: start the run, then read the dataset. Keep the token in a header, not the URL.

curl --fail-with-body --request POST \
--header "Authorization: Bearer $APIFY_TOKEN" \
--header "Content-Type: application/json" \
--data '{"productUrl":"https://shop.tiktok.com/us/pdp/catnip-chew-toy/1731791261654290596","maxReviews":30}' \
"https://api.apify.com/v2/acts/jy-labs~tiktok-shop-us-reviews/runs?build=latest"
curl --fail-with-body --header "Authorization: Bearer $APIFY_TOKEN" \
"https://api.apify.com/v2/datasets/$DATASET_ID/items?format=json&clean=true"

Scheduled runs and webhooks. Schedule this scraper daily at, say, 07:00 UTC and attach a webhook on ACTOR.RUN.SUCCEEDED. Your endpoint reads the dataset, posts to Slack only when it is non-empty, and stores the finished run ID as the next previousRunId. That ID is the only state a monitoring loop keeps.

n8n. HTTP Request node to start the run, a poll loop until it is terminal, then read OUTPUT from the run's key-value store. Continue only when OUTPUT.status is completed or noChanges: route dataset rows for completed, and for noChanges skip processing but still advance the saved run ID.

Make. The same state machine with HTTP modules: start, poll, read OUTPUT, branch on status, iterate rows. Store the run ID only after the status check, so a failed run never becomes your baseline.

Zapier. Use the native Apify integration to trigger on a finished run and push review rows into Airtable, Notion, or an email digest. A zero-row run produces no items, which is the "nothing to report" signal.

Google Sheets. Export from the Dataset tab, or append rows through the Sheets API on a schedule. Write with valueInputOption=RAW and import ID columns as plain text, or long IDs get rounded into nonsense.

Python and JavaScript clients. Both official Apify clients drive this scraper in a few lines.

from apify_client import ApifyClient
client = ApifyClient("APIFY_TOKEN")
run = client.actor("jy-labs/tiktok-shop-us-reviews").call(run_input={
"productUrl": "https://shop.tiktok.com/us/pdp/catnip-chew-toy/1731791261654290596",
"maxReviews": 30,
})
for review in client.dataset(run["defaultDatasetId"]).iterate_items():
print(review["rating"], review["changeType"], review["text"])
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'APIFY_TOKEN' });
const run = await client.actor('jy-labs/tiktok-shop-us-reviews').call({
productUrl: 'https://shop.tiktok.com/us/pdp/catnip-chew-toy/1731791261654290596',
maxReviews: 30,
previousRunId: 'PASTE_PREVIOUS_RUN_ID',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();

Inputs

InputRequiredWhat it does
productUrlYesThe TikTok Shop US product page URL, like https://shop.tiktok.com/us/pdp/catnip-chew-toy/1731791261654290596. Plain product link, no query string.
maxReviewsNoHow many of the newest reviews to collect, 1 to 99. Default 30.
previousRunIdNoID of an earlier successful run of this Actor. When set, you get only reviews that are new or edited since that run. Same product and same maxReviews.
allowSourceOrderWarningsNoDefault false. By default the run stops if TikTok returns a review out of date order, because the newest-first promise was broken. Turn it on to receive those reviews anyway, flagged with sourceOrderWarning: true.

What can go wrong

CodeWhat happenedWhat to do
blockedTikTok showed a security challenge for this product instead of the pageTry again later. Some products are challenged far more often than others.
apiStatusTikTok's reviews endpoint refused the requestTry again later.
timeout / transportA slow or dropped connection through the proxyTry again. The scraper already retries this on its own.
wrongCountryThe proxy exit was not in the United StatesTry again; a new run gets new connections.
deadlineExceededThe run ran out of its time budgetLower maxReviews and try again.
budgetExhaustedYour run charge limit cannot cover the rows foundRaise the run's charge limit and start a new run.
browserHostUnavailableNo TikTok Shop page the run tried could load the reviews: every candidate was challenged, region-blocked, or unreachableRetry later; contact support if it persists.
browserSdkMissingA page loaded but never finished setting itself up, so the reviews request could not be madeRetry later; contact support if it persists.
browserLaunchFailedThe browser itself could not start for this runRetry later; contact support if it persists.
unsafeResumeSomething tried to restart a run that already produced outputDo not resurrect it. Start a fresh run.

Every run writes a RUN_DIAGNOSTICS record naming the failing stage, a stable code, and what to do next. Send the run ID and the code to support, never proxy credentials or cookies.

Special cases

Products with no reviews. The run succeeds with zero rows and reports the product's rating and total. That is a real answer, not an error.

Star-only reviews. Many buyers leave a rating and write nothing. Those rows have an empty text and are roughly half of a typical product's output. Real data, not a parsing failure.

Region-blocked products. Some products refuse to display in some regions. The scraper still delivers their reviews, read for that product ID from another TikTok Shop page. Because the product page served no name or totals, those rows carry productAvailability: "regionBlocked" and productTitleSource: "slug": the title comes from the URL, and the total and star average from the reviews envelope. Treat that title as approximate, and expect productTotalReviews and productOverallRating to be null when that envelope carries no rating summary.

Out-of-order reviews. With allowSourceOrderWarnings on, rows whose source date broke the newest-first order carry sourceOrderWarning: true and the run summary counts them.

Limits

  • US depth, not global breadth. One product per run, US market only, up to 99 of the newest reviews. In exchange: the US verified-purchase flag, review country codes, and reviews even for products region-blocked from your own location.
  • A recent window, not an archive. No paging back through a product's full history, and no guarantee this is globally the newest set. fullReviewCoverage and newestVerified say so on every row.
  • No reviewer identity, by design: no names, user IDs, or avatars.
  • Deletions are not detected. A review missing from a later run is not reported as removed.
  • The source can change without notice. TikTok changed how review requests are signed on September 8, 2026, and this scraper was rebuilt around a real browser in response. Expect it to happen again.
  • Compliance is yours. Not affiliated with TikTok. TikTok's US Terms of Service require prior written approval for automated extraction, and as of September 9, 2026 that approval had not been established for this project. You remain responsible for your own compliance with applicable terms, rights, privacy obligations, and laws.

FAQ

What does one run cost?

$0.003 per delivered review row, plus $0.0001 for the start at the default 2 GB. A 30-review run is about $0.09 in result charges, a full 99-review run about $0.30, with roughly $0.02 of platform usage on top.

What does an empty run cost?

The start event plus platform usage, about $0.02. No rows means no result charges, which is the economic case for scheduling it daily.

How does change monitoring work?

Run once with no previous run ID to get a baseline. Next run, pass that run's ID: the scraper compares the two windows and returns only new or edited reviews, each labelled with which. Unchanged reviews are neither delivered nor charged.

Is it legal to scrape TikTok Shop reviews?

Review text and ratings are public content, which is not the whole question. TikTok's US Terms of Service require prior written approval for automated extraction, and this project does not have it. Decide for your own jurisdiction and use case, and take legal advice if it matters commercially.

Does TikTok Shop have a public reviews API?

No. There is no open endpoint that serves product reviews to a third party, which is why this scraper reads the storefront in a real browser.

Do I need cookies or a login?

No. No TikTok account, no cookies, no session export, no proxy configuration. Paste a product URL and run it.

What happens on a product with no reviews?

The run completes with zero rows and reports the product's rating and review total. Zero rows on a product that demonstrably has reviews is treated as a failure, not an empty answer.

Why do many rows have empty text?

Because plenty of buyers tap five stars and write nothing. Roughly half the rows on a typical product are rating-only, and their rating, date, and verified-purchase flag are still there.

Can I scrape several products in one run?

No, one product per run. Start one run per product, in parallel if you like, keeping a separate previousRunId chain for each.

How far back can it go?

Up to 99 of the newest reviews per run. It is a recent-reviews window, with no deep pagination into a product's full history.

Can it read products that are blocked in my region?

Yes. When the product page itself is not served, the reviews are still collected and delivered. The title on those rows comes from the URL and is marked as such, so treat it as approximate.

What about products behind a CAPTCHA?

The run fails rather than returning partial data, and no result charges are made. A challenge is a refusal aimed at that session, not a fact about the product, so retrying later often succeeds.

What happens if TikTok changes its site?

Extraction can break, and it has. TikTok changed its request signing on September 8, 2026; the scraper moved into a real browser, keeping its fields, comparison semantics, and billing rules identical. When a change does break a run you get a diagnostic code, not silent bad data.

Do I get the reviewer's name?

No, deliberately. No names, user IDs, or profile pictures are collected, so the output carries review content without personal identifiers.

Independent verification record

On September 8, 2026, output was compared field by field against a US browser session on a Los Angeles exit, across seven products. 39 reviews matched by reviewId with zero field mismatches, and product title, total, and star average matched exactly on every compared product. One product the browser session could not open returned no rows. That check ran against the earlier collection path; on September 9, 2026 the reviews stage moved into a real browser and region-blocked products began returning rows, while the delivered fields, comparison semantics, and billing rules stayed the same.

This is a dated one-off check against one exit location. It is not continuous monitoring, complete coverage, or an ongoing reliability claim.