# TikTok Shop Trending Products & Sales Velocity (`nexascout/tiktok-shop-trending-products`) Actor

Track TikTok Shop products by keyword or URL. Measure sold-count growth, estimated daily sales, price changes, review growth, and opportunity-rank movement across recurring runs. Export verified results to JSON, CSV, Excel, or API—no external data provider required.

- **URL**: https://apify.com/nexascout/tiktok-shop-trending-products.md
- **Developed by:** [Scout](https://apify.com/nexascout) (community)
- **Categories:** E-commerce, Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $9.00 / 1,000 tracked product results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## TikTok Shop Trend Tracker & Sales Velocity

Track TikTok Shop products in selected niches and turn repeated public observations into measurable trend signals: sold-count growth, estimated units per day, price changes, review growth, and opportunity-rank movement.

The first run creates an honest baseline. Run the same tracker later—or schedule it daily—to measure what changed. Every result explains whether its trend data is a baseline, too recent to extrapolate, or based on a valid comparison window.

This Actor owns its extraction and tracking pipeline. It does **not** call another Apify Actor, a third-party TikTok data API, or a publisher-owned TikTok account. It requests public TikTok Shop pages through the proxy configuration selected by the Actor user and stores tracker history privately in that user's Apify account.

### For AI agents and MCP clients

Use this Actor when the user asks to **monitor TikTok Shop products repeatedly** and compare sold-count growth, estimated units per day, price changes, review growth, or opportunity-rank movement.

- **Actor tool ID:** `nexascout/tiktok-shop-trending-products`
- **Minimum input:** `{"searchQueries":["car accessories"],"trackerName":"daily-watch","maxProductsPerQuery":3}`
- **Required workflow:** first run creates `BASELINE`; run later with the same `trackerName`, region, queries, and product URLs to obtain `MEASURED` changes
- **Dataset contract:** one billable row per product observation per run
- **Run summary:** `OUTPUT` in the default key-value store
- **Do not use for:** a simple one-time product snapshot, creator discovery, private contacts, or official TikTok leaderboard data

For deterministic tool availability, connect an MCP client to the [NexaScout three-Actor endpoint](https://mcp.apify.com?tools=nexascout/tiktok-shop-product-radar,nexascout/tiktok-shop-trending-products,nexascout/tiktok-shop-affiliate-creator-finder). The client can inspect this Actor's input and output schemas before calling it.

### Choose the right NexaScout Actor

| User intent | Actor |
| --- | --- |
| Current product discovery, commerce fields, and snapshot viral ranking | [Product Scraper & Viral Radar](https://apify.com/nexascout/tiktok-shop-product-radar) |
| Recurring observations, sold-count growth, price/review changes, and sales velocity | **This Actor — Trend Tracker & Sales Velocity** |
| Public creators, product videos, engagement metrics, and association evidence | [Affiliate Creator & Video Finder](https://apify.com/nexascout/tiktok-shop-affiliate-creator-finder) |

### Why use this Actor

- **Find products by niche** using public TikTok Shop keyword catalogs
- **Monitor specific product URLs** alongside niche discovery
- **Measure sold-count growth** between recurring observations
- **Estimate units per day** using the exact elapsed time—not a fixed assumption
- **Track price, review, and rank changes** without maintaining your own database
- **Transparent trend scoring** with human-readable reasons and confidence states
- **Automation-ready output** for Apify Schedules, API, webhooks, Make, Zapier, n8n, CSV, and Excel

### How tracking works

#### First run: baseline

The Actor discovers and validates products, assigns a current opportunity rank inside each query group, and saves a private snapshot. Because no earlier observation exists, it returns:

- `trackingState: "BASELINE"`
- `trendConfidence: "BASELINE"`
- `salesDelta: null`
- `estimatedUnitsPerDay: null`

This is deliberate. A single snapshot can show popularity, but it cannot prove growth.

#### Later run: measured change

Run the same inputs with the same `trackerName` after at least six hours—daily is recommended. The Actor compares current public metrics with the previous snapshot and derives:

- `salesDelta = current salesTotal - previous salesTotal`
- `estimatedUnitsPerDay = salesDelta / elapsed days`
- `priceChange` and `priceChangePercent`
- `reviewDelta`
- `rankChange = previous opportunity rank - current opportunity rank`
- `firstSeenAt`, `trackingWindowHours`, and `observationCount`

Positive `rankChange` means the product climbed. The opportunity rank is this Actor's transparent within-query ranking based on observed commerce evidence; it is **not** presented as an official TikTok leaderboard position.

#### Runs that are too close together

If the previous observation is newer than `minimumTrackingHours`, the Actor still reports raw deltas but returns:

- `trackingState: "TOO_SOON"`
- `estimatedUnitsPerDay: null`

This prevents a short spike from being extrapolated into a misleading daily figure.
The early check does not advance the saved comparison anchor, so frequent manual runs cannot prevent a later scheduled run from reaching a valid measurement window.

### Input example

```json
{
  "searchQueries": ["car accessories", "kitchen gadgets"],
  "productUrls": [],
  "trackerName": "daily-product-watch",
  "trackingEnabled": true,
  "resetHistory": false,
  "minimumTrackingHours": 6,
  "retainMissingDays": 30,
  "region": "US",
  "maxProductsPerQuery": 10,
  "sortBy": "TREND_SCORE",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "US"
  },
  "maxConcurrency": 2,
  "navigationTimeoutSecs": 45,
  "includeRawData": false,
  "includeSearchFallbacks": false
}
```

Keep the same `trackerName`, region, queries, and watchlist on recurring runs. If you change the query scope, the Actor automatically isolates it under a different tracker record even when the visible name is reused.

### Example measured output

```json
{
  "productId": "1729569241736188017",
  "productName": "Wireless CarPlay Screen",
  "productUrl": "https://shop.tiktok.com/us/pdp/wireless-carplay-screen/1729569241736188017",
  "imageUrl": "https://example.com/product.webp",
  "price": 50.99,
  "previousPrice": 54.99,
  "priceChange": -4,
  "priceChangePercent": -7.3,
  "currency": "USD",
  "salesTotal": 467277,
  "previousSalesTotal": 463077,
  "salesDelta": 4200,
  "estimatedUnitsPerDay": 4200,
  "rating": 4.2,
  "reviewCount": 45682,
  "previousReviewCount": 45412,
  "reviewDelta": 270,
  "sellerName": "Example Store",
  "viralScore": 90.2,
  "trackerName": "daily-product-watch",
  "trackingGroup": "car accessories",
  "trackingState": "MEASURED",
  "trendConfidence": "MEDIUM",
  "trendScore": 94.1,
  "trendSignals": [
    "Exceptional sales velocity",
    "Opportunity rank climbed 3 positions",
    "Review count increased by 270",
    "Price decreased since the previous observation"
  ],
  "opportunityRank": 2,
  "previousOpportunityRank": 5,
  "rankChange": 3,
  "firstSeenAt": "2026-08-20T00:00:00.000Z",
  "previousSeenAt": "2026-08-24T00:00:00.000Z",
  "trackingWindowHours": 24,
  "observationCount": 3,
  "qualityState": "verified_success",
  "dataSource": "tiktok_search_http_json",
  "searchQuery": "car accessories",
  "scrapedAt": "2026-08-25T00:00:00.000Z"
}
```

The values above illustrate the schema. The Actor returns only metrics that TikTok exposes publicly for the current product and region.

### Trend score

The 0–100 `trendScore` is deterministic and auditable.

For a measured observation it combines:

- Current verified product evidence through the existing `viralScore`: up to 45 weighted points
- Estimated public sold-count velocity: up to 35 points
- Positive opportunity-rank movement: up to 15 points
- Review growth: up to 5 points
- A verified price decrease: up to 5 additional points, with the final score capped at 100

Negative rank movement can reduce the score. A first observation uses only current evidence and is clearly labeled as a baseline. The score is a research-ranking signal, not a promise of future sales or revenue.

### Data quality

| State | Meaning |
| --- | --- |
| `verified_success` | Structured TikTok data and at least one live commerce field were captured. |
| `partial_verified` | The product was confirmed, but only part of its public commerce data was available. |
| `serp_enriched` | The URL came from a public search index and could not be fully live-validated. Returned only when explicitly enabled. |

Search-only rows are disabled by default so normal monitoring datasets contain live verified products.

### Private history and dropped products

When tracking is enabled, the Actor creates an additional named key-value store in the running user's Apify account. It saves only normalized observations required for comparisons—not cookies, proxy credentials, or private TikTok data.

Products that disappear from the current result are listed in the run's `OUTPUT` summary and retained privately for the configured number of days. They are not written as extra billable dataset rows.

Use `resetHistory: true` when you intentionally want a fresh baseline. The previous snapshot is replaced only after the current extraction completes.

### Recommended schedule

1. Run the Actor once and confirm that the dataset contains live products.
2. Save the configuration as an Apify Task.
3. Schedule it every 24 hours.
4. Keep the same `trackerName` and query scope.
5. Read the latest dataset through the Apify API or send it to a webhook, spreadsheet, or automation workflow.

Daily observations are usually more stable than hourly ones because public sold counts may be rounded or delayed.

### Pricing and cost notes

The recommended launch configuration is **$0.009 per dataset result** (**$9 per 1,000 results**) plus Apify's standard small Actor-start event, with platform usage included in the event prices. A default five-product baseline run therefore creates only five billable results.

The Actor writes each current product once per run. Missing products remain in the private summary and are not charged as dataset rows. If `includeSearchFallbacks` is enabled, its clearly labeled search-only leads are dataset results and are billed as such.

US residential proxy is recommended because TikTok Shop is geo-sensitive and frequently rate-limits data-center traffic. Keep `maxConcurrency` at 1–2.

### Owned extraction pipeline

1. Read TikTok's public keyword catalog for each niche.
2. Parse embedded product JSON and public metadata.
3. Validate and enrich candidates through public product-detail pages.
4. Use Playwright only when lightweight HTTP extraction is incomplete.
5. Preserve cookies per proxy session and retire challenged sessions.
6. Reject unrelated catalog leakage before ranking.
7. Compare normalized observations with the previous private snapshot.
8. Write current results to the default dataset and diagnostics to `OUTPUT`.

The Actor does not solve CAPTCHAs, log in to TikTok, access private affiliate analytics, or call paid external data providers.

### Current limitations

- US TikTok Shop only in this release
- The first run is a baseline and cannot contain real cross-run velocity
- Public sold counts can be delayed, rounded, corrected, or reset by TikTok
- A negative sold-count reset is not treated as negative sales; velocity becomes `null`
- Availability and fields depend on what TikTok exposes publicly
- Narrow or newly indexed niches may return fewer products than requested
- Opportunity rank is this Actor's evidence-based within-query rank, not an official TikTok leaderboard rank

### Responsible use

This Actor extracts publicly visible product and seller information. Do not use it to collect private data, defeat access controls, or violate applicable laws, contracts, or platform rules. Evaluate sourcing, intellectual property, product safety, and commercial claims independently before selling any product.

### Support

When reporting an issue, include the run ID, tracker name, region, failed stage, and `trackingState`. Never post private proxy credentials, cookies, or tokens.

# Actor input Schema

## `searchQueries` (type: `array`):

Optional TikTok Shop niches to track, for example car accessories, skincare serum, kitchen gadgets, or pet supplies. Use at least one query or product URL; keep the same values across recurring runs.

## `productUrls` (type: `array`):

Optional TikTok Shop product watchlist. Combine with searchQueries or use URLs alone, and keep the same watchlist across recurring runs for comparable history.

## `trackerName` (type: `string`):

Stable monitoring-job identifier. Reuse the exact trackerName, region, queries, and product URLs on scheduled runs so the Actor can compare observations; changing the scope isolates history.

## `trackingEnabled` (type: `boolean`):

Store a private snapshot in your Apify account and compare it with later runs. Disable for one-off snapshots.

## `resetHistory` (type: `boolean`):

Ignore the previous snapshot and create a new baseline. The old record is replaced only after a successful observation.

## `minimumTrackingHours` (type: `integer`):

Avoids unstable extrapolation when two runs happen too close together. Six hours is a safe minimum; daily schedules are recommended.

## `retainMissingDays` (type: `integer`):

Keeps recently missing products in private tracker history so their first-seen date is preserved if they return.

## `region` (type: `string`):

TikTok Shop market code. This release supports the United States.

## `maxProductsPerQuery` (type: `integer`):

Maximum billable dataset rows returned per keyword on every observation. Smaller recurring runs are faster and cheaper.

## `sortBy` (type: `string`):

Trend score is recommended. Sales velocity and rank change become meaningful after a second observation.

## `proxyConfiguration` (type: `object`):

US residential proxy is recommended because TikTok Shop is geo-sensitive and rate-limits data-center traffic.

## `maxConcurrency` (type: `integer`):

Keep this at 1–2 to reduce TikTok security challenges and residential proxy traffic.

## `navigationTimeoutSecs` (type: `integer`):

Maximum time allowed for each HTTP or browser navigation.

## `includeRawData` (type: `boolean`):

Include the best raw product object captured from TikTok. Useful for debugging, but makes exports larger.

## `includeSearchFallbacks` (type: `boolean`):

Return indexed product URLs even when the live TikTok page could not be validated. Disabled by default; enabled search-only rows are also billable results.

## Actor input object example

```json
{
  "searchQueries": [
    "car accessories"
  ],
  "productUrls": [],
  "trackerName": "my-trend-tracker",
  "trackingEnabled": true,
  "resetHistory": false,
  "minimumTrackingHours": 6,
  "retainMissingDays": 30,
  "region": "US",
  "maxProductsPerQuery": 5,
  "sortBy": "TREND_SCORE",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  },
  "maxConcurrency": 2,
  "navigationTimeoutSecs": 45,
  "includeRawData": false,
  "includeSearchFallbacks": false
}
```

# Actor output Schema

## `products` (type: `string`):

Default dataset items. Each billable row is one current product observation with trackingState, comparison fields, trend confidence, and transparent trend signals.

## `runSummary` (type: `string`):

OUTPUT key-value record with baseline/measured state, comparison-window counts, dropped products, quality diagnostics, and extraction failures.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchQueries": [
        "car accessories"
    ],
    "productUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("nexascout/tiktok-shop-trending-products").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchQueries": ["car accessories"],
    "productUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("nexascout/tiktok-shop-trending-products").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchQueries": [
    "car accessories"
  ],
  "productUrls": []
}' |
apify call nexascout/tiktok-shop-trending-products --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nexascout/tiktok-shop-trending-products"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/rV5U8w8nIqqvmiqeq/builds/zfzDbgDQ9v2a0HEgJ/openapi.json
