TikTok Shop scraper: track a store’s products, price, stock and sold count
Sellers and brand analysts watch competing TikTok Shop stores to see which products sell, when prices drop and when stock runs out. TikTok Shop has no export, and the numbers change every day.
arcadium/tiktok-shop-products takes product, store or category URLs (US and UK) and returns one row per product: current and original price, every variant with its stock, TikTok’s sold counter, rating, shipping, promotion labels and the shop’s own stats. No login or cookies.
Cost of this example on the Apify Free plan: 15 × $0.0225 + 5 × $0.0075 = $0.375 ($0.225 on the Apify Gold plan and higher), plus $0.001 per GB of memory when the run starts.
What you need
- An Apify account and API token.
- The TikTok Shop store URLs to watch (
https://www.tiktok.com/shop/store/<name>/<id>), or product or category URLs.
Step 1: Run it in the Apify Store (no code)
- Open arcadium/tiktok-shop-products on the Apify Store and sign in (a free Apify account works).
- Paste the store URLs into TikTok Shop URLs or product ids, one per line.
- Set Max products per store or category URL, for example 20 (a store page lists its first ~20 products).
- Set Description to
noneif you only need the numbers; it keeps the rows small. - Optional: set a maximum cost per run in the run options as a hard cap.
- Click Start. Rows appear in the Output tab; export them as JSON, CSV or Excel.
The same input as JSON (paste it in the JSON tab of the input form):
{
"startUrls": [
"https://www.tiktok.com/shop/store/asterwood/7495384600901552906"
],
"maxProductsPerUrl": 20,
"description": "none"
}
Step 2: Call it over the Apify API
One HTTP call runs the actor and returns its rows. It suits runs up to about five minutes; for longer runs start the run asynchronously and read the dataset when it finishes.
curl -X POST "https://api.apify.com/v2/acts/arcadium~tiktok-shop-products/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"startUrls":["https://www.tiktok.com/shop/store/asterwood/7495384600901552906"],"maxProductsPerUrl":20,"description":"none"}'
Step 3: Run it from Python
With apify-client 3.x, call() returns a Run object: read the dataset id as run.default_dataset_id (older examples use run["defaultDatasetId"], which no longer works).
# pip install "apify-client>=3"
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("arcadium/tiktok-shop-products").call(run_input={
"startUrls": ["https://www.tiktok.com/shop/store/asterwood/7495384600901552906"],
"maxProductsPerUrl": 20,
"description": "none",
})
rows = list(client.dataset(run.default_dataset_id).iterate_items()) # apify-client 3.x
products = [r for r in rows if r.get("rowType") == "product"]
for p in sorted(products, key=lambda r: r.get("soldCount") or 0, reverse=True):
print(p.get("soldCount"), p.get("price"), p.get("originalPrice"), p.get("totalStock"),
p.get("detailLevel"), ", ".join(p.get("promotions") or []), p.get("title"))
for e in (r for r in rows if r.get("rowType") == "error"):
print("could not read:", e.get("input"), e.get("code"))
Step 4: Run it from JavaScript
// npm install apify-client
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('arcadium/tiktok-shop-products').call({
"startUrls": [
"https://www.tiktok.com/shop/store/asterwood/7495384600901552906"
],
"maxProductsPerUrl": 20,
"description": "none"
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
Step 5: Ask an AI assistant (MCP)
Apify’s hosted MCP server turns the actor into one tool. Add it to Claude, Cursor, VS Code or any MCP client:
{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com/?tools=arcadium/tiktok-shop-products",
"headers": {
"Authorization": "Bearer <APIFY_TOKEN>"
}
}
}
}Then ask, for example:
Use arcadium/tiktok-shop-products to read the products of https://www.tiktok.com/shop/store/asterwood/7495384600901552906. Rank them by soldCount and tell me which ones are discounted, in a flash sale or low on stock.
More clients and the local setup on the MCP page.
Track changes every day
Save the input as a Task in Apify Console and add a daily Schedule. Each run writes a new dataset; join the runs on productId and compare price, totalStock, soldCount and promotions to see price changes, sell-outs and new flash sales. The difference in soldCount between two days is TikTok’s own counter moving, not an exact sales figure.
Single products and categories
Product URLs (https://shop.tiktok.com/us/pdp/...) or bare product ids give one full row each; use region (US or GB) for bare ids. A category URL (https://shop.tiktok.com/us/c/<name>/<id>) gives a changing sample of the category, so repeated runs build a wider picture.
Output fields
Every row has a rowType; filter on it first. Failed inputs come back as free rows with a code and message. The fields this tutorial uses, from the actor’s dataset schema:
| Field | What it holds |
|---|---|
rowType | Kind of row. Filter on this first. 'product': one TikTok Shop product (charged; see detailLevel). 'error': an input could not be read; see code and message (free). |
productId | TikTok Shop product id (the long number at the end of the product URL). |
detailLevel | 'full': read from the product page (charged as 'product'). 'card': TikTok did not serve the product page to an anonymous visitor, so the row holds only what the store or category card shows: title, price, originalPrice, discountPercent, soldCount, rating, reviewCount, seller id and name, one image (charged as 'product-card'; the other fields are null or empty). |
title | Product title as the seller wrote it. |
price | Lowest current variant price (after discounts), in currency. |
originalPrice | Lowest variant price before discounts; null when nothing is discounted. |
discountPercent | Discount of the lowest price against originalPrice, in percent; null without a discount. |
soldCount | Items sold since the product was listed, all markets (TikTok's own counter, excluding returns). |
rating | Average product rating, 1 to 5; null without reviews. |
reviewCount | Number of product reviews. |
variants | Purchasable variants (SKUs): skuId, options (e.g. {"Size": "1oz"}), price, originalPrice, discountPercent, stock, purchaseLimit, available. |
totalStock | Sum of variant stock as the page states it; null when no variant states stock. |
promotions | Promotion labels shown on the page, e.g. "Flash sale", "Free shipping". |
seller | The shop as a business: sellerId, name, url, rating, soldCount, productCount, reviewCount, followers, videoCount, badge (e.g. "OFFICIAL SHOP"), businessName (legal company name, only when it is clearly a company). No owner or creator account. |
All fields: TikTok Shop Scraper guide.
Cost per run
Pay per event: you pay for the rows delivered, at the actor’s live Apify price on 2026-11-02. Error, coverage and summary rows are free.
| What | Rows | Price per row (Free plan) | Subtotal |
|---|---|---|---|
| Product: 1 store, products read from their own page | 15 | $0.0225 | $0.3375 |
| Product card: products TikTok does not open anonymously (card data) | 5 | $0.0075 | $0.0375 |
Cost of this example on the Apify Free plan: 15 × $0.0225 + 5 × $0.0075 = $0.375 ($0.225 on the Apify Gold plan and higher), plus $0.001 per GB of memory when the run starts. Higher Apify plans pay less per row. The Store page always has the current price.
Limitations
- The split between full rows and card rows in the cost example is an estimate: in our tests about a quarter of store and category products came back as card rows. Card rows hold title, price, discount, sold count, rating, seller and image, and cost a third of a full row.
- US and UK only. TikTok does not serve the other Shop markets (EU, Southeast Asia, Latin America, Japan) to anonymous visitors.
- No keyword search: TikTok shows search results only behind a captcha. Use store or category URLs to discover products.
- A store URL gives the store's first ~20 products (the batch the store page loads first). A category URL gives a rotating sample: the actor reloads it while it keeps adding new products.
- TikTok opens some product pages to anonymous visitors only behind a check page, on every attempt (in our tests about a quarter of store and category products). Those come back as
detailLevel: "card"rows when they were found on a store or category page, or as a freeunavailableerror row when given directly. soldCountis TikTok's own global counter; shipping and delivery days are for the market of the page and change with the request date.
Links
- TikTok Shop Scraper: fields, price table and sample output
- How to use TikTok Shop Scraper: every input field, n8n, LangChain
- arcadium/tiktok-shop-products on the Apify Store
- All tutorials