# Changelog of TikTok Shop Reviews Pro ⭐️ (`deepmine/tiktok-shop-reviews-pro`) Actor

- **URL**: https://apify.com/deepmine/tiktok-shop-reviews-pro/changelog.md
- **Full Actor documentation**: https://apify.com/deepmine/tiktok-shop-reviews-pro.md

## Changelog

### 3.1 (October 2026, no cost cap on good runs)

- The run no longer caps what it spends at a small fixed amount plus a share of what its reviews earn. Residential retries for products and keywords TikTok refuses on datacenter IPs now go on for as long as the reviews they are expected to bring in pay for them, so blocked runs deliver every review they can. The only limit left is that a run never costs more than its reviews earn: it stops only when its products keep coming back with no reviews (empty, or refused on every IP).
- A product stopped before its first review because it would have cost more than the run had earned so far is tried again once more reviews have come in. A keyword TikTok refuses can get residential retries on its later passes too.
- `OUTPUT.costAllowance` also shows the price per review the run counts (`reviewPriceUsd`: your plan's price, read from the run's pricing) and the reviews the products being read are expected to deliver (`expectedReviews`).

### 3.1 (October 2026, datacenter first)

- Reviews are read through Apify's datacenter proxy first. Requests TikTok refuses there are retried on US residential IPs, as before. Saved tasks that name the residential proxy run the same way. The default memory is 256 MB.
- The run's cost allowance now also covers the run's own writes: the 🛍️ Products row of each product is paid for when the product starts, so products skipped at the allowance get no row, and the progress report is written at most every 15 seconds and only when there is room.
- If the run's cost record can't be saved within 5 seconds, or can't keep ahead of the run's spending, the run starts nothing new and finishes what it has.
- An answer whose headers pass 16 KB stops that product with the reason `response_too_large`, like an oversized body. A request that would be larger than 8 KB is never sent.
- The cost allowance also counts Apify's data transfer: every request's bytes on datacenter as well as residential, and the bytes the run writes to its datasets and `OUTPUT`. `OUTPUT.costAllowance.transferUsd` shows the request part.
- A keyword whose search TikTok refuses no longer holds up the keywords after it: they are searched and collected, and the refused keyword is searched again afterwards (on residential when the run has earned enough, otherwise once more on datacenter).

### 3.1 (October 2026, cost guard)

- A run Apify restarts stops with a clear error, instead of collecting again, when it can't open or read back the reviews it already delivered. Before, an open failure let it deliver (and charge) those reviews a second time.
- A run keeps its proxy, compute and storage spend in proportion to the reviews it delivers: a small fixed allowance, then a share of what the delivered reviews earn. Products that return few or no reviews (refused, empty or listed twice) can no longer run up a run's cost. If the allowance runs out, the remaining products are listed in `OUTPUT` under `costLimitedProducts`, keywords not searched yet are marked `skipped` in `searchSummary`, and the status line says so. `OUTPUT.costAllowance` shows the spend.
- A restarted run counts what its earlier start spent (kept in the `COST_LEDGER` record, written before anything is spent), and stops if that record can't be read.
- Every request has a size limit, so one oversized answer can't run up the proxy bill: an answer past it stops that product with the reason `response_too_large`.
- The `OUTPUT` report is updated at most every 5 seconds while the run collects, and in full at the end.
- With `maxReviewsPerProduct` under 250, review pages are the size of your limit: same reviews, in the same order, with fewer bytes per product.

### 3.1 (October 2026, later)

- Products are read through TikTok Shop's product data request instead of the product page: about a third of the bytes per product, and no "Security Check" captcha page to retry. Rows and the 🛍️ Products table carry the same fields as before.
- `OUTPUT` reports the bytes each product and the whole run used (`wireBytes`, `wireBytesPerReview`).
- A bad connection that answers the product request with an empty or non-JSON page, or a product TikTok refuses to name on four fresh IPs in a row, is retried on other sessions instead of failing the product.

### 3.1 (October 2026)

- Price cut to $2.49 / $1.99 / $1.69 / $1.29 per 1,000 reviews (Free / Starter / Scale / Business), with no start fee.
- Restart-safe: a run Apify restarts skips the reviews it already delivered, so nothing is charged twice.
- The run stops exactly at the number of reviews your maximum cost per run pays for.

### 3.1 (September 2026)

- **Full reviews again.** TikTok's review API started requiring signed requests, so earlier versions often returned only the 3 preview reviews on the product page. Version 3 signs every request the way TikTok's website does and pages through the whole review list.
- **Row counts go up.** `maxReviewsPerProduct` is now the number of reviews you actually get per product, and you pay per review. A saved task set to 50 now returns up to 50 reviews per product instead of about 3. Lower `maxReviewsPerProduct` or set `maxResults` if you want less. Leaving the field out now means 100 (it was 50).
- Newest first, without holes: with a limit you get the newest reviews in TikTok's order. If TikTok refuses an early page, the product is marked incomplete instead of skipping ahead to older reviews.
- Honest run status: a run where TikTok refused every product fails. When only some products are refused, the run succeeds with a warning, and the 🛍️ Products table marks them with the reason (`OUTPUT` lists them under `refusedProducts` and `incompleteProducts`).
- Retries per product are capped, so a refused product can't run up time.
- Fast: products are collected 5 at a time. A product TikTok keeps refusing gives up after about 20 seconds (longer for large limits while TikTok is still serving it) and is marked incomplete instead of holding up the run. With the defaults, the 3 example products take about 15 seconds.
- Products whose count includes a few reviews TikTok doesn't publish (for example 3 of 4) finish as soon as the list ends, instead of retrying the missing ones.
- The log ends with one line per product: reviews, status and seconds.
- TikTok's "Security Check" captcha on a product or search page is retried on a fresh IP. A product that still can't be opened is reported with the reason `challenge`.
- Products TikTok lists with no reviews finish right away as complete with 0 reviews.
- Modern `shop.tiktok.com/us/pdp/...` links work, as do `www.tiktok.com/shop/pdp/...`, `/view/product/<id>` links and product IDs.
- **New, cleaner rows.** Short camelCase field names in reading order (`text`, `rating`, `variant`, `reviewedAt`, ...), every field on every row with `null` when TikTok has no value, product image and review photo links without tracking parameters, and a Console table with images, stars and review snippets. Fields TikTok never fills (`likes_count`, video fields) or fills the same on every row (`reviewer_country`, always US) are gone. The README maps every old name to the new one.
- **Every keyword per product:** `query` is now `queries`, a list. A product found by two of your keywords is collected once and lists both.
- **Two free tables per run:** 🛍️ Products (star rating, 5-to-1 star counts, TikTok's review count next to the number collected, status in words) and 📸 Photo Reviews (the reviews with photos).
- **Old field names on request:** set `outputFormat` to `v2` to get rows with the version 2 names and layout, built by version 2's rules (snake_case keys in the same order, empty values left out, `compactNullFields` and `includeRawProduct` as before). They now hold full reviews and also fill `review_date`, `reviewer_id`, `reviewer_country` and `variant`, which version 2 left out; the README lists the differences.
- Old input fields that no longer do anything are accepted and ignored.
