# TikTok Shop Search Rank Tracker (`automation-lab/tiktok-shop-search-rank-tracker`) Actor

Track public US TikTok Shop product positions by keyword, separate organic and sponsored ranks, flag target products, and compare snapshots.

- **URL**: https://apify.com/automation-lab/tiktok-shop-search-rank-tracker.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** E-commerce
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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/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 Search Rank Tracker

Track where public products appear in US TikTok Shop search results.

This Actor captures an ordered keyword snapshot, separates organic and explicitly labeled sponsored positions, flags target products, and compares supplied previous ranks.

It is designed for scheduled monitoring, search visibility analysis, and reproducible exports—not private seller analytics or personalized buyer results.

### What does the TikTok Shop rank tracker do?

For every keyword, the Actor opens the public US TikTok Shop search experience in a mobile browser session.

It collects useful product rows from browser network responses and rendered product cards.

Each row contains both its absolute result position and its organic position.

Sponsored rows keep an absolute position but have `organicRank: null`.

You can provide product IDs or URLs to mark the products you care about.

You can also supply ranks from an earlier snapshot to calculate movement.

A positive change means the product moved up in the results.

### Who is it for?

- Ecommerce teams tracking TikTok Shop search visibility
- Brands checking whether a product appears for important keywords
- Agencies preparing recurring client rank reports
- Analysts comparing organic and sponsored result ordering
- Developers feeding search-position snapshots into dashboards
- Operations teams scheduling monitoring runs with Apify Tasks

Use this Actor when position and change are the buyer job.

For broader product research without rank-change fields, see the related TikTok Shop scraper below.

### Why use this Actor?

TikTok Shop search pages are region-sensitive and frequently return generic shells or Security Check pages to ordinary HTTP clients.

This Actor uses bounded US residential browser sessions and rotates the full IP/cookie context when a challenge is recognized.

It does not report a successful empty snapshot from a generic shell.

A keyword must produce typed public product rows or the run fails with a diagnostic error.

The default dataset is directly usable from Apify integrations, webhooks, API clients, Google Sheets workflows, and scheduled Tasks.

### Quick start

1. Open the Actor input page.
2. Enter one or more product phrases in **Search keywords**.
3. Keep **Market** set to United States.
4. Optionally paste target product IDs or public product URLs.
5. Choose the number of results per keyword.
6. Click **Start**.
7. Open the **Search ranks** dataset view.
8. Save the dataset or schedule the run for the next snapshot.

A small first input:

```json
{
  "queries": ["wireless earbuds"],
  "market": "US",
  "maxResultsPerQuery": 5
}
```

### Input parameters

#### `queries`

Required array of 1–20 non-empty product search phrases.

Duplicates are removed while preserving the supplied order.

#### `market`

TikTok Shop market for the snapshot.

The current release supports `US` only.

Other markets fail validation rather than silently returning US ranks.

#### `targetProducts`

Optional array of TikTok Shop product IDs or public product URLs.

Every value must contain a numeric product ID of at least 10 digits.

Matching rows receive `targetMatch: true`.

A target that does not appear in the captured depth simply has no matching row.

#### `previousRanks`

Optional array used to calculate movement.

Each object requires `query` and `productId`.

Add `absoluteRank`, `organicRank`, or both when those prior values are available.

The previous query match is case-insensitive.

#### `maxResultsPerQuery`

Maximum ordered products captured for each keyword.

Allowed range: 1–100.

Default: 20.

#### `maxSessionRetries`

Fresh browser/proxy sessions attempted after a challenge or empty shell.

Allowed range: 1–8.

Default: 4.

#### `proxyConfiguration`

Cloud runs default to the Apify US residential proxy group.

TikTok Shop commonly blocks direct and ordinary datacenter access.

Changing this setting can reduce reliability or produce the wrong geography.

### What data is extracted?

| Field | Meaning |
| --- | --- |
| `query` | Keyword used for this search |
| `market` | TikTok Shop market (`US`) |
| `productId` | Stable public product ID |
| `productTitle` | Product title displayed in search |
| `productUrl` | Public TikTok Shop product URL |
| `sellerName` | Public seller/shop name when exposed |
| `price` | Search-card price when exposed |
| `currency` | Displayed price currency |
| `sponsored` | Whether TikTok explicitly labeled the row as an ad |
| `absoluteRank` | Position including sponsored results |
| `organicRank` | Position among non-sponsored rows; null for an ad |
| `targetMatch` | Whether the ID matched `targetProducts` |
| `previousAbsoluteRank` | Supplied earlier absolute position |
| `absoluteRankChange` | Previous minus current absolute position |
| `previousOrganicRank` | Supplied earlier organic position |
| `organicRankChange` | Previous minus current organic position |
| `observedAt` | UTC timestamp for the snapshot |
| `searchUrl` | Public search URL used by the browser |

Missing optional values are returned as `null`, not invented.

### Output example

The following record shape comes from a current US search snapshot:

```json
{
  "query": "wireless earbuds",
  "market": "US",
  "productId": "1732500121972674708",
  "productTitle": "Wireless Bluetooth In-Ear Earphones - 3D Stereo Audio, ANC, Waterproof Headphones with Type-C Charging Cable & Charging Case, Wireless Travel Earbuds for Work, Sports, Voice Calls, Ideal Gift for Adults",
  "productUrl": "https://shop.tiktok.com/us/pdp/1732500121972674708",
  "sellerName": null,
  "price": 15.9,
  "currency": "USD",
  "sponsored": false,
  "absoluteRank": 1,
  "organicRank": 1,
  "targetMatch": false,
  "previousAbsoluteRank": null,
  "absoluteRankChange": null,
  "previousOrganicRank": null,
  "organicRankChange": null,
  "observedAt": "2026-08-03T03:08:39.703Z",
  "searchUrl": "https://www.tiktok.com/shop/s?q=wireless%20earbuds&source=ecommerce_mall&enter_method=search"
}
```

Search rankings and products change frequently, so IDs, titles, prices, and positions in later runs will differ.

### How rank changes are calculated

Pass the earlier snapshot's product IDs and ranks into `previousRanks`.

For example:

```json
{
  "queries": ["wireless earbuds"],
  "previousRanks": [
    {
      "query": "wireless earbuds",
      "productId": "1732500121972674708",
      "absoluteRank": 8,
      "organicRank": 7
    }
  ],
  "maxResultsPerQuery": 25
}
```

If the product now has absolute rank 3, `absoluteRankChange` is `5`.

Positive means moved up.

Negative means moved down.

Zero means unchanged.

Null means there was no comparable previous value in the input.

### Scheduled monitoring workflow

Create an Apify Task with stable keywords and result depth.

Schedule it hourly, daily, or weekly according to your reporting needs.

After each run, store the relevant ranks in your database or key-value workflow.

Provide those values as `previousRanks` on the next run.

Use a webhook or integration to notify your pipeline when the run succeeds.

The Actor produces monitoring-ready snapshots but does not send alerts itself.

### Organic and sponsored ranks

`absoluteRank` always follows the captured search ordering.

`organicRank` counts only rows not explicitly marked as sponsored.

TikTok can change ad labels and card shapes.

The Actor marks a row sponsored only when a recognizable explicit ad signal is present.

It does not infer sponsorship from price, seller, or position.

### How much does it cost to track TikTok Shop search ranks?

The Actor uses pay per event pricing.

A run has a one-time **$0.005 start event**.

Each saved dataset row emits one `rank-result` event.

At the BRONZE tier, the current per-row price is **$0.0099227**.

BRONZE cost calculation examples:

| Snapshot | Ranked rows | Calculation |
| --- | ---: | --- |
| One keyword × 5 results | 5 | One start event plus 5 rank-result events |
| Two keywords × 10 results | 20 | One start event plus 20 rank-result events |
| Ten keywords × 25 results | 250 | One start event plus 250 rank-result events |

Multiply the active per-row tier price by the saved row count, then add the one-time start event. Actual billed tiers depend on your Apify plan.

Rows rejected as duplicates or invalid are not charged as rank results.

Proxy, compute, and platform usage are handled according to Apify's active pricing configuration.

### Result depth and interpretation

A target outside `maxResultsPerQuery` cannot be distinguished from a target absent from the wider search results.

Increase depth when you need a stronger absence signal.

Keep the same depth across scheduled snapshots for comparable ranks.

Results are an observation of the public search surface at `observedAt`.

They are not a guarantee of what every TikTok user sees.

### API usage with cURL

Replace `YOUR_TOKEN` with an Apify API token:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~tiktok-shop-search-rank-tracker/runs?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries":["wireless earbuds"],"market":"US","maxResultsPerQuery":5}'
```

To wait for completion and return dataset items, use the synchronous dataset-items endpoint documented by Apify.

### API usage with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/tiktok-shop-search-rank-tracker').call({
  queries: ['wireless earbuds'],
  market: 'US',
  maxResultsPerQuery: 5,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API usage with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/tiktok-shop-search-rank-tracker').call(run_input={
    'queries': ['wireless earbuds'],
    'market': 'US',
    'maxResultsPerQuery': 5,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/tiktok-shop-search-rank-tracker"
```

#### Claude Desktop, Cursor, and VS Code setup

Use this equivalent MCP configuration in Claude Desktop, Cursor, or VS Code:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/tiktok-shop-search-rank-tracker"
    }
  }
}
```

Example prompts:

- “Capture the top 10 TikTok Shop ranks for wireless earbuds in the US.”
- “Check these product IDs against the lip gloss search results.”
- “Compare this previous snapshot with today's ranks and summarize products that moved up.”

### Integrations and exports

Export the default dataset as JSON, CSV, Excel, XML, or RSS from Apify.

Send finished runs to Google Sheets through an integration.

Trigger a Make or Zapier scenario from a run webhook.

Load snapshots into BigQuery, Snowflake, PostgreSQL, or a BI dashboard.

Join results by `query`, `market`, `productId`, and `observedAt`.

### Reliability and retries

The Actor keeps each proxy identity, browser context, and cookies together for one attempt.

Recognized challenge, login, regional-block, and empty-shell responses retire that context.

The next attempt receives a fresh session identity.

Retries are bounded; the Actor does not loop indefinitely.

If every route returns no useful rows, the run fails rather than emitting a misleading success record.

### Limitations

- Only the public US TikTok Shop market is currently supported.
- Results can vary by time, geography, experiments, and TikTok ranking changes.
- Account-personalized and logged-in buyer results are excluded.
- Affiliate, private seller, and seller-dashboard data are excluded.
- Sponsored detection depends on an explicit public label.
- A product below the selected result depth is not captured.
- Search-card seller and price fields can be absent and then return null.
- TikTok anti-bot changes may temporarily exhaust all session retries.
- The Actor does not retain previous snapshots automatically.
- The Actor does not send alerts; connect scheduled runs to your alerting workflow.

### Troubleshooting

#### The run says no usable product rows

Confirm the query is a real product phrase and the market is US.

Use the default residential proxy configuration.

Increase `maxSessionRetries` within the allowed range if several IPs are challenged.

Do not treat a direct or datacenter Security Check as a valid empty result.

#### My target product did not match

Check that the ID is copied from a public TikTok Shop product URL.

Increase `maxResultsPerQuery`.

Remember that a missing match means only that the target was not found within the captured depth.

#### Organic rank is null

That row was explicitly identified as sponsored.

Use `absoluteRank` to see its position in the complete returned ordering.

#### Rank change is null

No matching prior `query` and `productId` was supplied, or the comparable organic rank is unavailable for a sponsored row.

### Responsible use and legality

This Actor accesses public TikTok Shop search results without a buyer or seller account.

Use the data only for lawful purposes and in accordance with applicable terms, laws, and regulations.

Do not use it to collect private seller information, infer sensitive traits, circumvent account controls, or harass merchants.

Avoid excessive schedules and result depths.

You are responsible for deciding whether your use and retention of the data is permitted in your jurisdiction.

### Related Automation Lab Actors

- [TikTok Shop Scraper](https://apify.com/automation-lab/tiktok-shop-scraper) — broader public product and sales-intelligence fields when rank movement is not the primary job.
- [TikTok Shop Products Scraper](https://apify.com/automation-lab/tiktok-shop-products-scraper) — product-list extraction with configurable starting routes.
- [TikTok Scraper](https://apify.com/automation-lab/tiktok-scraper) — public TikTok video and creator workflows outside Shop search ranking.

### FAQ

#### Does it require TikTok login cookies?

No.

The supported workflow uses anonymous public US Shop search results.

#### Does it track every TikTok Shop market?

No.

The current release validates and supports US only.

#### Can I schedule it?

Yes.

Create an Apify Task and schedule repeated snapshots.

#### Does it store rank history?

No.

Store earlier rows in your workflow and pass selected values back through `previousRanks`.

#### Are sponsored rows charged separately?

No.

Every useful row, organic or sponsored, uses the same `rank-result` event.

#### Why did the ranking change between nearby runs?

TikTok can refresh inventory, promotions, ads, experiments, and ranking signals continuously.

Use a consistent schedule, market, proxy geography, keyword, and result depth for the most comparable snapshots.

# Actor input Schema

## `queries` (type: `array`):

TikTok Shop product-search phrases to rank, processed in the supplied order.

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

Public TikTok Shop market used for ranking. US is currently the supported market.

## `targetProducts` (type: `array`):

Optional TikTok Shop product IDs or public product URLs to flag with targetMatch in every query snapshot.

## `previousRanks` (type: `array`):

Optional prior ranks used to calculate movement. Provide query and productId plus absoluteRank and/or organicRank.

## `maxResultsPerQuery` (type: `integer`):

Maximum ordered product rows captured for each keyword.

## `maxSessionRetries` (type: `integer`):

Maximum fresh browser/proxy sessions tried per keyword when TikTok returns a challenge or empty shell.

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

Proxy settings. Cloud runs default to US residential proxy sessions because TikTok Shop blocks ordinary datacenter routes.

## Actor input object example

```json
{
  "queries": [
    "wireless earbuds"
  ],
  "market": "US",
  "targetProducts": [],
  "previousRanks": [],
  "maxResultsPerQuery": 20,
  "maxSessionRetries": 4,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# Actor output Schema

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

Open the ordered TikTok Shop product ranks, sponsored flags, target matches, and snapshot movement fields.

# 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 = {
    "queries": [
        "wireless earbuds"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/tiktok-shop-search-rank-tracker").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 = { "queries": ["wireless earbuds"] }

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/tiktok-shop-search-rank-tracker").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 '{
  "queries": [
    "wireless earbuds"
  ]
}' |
apify call automation-lab/tiktok-shop-search-rank-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/tiktok-shop-search-rank-tracker"
        }
    }
}

```

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/Fmt6h22dhM4lXuzmd/builds/SBkWG5zn6H9giiat7/openapi.json
