# (NEW) TikTok Shop Scraper – Products, Sales, Prices & Stores (`harshmaur/tiktok-shop-scraper`) Actor

Scrape TikTok Shop products, stores, categories and search in the US, UK, Singapore, Malaysia, Philippines, Thailand and Vietnam. Get price, sold count, rating, variants, stock, seller stats and reviews. No login. Pay only for products returned.

- **URL**: https://apify.com/harshmaur/tiktok-shop-scraper.md
- **Developed by:** [Harsh Maur](https://apify.com/harshmaur) (community)
- **Categories:** E-commerce, Social media
- **Stats:** 21 total users, 12 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 products

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## TikTok Shop Scraper: Products, Prices, Sold Counts, Stock & Sellers (No Login)

Export **TikTok Shop products** to JSON, CSV or Excel: price, discount, **sold count**, rating, variants with **stock levels**, shipping, seller stats and the first customer reviews. Start from a keyword, a store, a category, a product link or a bare product ID.

The scraper browses TikTok Shop the way a logged-out shopper does. You don't need a TikTok account, cookies or a Shop API key, and you don't have to set up proxies.

It works in 7 markets: the **United States, United Kingdom, Singapore, Malaysia, Philippines, Thailand and Vietnam**.

### What can this TikTok Shop scraper do?

- **Search TikTok Shop by keyword.** Type "phone case" or "cat grooming" and get the matching products in the US and the Southeast Asian markets. TikTok Shop UK has no keyword search on its website, so use UK category or store links.
- **Export a whole store.** Paste a seller's store link and get every product in its catalogue.
- **Scrape a category.** Paste a category link. The scraper also walks that category's subcategories.
- **Look up single products.** Paste product links or 19-digit product IDs to get the full detail page for each one.
- **Choose detail level.** Full detail opens every product page. Card mode returns only the listing cards, which is faster and cheaper.
- **Track change over time.** Schedule runs and compare price, stock and `soldCount` between them.

### How to scrape TikTok Shop products

1. Add TikTok Shop links to **Start URLs**, or keywords to **Search queries**. You can use both in one run.
2. Pick a **Market** for keywords and for links that don't name a country.
3. Set **Max products per source** to cap each keyword, store or category.
4. Leave **Scrape product details** on for full product data, or turn it off for listing cards only.
5. Click **Start**. Products appear in the dataset as they are scraped, and you can download them in any format Apify supports.

### TikTok Shop scraper input

| Field | Type | Default | What it does |
| --- | --- | --- | --- |
| `startUrls` | list | — | Any TikTok Shop link: product, store, category or search page, or a bare product ID |
| `searchQueries` | list | — | Keywords to search on TikTok Shop |
| `market` | select | `us` | `us`, `gb`, `sg`, `my`, `ph`, `th` or `vn`. Used for keywords, bare IDs and links without a country code |
| `maxProductsPerSource` | integer | `50` | Most products to return for each keyword, store or category |
| `scrapeProductDetails` | boolean | `true` | `true` opens each product page; `false` returns listing cards only |
| `searchSort` | select | `relevance` | `relevance`, `best_selling`, `price_low_to_high`, `price_high_to_low` or `newest` |
| `mcpConnector` | connector | — | Optional. Sends results to Slack, Notion or Google Sheets when the run ends |

#### Which TikTok Shop links work?

- Product pages: `https://www.tiktok.com/shop/pdp/<slug>/<id>`, `https://shop.tiktok.com/us/pdp/<id>` and `/view/product/<id>` links
- Store pages: `https://www.tiktok.com/shop/store/<name>/<id>`
- Category pages: `https://www.tiktok.com/shop/c/<name>/<id>`
- Search pages: `https://shop.tiktok.com/us/s?q=...`
- A bare 19-digit product ID, such as `1731578642912612516`

When a link contains a country, such as `/sg/`, that market is used for it. Everything else falls back to the `market` setting.

#### Example input

```json
{
  "searchQueries": ["cat nail clipper", "pet grooming glove"],
  "startUrls": [
    "https://www.tiktok.com/shop/store/potaroma-llc/7495813075786500260",
    "1731578642912612516"
  ],
  "market": "us",
  "maxProductsPerSource": 100,
  "scrapeProductDetails": true,
  "searchSort": "best_selling"
}
```

### TikTok Shop data output

You get one dataset row per product, with `dataType: "product"`. The `detailLevel` field tells you how much of the row is filled:

- **`"full"`** (from `scrapeProductDetails: true`): every field below, read from the product page.
- **`"card"`** (from `scrapeProductDetails: false`): the fields TikTok shows on a search, store or category card. Fields that only exist on the product page, such as `variants`, `specifications`, `shipping` and `topReviews`, are empty or `null`.

#### Fields in each product row

- **Product**: `productId`, `market`, `url`, `title`, `brand`, `description`, `categories` (names from top level down to leaf), `images`, `specifications` (`name` / `value` pairs)
- **Price**: `price`, `originalPrice`, `discountPercent`, `currency`, `priceText`
- **Sales and ratings**: `soldCount`, `rating`, `reviewCount`, `ratingBreakdown` (number of 1 to 5 star ratings)
- **Variants and stock**: `variants` (each with `skuId`, `name`, `properties`, `price`, `originalPrice`, `stock`, `available`) and `totalStock`
- **Shipping**: `shipping` with `isFree`, `fee`, `currency`, `deliveryMinDays`, `deliveryMaxDays`, `deliveryEstimate`, `method`
- **Seller**: `seller` with `id`, `name`, `url`, `rating`, `followerCount`, `productCount`, `soldCount`, `reviewCount`, `positiveFeedbackPercent`
- **Reviews**: `topReviews` (each with `reviewId`, `rating`, `text`, `reviewerName`, `createdAt`, `variant`, `isVerifiedPurchase`, `isIncentivized`, `images`, `country`)
- **Run info**: `source` (`type` is `product`, `store`, `category` or `search`, plus the `input` that found the product) and `scrapedAt`

#### Example product row

Arrays are trimmed to one entry here.

```json
{
  "dataType": "product",
  "detailLevel": "full",
  "productId": "1731578642912612516",
  "market": "us",
  "url": "https://shop.tiktok.com/us/pdp/cat-nail-clipper-by-potaroma-adjustable-sizes-built-in-file-safe-for-kittens-cats/1731578642912612516",
  "title": "Potaroma Universal Cat Paw Trimmer - 4-Size Adjustable Holes…",
  "brand": null,
  "price": 12.69,
  "originalPrice": 20.0,
  "discountPercent": 37,
  "currency": "USD",
  "priceText": "$12.69",
  "soldCount": 15742,
  "rating": 4.5,
  "reviewCount": 1294,
  "ratingBreakdown": { "1": 82, "2": 44, "3": 74, "4": 153, "5": 941 },
  "categories": ["Pet Supplies", "Dog & Cat Grooming", "Claw Care"],
  "variants": [
    {
      "skuId": "1731578664610402468",
      "name": "Default",
      "properties": { "Specifications": "Default" },
      "price": 12.69,
      "originalPrice": 20,
      "stock": 44,
      "available": true
    }
  ],
  "totalStock": 44,
  "shipping": {
    "isFree": true,
    "fee": 0,
    "currency": "USD",
    "deliveryMinDays": 3,
    "deliveryMaxDays": 6,
    "deliveryEstimate": "Oct 6 - Oct 9",
    "method": "Standard"
  },
  "seller": {
    "id": "7495813075786500260",
    "name": "Potaroma LLC",
    "url": "https://shop.tiktok.com/us/store/potaroma-llc/7495813075786500260",
    "rating": 4.4,
    "followerCount": 13294,
    "productCount": 63,
    "soldCount": 203881,
    "reviewCount": 16771,
    "positiveFeedbackPercent": 87
  },
  "source": { "type": "store", "input": "https://www.tiktok.com/shop/store/potaroma-llc/7495813075786500260" },
  "scrapedAt": "2026-10-03T09:12:44.000Z"
}
```

#### Failed products

If a product can't be fetched, you still get a row so nothing goes missing silently. It has `dataType: "failed"` and an `errorCode`, for example `product_not_found` (delisted), `product_unavailable` (TikTok refused the ID, which usually means it does not exist in that market), `region_not_available` (not sold in that market), `no_products` (a keyword, store or category with no results) or `blocked`. Failed rows are free.

### How many products can you scrape from TikTok Shop?

The limits come from TikTok, not from the scraper:

- **Keyword search:** about 50 to 300 products per keyword, depending on the keyword. TikTok stops paging after that, so the scraper runs the same keyword under several sort orders and merges the results to get past a single list.
- **Category pages:** up to about 100 products per category. TikTok shows a rotating sample of each category, so the scraper also visits the subcategories to cover more of it.
- **Store pages:** the full catalogue of the store.

To get more products for a broad topic, split it into narrower keywords or add the relevant subcategory links.

### TikTok Shop scraper use cases

- **Find winning products.** Search a niche, sort by `best_selling`, and rank the results by `soldCount` and `rating` to see what is moving.
- **Monitor competitor prices and stock.** Schedule a daily run on a rival's store and watch `price`, `discountPercent` and per-variant `stock`.
- **Export a seller's catalogue.** Download every listing from a store, with seller follower count, total sales and feedback score.
- **Track sold counts over time.** `soldCount` is a running total, so the difference between two scheduled runs shows how many units sold in between.
- **Source products as an affiliate or creator.** Shortlist well-reviewed, well-stocked products with free shipping before you promote them.
- **Research Southeast Asian markets.** Run the same keywords in Singapore, Malaysia, the Philippines, Thailand and Vietnam and compare prices, sellers and demand by country.

### How much does it cost to scrape TikTok Shop?

Pricing is pay per event. You pay only for products you receive:

| Mode | Price |
| --- | --- |
| Listing cards (`scrapeProductDetails: false`) | **$2.00 per 1,000 products** |
| Full product details (`scrapeProductDetails: true`) | **$3.50 per 1,000 products** |

Product links and product IDs always return full details, so they are billed at the full-detail price. There is no start fee, and failed rows are never charged. For comparison, many TikTok Shop actors charge $5 to $30 per 1,000 products.

Card mode is the cheaper option when you only need price, sold count and rating for many products. Use full details when you need variants, stock, shipping, seller data or reviews.

### Send TikTok Shop data to Slack, Notion or Google Sheets

Choose an authorized MCP connector in `mcpConnector` and the scraped products are posted to that app when the run finishes. Combined with a schedule, this gives you a daily price or sold-count feed in a channel, page or sheet. Delivery is optional. If you leave the field empty, the run behaves exactly the same and nothing is sent anywhere.

### Use the TikTok Shop scraper from AI agents

Claude, ChatGPT, Cursor and other MCP-capable agents can call this actor through Apify's MCP server:

```
https://mcp.apify.com/?tools=harshmaur/tiktok-shop-scraper
```

The agent can then ask questions like "find the best-selling pet grooming products on TikTok Shop US" and get structured rows back.

### API, schedules and integrations

- **Apify API:** start runs and read the dataset from any language, or use the Python and JavaScript clients.
- **Schedules:** run hourly, daily or weekly to keep a price and stock history.
- **Webhooks:** get notified when a run ends and pull the new rows.
- **Make, Zapier and n8n:** connect through Apify's integrations or a plain HTTP request to the API.

### FAQ

#### Is it legal to scrape TikTok Shop?

The scraper reads only public product pages that anyone can open without logging in. Reviewer names are the display names TikTok already shows publicly, and they arrive masked (for example `L**G`). You are still responsible for following the laws in your country and TikTok's terms, especially if you store or republish the data. If in doubt, ask a lawyer.

#### Which countries does it support?

The United States (`us`), United Kingdom (`gb`), Singapore (`sg`), Malaysia (`my`), Philippines (`ph`), Thailand (`th`) and Vietnam (`vn`). Indonesia is not supported because TikTok Shop there moved to Tokopedia. Brazil, Mexico, Japan and EU countries are not supported in this version. In the UK, product, store and category links work, but keyword search does not, because TikTok Shop UK does not offer it on its website.

#### Do I need a TikTok account, cookies or proxies?

No. There is nothing to log in to and no cookies to paste. The scraper handles the connection to TikTok itself, so you don't need to configure a proxy.

#### Why did some products fail?

Usually the product has been delisted (`product_not_found`), the ID does not exist in that market (`product_unavailable`), or it is not sold in the market you asked for (`region_not_available`). Occasionally TikTok refuses a request (`blocked`). Each case returns a free `failed` row with the `errorCode`, so you can see what happened.

#### How many results do I get per keyword?

Roughly 50 to 300, depending on the keyword. TikTok caps search results, and the scraper combines sort orders to reach as many as it allows. Stores return their full catalogue.

#### How fresh is the data?

Every run reads TikTok Shop live, so prices, stock and sold counts are what TikTok showed at `scrapedAt`.

#### Can I track a product's sold count every day?

Yes. Save your input as a task, schedule it daily, and compare `soldCount` for the same `productId` between runs. The difference is the units sold that day.

#### Can I export all reviews for a product?

Not in this version. Each full product row includes the first reviews TikTok shows on the page (usually 3) in `topReviews`, plus the complete 1 to 5 star counts in `ratingBreakdown`.

#### What is the difference between card and full detail mode?

Card mode reads search, store and category listings only, so it is faster and costs $2.00 per 1,000. Full detail mode opens each product page and adds variants, stock, description, specifications, shipping, seller stats, the rating breakdown and top reviews, for $3.50 per 1,000.

### More scrapers by the same developer

- [Reddit Scraper](https://apify.com/harshmaur/reddit-scraper): collect posts, comments and user activity from any subreddit or search.
- [Facebook Ads Library Scraper](https://apify.com/harshmaur/facebook-ads-library-scraper): see which ads a brand runs on Meta and how long each one has been live.
- [YouTube Transcript Scraper](https://apify.com/harshmaur/youtube-transcript-scraper): turn video, channel or playlist captions into text, SRT or VTT.
- [LinkedIn Jobs Scraper](https://apify.com/harshmaur/linkedin-jobs-scraper): pull public job postings by keyword, location and filters.
- [Indeed Scraper](https://apify.com/harshmaur/indeed-scraper): export Indeed job listings with salaries and company details.

# Actor input Schema

## `startUrls` (type: `array`):

Any TikTok Shop link: a product page (tiktok.com/shop/pdp/…), a store page (tiktok.com/shop/store/…), a category page (tiktok.com/shop/c/…) or a search page (shop.tiktok.com/us/s?q=…). You can also paste a bare 19-digit product ID. A link that names a country (for example /sg/) uses that country; other links use the Market below.

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

Search TikTok Shop for each keyword, as a shopper would. Each keyword returns up to 'Max products per source'. Not available in the UK store: use UK category or store links.

## `market` (type: `string`):

The TikTok Shop country for keywords, bare product IDs and links that do not name a country. Prices, stock and search results are those of this market.

## `maxProductsPerSource` (type: `integer`):

The most products to take from EACH keyword, store or category. Product links are always scraped. TikTok shows about 50–300 products per keyword and about 100 per category; stores return their full catalogue.

## `scrapeProductDetails` (type: `boolean`):

On: open every product page for variants, stock, description, specifications, shipping, seller stats, the star rating breakdown and the first reviews. Off: return only the product cards from search, store and category pages (faster and cheaper).

## `searchSort` (type: `string`):

How keyword results are ordered. When a keyword runs out of results in this order, the actor continues with the other orders to reach your maximum.

## `mcpConnector` (type: `string`):

Pick an authorized MCP connector (Slack, Notion, Airtable, Google Sheets, …) to receive the products. Your credentials stay in Apify and are never exposed to this actor (Apify's proxy injects them). Leave empty to scrape only. Tip: schedule a store or keyword to log prices and sold counts in your workspace.

## `mcpMode` (type: `string`):

perPost: one message or record per product. summary: a single digest of the whole run.

## `mcpTarget` (type: `string`):

Where to write — the destination ID the tool needs: a Notion database/page ID, a Google Sheet ID, or a Slack channel. Leave blank for connectors that post to a default location. Advanced shapes go in Arguments JSON below.

## `mcpMessage` (type: `string`):

Template for each message. Use {{field}} placeholders from any product field — common ones: {{title}}, {{priceText}}, {{price}}, {{currency}}, {{soldCount}}, {{rating}}, {{reviewCount}}, {{market}}, {{url}}. Missing fields render empty.

## `mcpTool` (type: `string`):

Force a specific tool name on the connector (e.g. send_message, create_page, append_row). Leave empty to auto-detect the connector's write/notify tool.

## `mcpArguments` (type: `object`):

Extra/override arguments merged into each tool call as JSON — e.g. {"channel": "#tiktok-shop"} for Slack. {{field}} placeholders work inside string values too, so you can nest live data into any shape — e.g. Notion: {"properties": {"Title": {"title": \[{"text": {"content": "{{title}}"}}]}, "Link": {"url": "{{url}}"}}}.

## `mcpMaxItems` (type: `integer`):

Safety cap on how many products are piped to the connector per run (perPost mode). Protects against flooding the destination.

## `mcpServerUrl` (type: `string`):

Advanced/testing only. Connect directly to a raw MCP server URL, bypassing the connector above. For real use prefer a connector — your credentials then stay in Apify. When set, this overrides the connector.

## `mcpServerToken` (type: `string`):

Bearer token for the dev MCP server URL above. A token entered here IS visible to the actor at runtime — for production use an MCP Connector instead. Ignored unless the URL is set.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.tiktok.com/shop/pdp/cat-nail-clipper-by-potaroma-adjustable-sizes-built-in-file-safe-for-kittens-cats/1731578642912612516"
  ],
  "market": "us",
  "maxProductsPerSource": 50,
  "scrapeProductDetails": true,
  "searchSort": "relevance",
  "mcpMode": "perPost",
  "mcpMessage": "*{{title}}* — {{priceText}} · {{soldCount}} sold\n{{url}}",
  "mcpMaxItems": 50
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped products.

# 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 = {
    "startUrls": [
        "https://www.tiktok.com/shop/pdp/cat-nail-clipper-by-potaroma-adjustable-sizes-built-in-file-safe-for-kittens-cats/1731578642912612516"
    ],
    "market": "us",
    "maxProductsPerSource": 50,
    "scrapeProductDetails": true,
    "searchSort": "relevance",
    "mcpMode": "perPost",
    "mcpMessage": `*{{title}}* — {{priceText}} · {{soldCount}} sold
{{url}}`,
    "mcpMaxItems": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("harshmaur/tiktok-shop-scraper").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 = {
    "startUrls": ["https://www.tiktok.com/shop/pdp/cat-nail-clipper-by-potaroma-adjustable-sizes-built-in-file-safe-for-kittens-cats/1731578642912612516"],
    "market": "us",
    "maxProductsPerSource": 50,
    "scrapeProductDetails": True,
    "searchSort": "relevance",
    "mcpMode": "perPost",
    "mcpMessage": """*{{title}}* — {{priceText}} · {{soldCount}} sold
{{url}}""",
    "mcpMaxItems": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("harshmaur/tiktok-shop-scraper").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 '{
  "startUrls": [
    "https://www.tiktok.com/shop/pdp/cat-nail-clipper-by-potaroma-adjustable-sizes-built-in-file-safe-for-kittens-cats/1731578642912612516"
  ],
  "market": "us",
  "maxProductsPerSource": 50,
  "scrapeProductDetails": true,
  "searchSort": "relevance",
  "mcpMode": "perPost",
  "mcpMessage": "*{{title}}* — {{priceText}} · {{soldCount}} sold\\n{{url}}",
  "mcpMaxItems": 50
}' |
apify call harshmaur/tiktok-shop-scraper --silent --output-dataset

```

## MCP server setup

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

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/GX653K21aASltLCdT/builds/Gnw5rPhX9mVICdVVK/openapi.json
