Track TikTok Shop SKU Availability and Stock Changes
Lead Scraping Automation Engineer
TL;DR:
- TikTok Shop inventory tracking belongs at the SKU level. Product-level stock and variant availability answer different questions.
- A stock event needs two valid observations. Missing fields and failed requests remain unknown instead of becoming out-of-stock records.
- The comparison key includes market context. Keep product ID, returned region, SKU ID, and option values together.
- New, unavailable, and absent SKUs are different states. A variant missing from one response should enter review rather than be marked discontinued.
- Public product snapshots are not a warehouse ledger. They do not replace seller-side committed, reserved, or fulfillment inventory.
- Free to start. New Scrapeless accounts include free credit through the Scrapeless Dashboard.
Introduction: one product can contain many availability states
A product page may be available while one size or color is not. Monitoring only the aggregate stock object hides the exact variant a buyer can select.
This tutorial expands the skus array returned by the Scrapeless TikTok Shop actor, stores one row per variant and observation, and produces out-of-stock and back-in-stock events. It also keeps missing fields, request failures, and temporarily absent SKUs out of the definitive stock-event stream.
The TikTok Shop scraper guide explains the product and SKU response layers used here.
Pipeline at a Glance
| Stage | Action | Output |
|---|---|---|
| Watch | Supply product ID and region pairs | Product watchlist |
| Fetch | Request each public product page | Raw product snapshot |
| Expand | Create one row per SKU | Variant snapshot table |
| Compare | Join each SKU to its prior valid row | Availability changes |
| Review | Separate absent and unknown records | Data-quality queue |
The pipeline reports buyer-facing product snapshot fields. It is not a complete warehouse inventory system.
Prerequisites
- A Scrapeless account and API token from the Scrapeless Dashboard
- A watchlist of known public TikTok Shop product IDs and regions
- A defined observation schedule and review policy
- A live
SCRAPELESS_API_KEYfor the API example
The collection block is a prerequisite gap because a credential and real watchlist are supplied by the reader. The normalization rules follow the documented Shop response without presenting invented live output.
Stage 1: Request a Known Product in a Fixed Region
Call scraper.tiktok.shop.page with product_id and region. The result can contain the resolved region, product-level stock, options, and skus. Each SKU can include sku_id, its option pairs, nested price data, available_quantity, in_stock, and an image URL.
Keep the returned region, even when it differs in case from the request. Region belongs in every comparison key because product availability can vary by market.
TikTok Shop's official inventory-search documentation separates product-ID and SKU-ID queries. That distinction also belongs in a public snapshot model.
Stage 2: Expand Product and SKU Inventory Separately
The product-level stock object can include a SKU count, aggregate available quantity, and an in-stock flag. These fields summarize the product response. They should not overwrite variant rows.
One normalized SKU row should contain:
| Field | Purpose |
|---|---|
collected_at |
Identifies the observation |
product_id |
Links the variant to its product |
region |
Prevents cross-market comparisons |
sku_id |
Stable variant comparison key |
option_signature |
Human-readable color, size, or other option pairs |
available_quantity |
Quantity returned for that SKU, nullable |
in_stock |
Returned availability flag, nullable |
collection_status |
Separates success from failed collection |
Do not derive in_stock = false when available_quantity is missing. Preserve both fields because the response may expose one without enough evidence to infer the other.
Start Scraping with Scrapeless
Power up your web scraping and automation workflow with Scrapeless!
Sign up today and get $5 in free credit — no credit card required.Claim your free credit now in the Scrapeless Dashboard.
Stage 3: Store Variant Snapshots in SQLite
An append-only table preserves every observed state. SQLite's CREATE TABLE documentation defines the primary-key constraint used here.
Note: The code below requires a live Scrapeless API token in
SCRAPELESS_API_KEY, plusTIKTOK_SHOP_PRODUCT_IDandTIKTOK_SHOP_REGIONsupplied by the reader.
python
import json
import os
import sqlite3
from datetime import datetime, timezone
from urllib.request import Request, urlopen
ENDPOINT = "https://api.scrapeless.com/api/v1/scraper/request"
def fetch_product(product_id, region):
payload = json.dumps({
"actor": "scraper.tiktok.shop.page",
"input": {"product_id": str(product_id), "region": region},
}).encode()
request = Request(
ENDPOINT,
data=payload,
headers={
"x-api-token": os.environ["SCRAPELESS_API_KEY"],
"content-type": "application/json",
},
method="POST",
)
with urlopen(request, timeout=60) as response:
return json.load(response)
raw = fetch_product(
os.environ["TIKTOK_SHOP_PRODUCT_ID"],
os.environ["TIKTOK_SHOP_REGION"],
)
collected_at = datetime.now(timezone.utc).isoformat()
product_id = str(raw.get("product_id") or "")
region = str(raw.get("region") or "")
database = sqlite3.connect("tiktok-shop-inventory.sqlite3")
database.execute("""
CREATE TABLE IF NOT EXISTS sku_snapshots (
collected_at TEXT NOT NULL,
product_id TEXT NOT NULL,
region TEXT NOT NULL,
sku_id TEXT NOT NULL,
option_signature TEXT,
available_quantity INTEGER,
in_stock INTEGER,
PRIMARY KEY (collected_at, product_id, region, sku_id)
)
""")
for sku in raw.get("skus") or []:
options = sku.get("options") or []
signature = " | ".join(
f"{option.get('name', '')}={option.get('value', '')}"
for option in options
)
database.execute(
"INSERT INTO sku_snapshots VALUES (?, ?, ?, ?, ?, ?, ?)",
(
collected_at, product_id, region, str(sku.get("sku_id") or ""),
signature, sku.get("available_quantity"), sku.get("in_stock"),
),
)
database.commit()
database.close()
with open("tiktok-shop-product-raw.json", "w", encoding="utf-8") as output:
json.dump(raw, output, ensure_ascii=False, indent=2)
Store identifiers as text and preserve the raw JSON next to the normalized table. This makes option-label or schema changes reviewable later.
Stage 4: Classify Stock Changes Conservatively
A valid availability event compares the same product ID, returned region, and SKU ID across two successful observations.
| Prior state | Current state | Event |
|---|---|---|
true |
false |
out_of_stock |
false |
true |
back_in_stock |
| quantity changed, flags equal | quantity change | quantity_changed |
| no prior row | present | new_sku_observed |
| present before, absent now | not returned | sku_absent_review |
| valid prior row, failed request | unknown | collection_gap |
Do not turn sku_absent_review into discontinued inventory from one observation. Product options can change, fields can be absent, and a failed request contains no valid availability evidence.
TikTok Shop documents seller-side inventory-change events with quantities such as available, committed, and campaign-locked stock in its inventory webhook specification. Those seller-side dimensions are different from the public Shop page snapshot used here.
Stage 5: Produce the Availability Report
The report should include product name, region, SKU ID, option signature, prior and current observation times, prior and current flags, prior and current quantities, and event type. Keep collection gaps in a separate quality section.
Group the output into three queues:
- Confirmed availability changes
- Newly observed or temporarily absent variants
- Missing fields and failed collections requiring review
This separation keeps an operations team from acting on a value the collector never observed.
Handle Product Data Responsibly
Collect only the product and SKU fields needed for the inventory decision. Avoid duplicating product media when storing source URLs is sufficient, and restrict access to internal watchlists or alert thresholds. The NIST Privacy Framework provides general controls for data minimization and retention.
Scrapeless provides the Shop actor through Scraping API. Review the current pricing page before setting the watchlist size and schedule.
Conclusion: preserve uncertainty in the event model
TikTok Shop inventory tracking becomes reliable when product stock and SKU availability remain separate. Compare exact variant keys across valid snapshots, preserve missing data as unknown, and route absent SKUs to review before declaring a stock event.
Ready to Track TikTok Shop Variants?
Join the Scrapeless Discord or Telegram community to discuss variant-history schemas. Create an account in the Scrapeless Dashboard when the product watchlist is ready.
FAQ
Q: What should a TikTok Shop inventory tracker monitor?
A TikTok Shop inventory tracker should preserve product-level stock and individual SKU availability as separate observations.
Q: Is a missing SKU automatically out of stock?
A missing SKU is not automatically out of stock. Mark it for review unless a valid current response explicitly establishes the unavailable state.
Q: What key identifies a comparable SKU snapshot?
Use product ID, returned region, and SKU ID. Store option labels for review without using them as the only key.
Q: Does public Shop stock equal warehouse inventory?
Public Shop stock does not equal a complete warehouse ledger. Seller-side systems can contain reserved, committed, location, and fulfillment states not exposed by the public product snapshot.
Q: Do I need to manage proxies or Shop page selectors?
The actor handles its collection surface behind the API request. The caller manages the watchlist, timestamps, storage, comparisons, and notifications.
Q: Is monitoring public TikTok Shop availability legal?
Legality depends on jurisdiction, market, purpose, access method, and applicable terms. Use public data for a permitted purpose and obtain legal advice for the intended workflow.
At Scrapeless, we only access publicly available data while strictly complying with applicable laws, regulations, and website privacy policies. The content in this blog is for demonstration purposes only and does not involve any illegal or infringing activities. We make no guarantees and disclaim all liability for the use of information from this blog or third-party links. Before engaging in any scraping activities, consult your legal advisor and review the target website's terms of service or obtain the necessary permissions.


