# TikTok Shop Seller Scraper (`coregent/tiktok-shop-seller-scraper`) Actor

Scrape TikTok Shop sellers from store URLs, product URLs, or keyword searches. Get seller names, IDs, store links, ratings, followers, product counts, sample products, price ranges, and a transparent benchmark score. Clean CSV/JSON for ecommerce competitor research.

- **URL**: https://apify.com/coregent/tiktok-shop-seller-scraper.md
- **Developed by:** [Delowar Munna](https://apify.com/coregent) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.50 / 1,000 seller results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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 Seller Scraper

![TikTok Shop Seller Scraper](https://raw.githubusercontent.com/coregentdevspace/tiktok-shop-seller-scraper-assets/main/thumbnail-tiktok-shop-seller-scraper.jpg)

Scrape **TikTok Shop sellers** from keyword searches, store URLs, or product URLs. Each seller becomes one clean, flat, deduplicated, CSV-ready row with a transparent, non-AI **benchmark score**. You don't need a TikTok login, cookies, or a proxy.

Most TikTok Shop actors are product-first. This one is **seller-first**: it groups products under the stores that sell them, merges duplicates, and adds a benchmark score. It's built for competitor mapping and seller discovery rather than raw product dumps.

***

### ⚡ Need a real-time API?

This Actor also powers the **[TikTok Shop API](https://rapidapi.com/coregentdevspace/api/tiktok-shop-api8)** on RapidAPI. `GET /seller` returns a TikTok Shop seller's profile and stats as JSON in a single HTTP request, with a free Basic plan and no Apify account needed.

Use the API for on-demand lookups inside your app. Use this Actor for bulk runs, schedules, datasets and integrations.

### ✨ What it does

- **Three input modes, combinable in one run:**
  - **Keywords**: searches TikTok Shop products and collects the sellers behind them. Several products from one seller become one seller row.
  - **Seller / store URLs or IDs**: looks up a specific store and samples its catalogue.
  - **Product URLs or IDs**: returns the seller behind each product.
- **Seller profile** (on by default): the store's rating, review count, total sold, follower count, listed-product count, logo, official store link and category.
- **Deduplicates** sellers across all three modes (by seller ID, then URL, then name).
- **Benchmark score** (0–100) from the metrics TikTok shows: rating, sold count, reviews, product count, verification, sample products and price range.
- **Sample products**: up to 5 product names and URLs, plus a sample price range, per seller. These come from products already fetched, so they cost no extra lookups.
- **Filters**: minimum rating, sold count and product count. Filtered sellers aren't saved and aren't charged.
- Flat, stable CSV/JSON output. If some lookups are refused, the actor still returns the sellers it found.

#### Run it with the defaults

Click **Start** without changing anything and the actor searches `portable blender` in the US marketplace. It returns **up to 10 sellers** with their profiles and sample products. Leaving every input empty runs that same sample search.

***

### 📥 Input

| Field                   | Type    | Default | Description                                                                                               |
| ----------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------- |
| `keywords`              | array   | `[]`    | Product search keywords used to discover sellers (max 50). The form is prefilled with `portable blender`. |
| `sellerUrls`            | array   | `[]`    | Store URLs (`https://shop.tiktok.com/us/store/<name>/<seller-id>`) or bare numeric seller IDs.            |
| `productUrls`           | array   | `[]`    | Product URLs (`/view/product/<id>` or `/<region>/pdp/<slug>/<id>`) or bare numeric product IDs.           |
| `region`                | string  | `"US"`  | Marketplace: `US`, `MY`, `TH`, `VN`, `PH`, `SG`.                                                          |
| `maxResults`            | integer | `10`    | Cap on saved unique seller rows across the whole run (1–5000).                                            |
| `maxProductsPerKeyword` | integer | `30`    | Search results scanned per keyword (1–500). One search page is about 30 products.                         |
| `includeSellerProfile`  | boolean | `true`  | Add rating, followers, product count, official store link and category (one lookup per seller).           |
| `includeSampleProducts` | boolean | `true`  | Add up to 5 sample products and a sample price range per seller.                                          |
| `minSellerRating`       | number  | `0`     | Drop sellers rated below this (0–5).                                                                      |
| `minSellerSoldCount`    | integer | `0`     | Drop sellers with a total sold count below this.                                                          |
| `minProductCount`       | integer | `0`     | Drop sellers with fewer listed products than this.                                                        |
| `strictFilters`         | boolean | `false` | If on, a seller missing a filtered field fails that filter.                                               |
| `deduplicate`           | boolean | `true`  | Merge the same seller found by different inputs into one row.                                             |

Seller URLs must contain the **numeric seller ID**. Handle-only links such as `shop.tiktok.com/@store-name` don't include one, so the actor skips them and logs why. You can paste the `seller_id` from any output row back in as an input.

#### Example: map the sellers behind two product searches

This is the input behind the sample output and screenshot below. It returned 20 unique sellers: 14 for `portable blender` and 6 for `wireless earbuds`.

```json
{
    "keywords": ["portable blender", "wireless earbuds"],
    "region": "US",
    "maxResults": 20,
    "maxProductsPerKeyword": 15,
    "includeSellerProfile": true,
    "includeSampleProducts": true
}
```

#### Example: top-rated sellers only

```json
{
    "keywords": ["portable blender", "wireless earbuds"],
    "region": "US",
    "maxResults": 50,
    "maxProductsPerKeyword": 90,
    "minSellerRating": 4.5
}
```

#### Example: benchmark specific stores and the sellers of specific products

```json
{
    "sellerUrls": ["https://shop.tiktok.com/us/store/jbl/7494161853719414088"],
    "productUrls": [
        "https://shop.tiktok.com/us/pdp/ultimate-portable-juicer-blender-usb-rechargeable-smart-display-leak-proof-design-compact-500ml-size/1732167577605869836"
    ],
    "region": "US"
}
```

#### Example: fastest seller list without profiles

```json
{
    "keywords": ["led strip lights"],
    "region": "MY",
    "maxResults": 100,
    "maxProductsPerKeyword": 300,
    "includeSellerProfile": false
}
```

***

### 📤 Output

One flat row per unique seller (26 fields):

| Field                   | Type    | Description                                                                  |
| ----------------------- | ------- | ---------------------------------------------------------------------------- |
| `seller_id`             | string  | TikTok Shop seller/store ID.                                                 |
| `seller_name`           | string  | Store display name.                                                          |
| `seller_url`            | string  | Store URL (TikTok's own link when the profile is fetched; tracking removed). |
| `seller_region`         | string  | Marketplace region.                                                          |
| `seller_logo_url`       | string  | Store logo URL (not downloaded).                                             |
| `seller_rating`         | number  | Store rating (profile).                                                      |
| `seller_review_count`   | integer | Store review count (profile).                                                |
| `seller_sold_count`     | integer | Store-level total sold (profile).                                            |
| `seller_product_count`  | integer | Number of listed products (profile).                                         |
| `seller_follower_count` | integer | Store follower count (profile; `null` for stores that don't show it).        |
| `seller_badges`         | string  | Store badges, comma-separated. Currently always empty (see Limitations).     |
| `seller_verified`       | boolean | An official/verified flag or badge was found. Currently always `false`.      |
| `top_category`          | string  | Most common category across the seller's sampled products.                   |
| `sample_product_names`  | string  | Up to 5 product names joined with `\|`.                                      |
| `sample_product_urls`   | string  | Up to 5 product URLs joined with `\|`.                                       |
| `sample_product_count`  | integer | Number of sampled products.                                                  |
| `lowest_sample_price`   | number  | Lowest sample price.                                                         |
| `highest_sample_price`  | number  | Highest sample price.                                                        |
| `currency`              | string  | Currency of the sample prices.                                               |
| `benchmark_score`       | integer | 0–100 transparent score.                                                     |
| `benchmark_label`       | string  | Score label (see below).                                                     |
| `reason_tags`           | string  | Comma-separated score reasons.                                               |
| `source_input_type`     | string  | `seller_url`, `product_url`, or `keyword`.                                   |
| `source_input_value`    | string  | The input that found the seller.                                             |
| `source_product_url`    | string  | The product that exposed the seller (product and keyword modes).             |
| `scraped_at`            | string  | ISO UTC timestamp.                                                           |

Metrics TikTok doesn't expose for a store come back as `null`, never as an invented `0`. Joined list fields come back as `""`. The profile fields (rating, reviews, sold count, product count, followers, logo, category) need **Include seller profile**.

#### Overview

![Overview table view](https://raw.githubusercontent.com/coregentdevspace/tiktok-shop-seller-scraper-assets/main/tiktok-shop-seller-scraper-output-overview-table-view.png)

#### Example output

A real row from the example run above (logo URL shortened):

```json
{
    "seller_id": "7494161853719414088",
    "seller_name": "JBL",
    "seller_url": "https://shop.tiktok.com/us/store/jbl/7494161853719414088",
    "seller_region": "US",
    "seller_logo_url": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-omjb5zjo8w-tx/2eae32bc80744404a8809b3fdc7e5a50~tplv-fhlh96nyum-resize-webp:300:300.webp?…",
    "seller_rating": 4.7,
    "seller_review_count": 31953,
    "seller_sold_count": 245162,
    "seller_product_count": 78,
    "seller_follower_count": 493349,
    "seller_badges": "",
    "seller_verified": false,
    "top_category": "Headphones, Earphones & Accessories",
    "sample_product_names": "JBL Vibe Buds 2, True Wireless Noise Cancelling Earbuds",
    "sample_product_urls": "https://shop.tiktok.com/us/pdp/jbl-vibe-buds-2-true-wireless-noise-cancelling-earbuds-8mm-driver/1732027908924150088",
    "sample_product_count": 1,
    "lowest_sample_price": 77.94,
    "highest_sample_price": 77.94,
    "currency": "USD",
    "benchmark_score": 75,
    "benchmark_label": "established_seller",
    "reason_tags": "high_rating, high_sales, many_reviews, price_range_available",
    "source_input_type": "keyword",
    "source_input_value": "wireless earbuds",
    "source_product_url": "https://shop.tiktok.com/us/pdp/jbl-vibe-buds-2-true-wireless-noise-cancelling-earbuds-8mm-driver/1732027908924150088",
    "scraped_at": "2026-11-02T11:58:16.865Z"
}
```

Keyword searches usually surface one or two products per seller, so `sample_product_count` is often 1 in keyword mode. Store URLs sample up to 5 products from the store's catalogue.

***

### 🏅 Benchmark score

Transparent and rule-based (no AI), scored 0–100:

- **Rating** up to 25 · **Sold count** up to 25 · **Reviews** up to 15 · **Product count** up to 15
- **Verified** +10 · **3 or more sample products** +5 · **sample price range** +5

**Labels:** `strong_seller` (80–100) · `established_seller` (60–79) · `emerging_seller` (40–59) · `small_or_limited_signal` (1–39) · `unknown` (0).

`reason_tags` explains each score, e.g. `high_rating, high_sales, many_reviews, large_catalog, verified_seller, price_range_available, limited_visible_data`. A metric TikTok doesn't show adds no points; it is never guessed.

***

### 🔍 Filtering & deduplication

- Filters run **after** the profile lookup. Filtered sellers are **not** saved and **not** charged.
- Missing values pass filters by default, so sellers aren't lost when TikTok hides a metric. Set `strictFilters: true` to make missing values fail.
- Dedup priority: `seller_id`, then normalized `seller_url`, then `seller_name` + region, then `seller_name` + input. Duplicates are merged: non-null values win, store-URL data is preferred, and samples are combined up to 5.
- The run stops looking up and saving sellers as soon as `maxResults` is reached.
- **Lookup limit with filters:** each run looks up at most **2 × `maxResults` + 20** seller profiles. With strict filters most sellers fail, and once that limit is reached the actor stops, so it can return **fewer than `maxResults` sellers**. The log says so, and `RUN_SUMMARY.skipped_by_lookup_cap` counts the sellers left unchecked. To get more matches, raise `maxResults` or loosen the filters. Without filters the limit never applies.

***

### 💰 Pricing

**Pay-per-event**, one event, `seller-result`: charged once per **valid, unique seller row saved to the dataset**. Duplicates, filtered-out sellers, invalid rows, refused lookups, sellers skipped by the lookup limit and failed inputs are never charged. A run that finds nothing costs nothing in events. See the **Pricing** tab for the live rate (this README deliberately doesn't quote figures). Your per-run spending limit is respected: the actor stops saving sellers before it would exceed it.

***

### 📊 Run summary

A `RUN_SUMMARY` record is written to the default key-value store with: `inputs_total`, `seller_urls_total`, `product_urls_total`, `keywords_total`, `successful_inputs`, `failed_inputs`, `raw_results_found`, `seller_candidates_found`, `results_saved`, `duplicates_removed`, `filtered_out`, `charged_events`, `charge_failures`, `blocked_requests`, `retry_count`, `profile_lookups`, `skipped_by_lookup_cap`, `runtime_seconds`, `region`, `scraped_at`.

***

### ⚠️ Limitations

- Markets: **US, MY, TH, VN, PH, SG**. Other TikTok Shop markets (UK, ID and others) currently return no data from the source.
- V1 doesn't crawl full seller catalogues, product reviews or media.
- TikTok Shop's store data currently carries **no badges and no official/verified flag**, so `seller_badges` is empty and `seller_verified` is `false` even for brand stores. The benchmark's verified bonus therefore doesn't apply at the moment.
- A few stores don't show a follower count, so `seller_follower_count` is `null` for them. With **Include seller profile** off, all profile fields are `null` and the rating, sold-count and product-count filters only drop sellers when `strictFilters` is on.
- Keyword search returns the products TikTok ranks for that term, and that set varies between runs. A narrow keyword can surface fewer sellers than `maxResults`.
- TikTok occasionally refuses individual lookups. The actor retries, then saves the seller with the data it already has (identity and sample products) and records the refusal in `blocked_requests`.

***

### ❓ FAQ

**Do I need a TikTok login or a proxy?** No. There are no cookies, sessions or proxy settings.

**Can I combine keywords, store URLs and product URLs?** Yes, in a single run. Store URLs are processed first (cleanest data), then product URLs, then keywords.

**Why is a seller missing some metrics?** TikTok Shop doesn't publish every store metric. Missing numbers are stored as `null`. Turn on **Include seller profile** to get rating, reviews, sold count, followers and product count.

**Why was my store URL skipped?** It had no numeric seller ID (for example a `/@handle` link). Open the store on TikTok Shop and copy a URL containing `/store/<name>/<id>`, or paste the seller ID itself.

# Actor input Schema

## `keywords` (type: `array`):

Search TikTok Shop products by keyword and collect the sellers behind them (max 50 keywords). Several products from the same seller are combined into one seller row.

## `sellerUrls` (type: `array`):

TikTok Shop store URLs (e.g. https://shop.tiktok.com/us/store/<store-name>/<seller-id>) or bare numeric seller IDs. The URL must contain the numeric seller ID; handle-only links (/@name) can't be resolved. The seller_id on any output row can be pasted back in here.

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

TikTok Shop product URLs (e.g. https://shop.tiktok.com/view/product/<id> or /<region>/pdp/<slug>/<id>) or bare numeric product IDs. The seller behind each product is returned.

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

TikTok Shop marketplace to search and look up sellers in. Only markets where the data source returns results are listed.

## `maxResults` (type: `integer`):

Cap on saved unique seller rows across all inputs. Discovery and seller lookups stop as soon as this many sellers are saved.

## `maxProductsPerKeyword` (type: `integer`):

How many search results to scan per keyword when discovering sellers. One search page holds about 30 products. Raise it to find more sellers per keyword.

## `includeSellerProfile` (type: `boolean`):

Look up each saved seller's store profile: rating, follower count, product count, official store link and category. Uses one extra lookup per unique seller. Turn off for the fastest name/ID/sample-products-only list.

## `includeSampleProducts` (type: `boolean`):

Add up to 5 sample product names and URLs plus a sample price range per seller, taken from products already fetched. No extra lookups.

## `minSellerRating` (type: `number`):

Drop sellers rated below this (0-5, e.g. 4.2). Sellers with no visible rating pass unless Strict filters is on. Needs 'Include seller profile' to see ratings.

## `minSellerSoldCount` (type: `integer`):

Drop sellers whose total sold count is below this. TikTok exposes a store-level sold count for only some sellers; those without one pass unless Strict filters is on.

## `minProductCount` (type: `integer`):

Drop sellers with fewer listed products than this. Sellers with no visible product count pass unless Strict filters is on.

## `strictFilters` (type: `boolean`):

If on, a seller missing a filtered field fails that filter. If off (default), missing values pass, so useful sellers aren't lost when TikTok hides a metric.

## `deduplicate` (type: `boolean`):

Merge the same seller found by different inputs into one row (by seller ID, then URL, then name). If off, each input keeps its own row for a seller.

## Actor input object example

```json
{
  "keywords": [
    "portable blender"
  ],
  "sellerUrls": [],
  "productUrls": [],
  "region": "US",
  "maxResults": 10,
  "maxProductsPerKeyword": 30,
  "includeSellerProfile": true,
  "includeSampleProducts": true,
  "minSellerRating": 0,
  "minSellerSoldCount": 0,
  "minProductCount": 0,
  "strictFilters": false,
  "deduplicate": true
}
```

# Actor output Schema

## `overview` (type: `string`):

No description

# 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 = {
    "keywords": [
        "portable blender"
    ],
    "region": "US",
    "maxResults": 10,
    "maxProductsPerKeyword": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("coregent/tiktok-shop-seller-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 = {
    "keywords": ["portable blender"],
    "region": "US",
    "maxResults": 10,
    "maxProductsPerKeyword": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("coregent/tiktok-shop-seller-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 '{
  "keywords": [
    "portable blender"
  ],
  "region": "US",
  "maxResults": 10,
  "maxProductsPerKeyword": 30
}' |
apify call coregent/tiktok-shop-seller-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,coregent/tiktok-shop-seller-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/UzWiyQrVlyXMVaX7D/builds/wTjqpkxWpdQKEMUsh/openapi.json
