# TikTok Shop Product Scraper (`axlymxp/tiktok-shop-product-scraper`) Actor

Scrape TikTok Shop US products by keyword, category, or URL — title, price, rating, sold count, seller, and images as clean JSON. Reads the real US storefront a shopper sees, with slider-captcha handling built in. Great for product research and trend spotting. Pay only for results.

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

## Pricing

from $4.00 / 1,000 dataset items

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/platform/actors/running/actors-in-store#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 Product Scraper

**Extract TikTok Shop (US) product data at scale — by keyword, category, or product URL.** This Actor reads the **real US TikTok Shop storefront** a shopper actually sees and returns clean, structured JSON: title, price, discount, rating, sold count, seller, images, and full product detail.

Unlike scrapers that call TikTok's private mobile API (which breaks every time ByteDance rotates its app request-signing), this Actor reads the storefront's server-rendered data directly — **no fragile app signing** — and includes a built-in slider-captcha solver so it keeps working when TikTok challenges a session.

> ### ⚠️ Proxy requirement — please read first
>
> The TikTok Shop **US storefront is US-geo-gated** and protected by a slider captcha. This Actor **solves the captcha automatically**, but TikTok's anti-bot **flags shared/overused residential IPs**. For reliable results you must run it through a **US residential or — best of all — mobile proxy**:
>
> - **Recommended:** a premium US **mobile** proxy (TikTok trusts mobile carrier IPs most), or a clean premium US residential proxy.
> - **Often blocked:** large shared residential pools (including Apify's default RESIDENTIAL and other shared pools) are frequently flagged by TikTok and may return few or no results.
>
> Set your proxy in **Proxy configuration** (or `proxyProvider` / bring-your-own). Because pricing is **pay-per-result**, a run that is fully blocked costs only the small start fee — you are never charged for results you don't receive.

***

### Who is this for?

| You are…                               | You use it to…                                                                   |
| -------------------------------------- | -------------------------------------------------------------------------------- |
| **Dropshippers & TikTok Shop sellers** | Find trending products before they blow up; track price and units sold over time |
| **E-commerce & brand analysts**        | Monitor a category, benchmark competitor pricing, snapshot catalogs              |
| **Agencies & market researchers**      | Build product datasets, spot demand signals, report on TikTok commerce trends    |
| **SaaS / AI developers**               | Feed a stable product JSON schema into an app, dashboard, or AI agent via MCP    |

### What you get — output fields

Each result is one product:

| Field            | Type    | Description                                                     |
| ---------------- | ------- | --------------------------------------------------------------- |
| `product_id`     | string  | TikTok Shop product ID (19-digit)                               |
| `title`          | string  | Product title                                                   |
| `url`            | string  | Product detail page URL                                         |
| `price`          | number  | Current displayed price                                         |
| `original_price` | number  | List price before discount (when shown)                         |
| `currency`       | string  | Currency code (USD for the US storefront)                       |
| `rating`         | number  | Average star rating (0–5)                                       |
| `review_count`   | integer | Number of reviews/ratings                                       |
| `sold_count`     | string  | Units-sold label, e.g. `10,000+ sold`                           |
| `seller_name`    | string  | Seller / shop name                                              |
| `seller_id`      | string  | Seller / shop ID                                                |
| `category`       | string  | Category name (when available)                                  |
| `description`    | string  | Product description (with **Fetch full product detail**)        |
| `image`          | string  | Primary image URL                                               |
| `images`         | array   | All product image URLs                                          |
| `in_stock`       | boolean | In-stock flag, when derivable                                   |
| `source_query`   | string  | Which input produced the row (`search:` / `category:` / `url:`) |
| `scraped_at`     | string  | ISO-8601 scrape timestamp                                       |

### High-value use cases

1. **Winning-product research** — search a niche (`"skincare"`, `"kitchen gadgets"`), sort by sold count, and surface fast-movers before they saturate.
2. **Price & promo monitoring** — schedule daily runs on your competitors' products and track `price` / `original_price` drift.
3. **Category intelligence** — harvest a category/mall URL to map what's selling and at what price points.
4. **Catalog enrichment** — feed a list of `productUrls` with **Fetch full product detail** on to pull seller, description, and full image sets into your PIM/CRM.
5. **Trend datasets for AI** — pipe structured rows into a vector store or spreadsheet for an LLM to analyze demand.

### Input parameters

| Field                 | Type     | Default                  | Description                                                |
| --------------------- | -------- | ------------------------ | ---------------------------------------------------------- |
| `searchQueries`       | string\[] | `[]`                     | Keywords to search (one search per keyword)                |
| `categoryUrls`        | string\[] | `[]`                     | Listing/category/mall URLs (harvested by scrolling)        |
| `productUrls`         | string\[] | `[]`                     | Product URLs or bare IDs (always fetched with full detail) |
| `maxItems`            | integer  | `100`                    | Global cap across all inputs                               |
| `maxItemsPerQuery`    | integer  | `100`                    | Cap per keyword / category                                 |
| `fetchProductDetails` | boolean  | `false`                  | Open each product page for full detail (slower, richer)    |
| `solveCaptcha`        | boolean  | `true`                   | Auto-solve the OEC slider captcha (else reload-only)       |
| `proxyProvider`       | string   | `apify`                  | `apify` (your Apify Proxy) or `massive` (shared pool)      |
| `proxyCountry`        | string   | `US`                     | Residential exit-IP country (keep `US`)                    |
| `headless`            | boolean  | `true`                   | Run the stealth browser headless                           |
| `proxyConfiguration`  | object   | Apify **RESIDENTIAL US** | Used when `proxyProvider = apify`; US IP required          |

> **A US residential (ideally mobile) proxy is required.** TikTok Shop serves the US storefront only to US IPs, and its captcha flags shared/overused residential pools — for reliable results use a **premium US residential or mobile** proxy. See the proxy note at the top.

#### Example input

```json
{
    "searchQueries": ["wireless earbuds", "skincare"],
    "maxItems": 100,
    "maxItemsPerQuery": 50,
    "fetchProductDetails": false,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US"
    }
}
```

#### Example output

```json
{
    "product_id": "1729546869661337000",
    "title": "Wireless Earbuds Bluetooth 5.3, 40H Playtime",
    "url": "https://shop.tiktok.com/view/product/1729546869661337000",
    "price": 19.99,
    "original_price": 39.99,
    "currency": "USD",
    "rating": 4.8,
    "review_count": 1203,
    "sold_count": "10,000+ sold",
    "seller_name": "Acme Audio",
    "seller_id": "740000000000",
    "category": "Electronics",
    "image": "https://p16-oec-sg.ibyteimg.com/…/main.jpg",
    "images": ["https://…/1.jpg", "https://…/2.jpg"],
    "in_stock": true,
    "source_query": "search:wireless earbuds",
    "scraped_at": "2026-07-29T12:00:00+00:00"
}
```

### Scheduling & integrations

- **Schedule** runs (hourly/daily) from the Apify Console to keep a product feed fresh.
- **Webhooks** — trigger a downstream service when a run finishes.
- **Export** to JSON, CSV, Excel, or Google Sheets; push to S3 or your DB via the Apify API/integrations (Make, Zapier).
- Every run's data is available via the **Dataset API** for programmatic pulls.

### Use it from an AI agent (MCP)

Apify Actors are callable over the **Model Context Protocol**, so assistants like Claude or ChatGPT can run this scraper as a tool. Point your MCP client at the Apify MCP server and call `tiktok-shop-product-scraper` with the same input as above — great for "find me the top-selling earbuds on TikTok Shop right now" style prompts.

### FAQ

**Do I need a proxy?** Yes — a **US residential or mobile** proxy (the storefront is US-geo-gated). Because TikTok flags shared/overused residential IPs, a **premium US residential or mobile proxy is strongly recommended** for reliable results; large shared pools may be blocked. See the proxy note at the top.

**How many products can I get per keyword?** As many as the storefront renders while scrolling, bounded by `maxItemsPerQuery` and the global `maxItems`. Very deep result sets are limited by what TikTok surfaces in the listing.

**Why do some rows have fewer fields?** List/search cards carry the headline fields (title, price, image, id). Turn on **Fetch full product detail** to also pull seller, description, category, and full image sets from each product page.

**How does it handle the captcha?** When TikTok shows the OEC "Lucifer" slider, a built-in computer-vision solver intercepts the challenge images, locates the gap, and drags the real handle so TikTok's own SDK builds the verification. It works reliably from a clean (non-flagged) US IP; from a flagged shared-pool IP the challenge may keep rejecting even a correct solve, so a clean US residential/mobile proxy matters.

**Is the data fresh?** Every field is read live from the storefront at scrape time (`scraped_at` records when).

**Is scraping TikTok Shop legal?** The Actor collects **publicly visible** product information. You are responsible for complying with TikTok's terms and applicable laws (e.g. GDPR/CCPA) and for how you use the data. No login/private data is accessed.

**A run returned zero results.** Almost always the proxy: TikTok's captcha is blocking the exit IP. Switch to a **premium US residential or mobile** proxy (shared residential pools are often flagged). The Actor rotates IPs and retries automatically, and pay-per-result means a fully-blocked run only costs the small start fee.

**Can I get reviews / seller catalogs?** Not in this Actor — it focuses on product data. Reviews and seller-catalog Actors are planned separately.

# Actor input Schema

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

Keywords to search on the TikTok Shop US storefront (one search per keyword). Example: "wireless earbuds", "skincare".

## `categoryUrls` (type: `array`):

Direct TikTok Shop listing URLs (category, mall or hashtag pages). Products are harvested by scrolling the page.

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

Direct TikTok Shop product URLs (or bare 19-digit product IDs) to fetch full detail for. These are always fetched with full product detail.

## `maxItems` (type: `integer`):

Global cap across all queries, categories and URLs. The run stops once this many products are pushed. You are billed per result.

## `maxItemsPerQuery` (type: `integer`):

Cap on products harvested from a single search keyword or category URL (before the global cap applies).

## `fetchProductDetails` (type: `boolean`):

Open each product's page for the full detail payload (seller, description, category, more images). Higher quality but slower and more captcha-exposed. Leave off for fast list scraping.

## `solveCaptcha` (type: `boolean`):

Automatically solve the TikTok Shop OEC "Lucifer" slider captcha (computer-vision gap detection) when it appears. When off, only a cheap page-reload retry is used.

## `proxyProvider` (type: `string`):

Residential/unblocker egress. 'apify' (default) uses your Apify Proxy RESIDENTIAL allocation; 'massive' uses a shared Massive pool; 'zyte' routes through the Zyte API anti-ban proxy (set the ZYTE\_API\_KEY environment variable). IMPORTANT: TikTok's captcha flags shared/overused residential IPs — for reliable results use a premium US residential/mobile proxy or the Zyte unblocker. The US storefront requires a US IP.

## `proxyCountry` (type: `string`):

Residential exit-IP country (ISO-3166 alpha-2). Keep 'US' for the US storefront.

## `headless` (type: `boolean`):

Run the stealth browser headless. Leave true for production runs on the platform.

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

The TikTok Shop US storefront is served only to US IP addresses, so US Residential proxies are used by default. A US residential IP is strongly recommended.

## Actor input object example

```json
{
  "searchQueries": [
    "wireless earbuds",
    "skincare"
  ],
  "categoryUrls": [
    "https://shop.tiktok.com/us"
  ],
  "productUrls": [
    "https://shop.tiktok.com/view/product/1729546869661337000"
  ],
  "maxItems": 100,
  "maxItemsPerQuery": 100,
  "fetchProductDetails": false,
  "solveCaptcha": true,
  "proxyProvider": "apify",
  "proxyCountry": "US",
  "headless": true,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# 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": [
        "wireless earbuds"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("axlymxp/tiktok-shop-product-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 = {
    "searchQueries": ["wireless earbuds"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("axlymxp/tiktok-shop-product-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 '{
  "searchQueries": [
    "wireless earbuds"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call axlymxp/tiktok-shop-product-scraper --silent --output-dataset

```

## MCP server setup

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