TikTok Shop Scraper - Products, Prices, Sales & Reviews
Pricing
from $2.30 / 1,000 listing results
TikTok Shop Scraper - Products, Prices, Sales & Reviews
Scrape TikTok Shop by keyword, category or product URL. Extract prices, discounts, sales, ratings, images, shops, variants and reviews. Optional details include descriptions and rating breakdowns. Supports incremental monitoring.
Pricing
from $2.30 / 1,000 listing results
Rating
5.0
(1)
Developer
Abot API
Maintained by CommunityActor stats
2
Bookmarked
3
Total users
1
Monthly active users
11 days ago
Last modified
Categories
Features
Share
TikTok Shop Scraper: Products, Prices, Sales & Reviews
TikTok Shop Scraper turns the TikTok Shop US storefront into structured product data. Scrape a category with all its subcategories, walk the whole store, search by keyword, or paste product links. Every product comes back as one flat record with price, original price and discount, sold count, rating and review count, images, shop and category, plus, with details on, the full description, variations, rating breakdown, seller stats and recent reviews. Export to JSON, CSV or Excel, or read the results through the API.
Why This Scraper?
- Whole categories, not a first page. Point it at any category and it walks every subcategory to its end, or pick the whole-store mode to cover every category.
- Four ways in. Category with subcategories, whole store, keyword search, or pasted product links.
- Full product detail on request. Description, variations, rating breakdown, seller rating and followers, and recent reviews with photos.
- Category path on every record. Each product carries the category trail it was found under.
- Incremental monitoring built in. Schedule it and get only new and changed products, unchanged ones are not billed.
- Streams as it goes. Results are saved category by category, so a long run keeps everything it collected.
Use Cases
- Ecommerce analysts: track prices, discounts and sold counts across TikTok Shop categories on a schedule.
- Sellers and brands: monitor competitor catalogs, ratings and review volume in your niche.
- Market researchers: map a whole category tree or the full store with structured, comparable records.
- Deal and arbitrage teams: watch categories for new discounted products.
- Product sourcing teams: find fast sellers by sold count and rating before they trend elsewhere.
Data You Get
Sample shape: values are illustrative placeholders, not from a live record.
| Field | Example |
|---|---|
productId | "1730000000000000001" |
title | "Example Phone Stand, Adjustable" |
url | "https://shop.tiktok.com/us/pdp/example-phone-stand/1730000000000000001" |
price, currency, originalPrice, discountPercent | 13.99, "USD", and the list price and percentage when discounted |
soldCount, reviewCount | 3500, 1208 |
rating | 4.6 (empty when the product has no ratings yet) |
images, brand | image links and the brand when listed |
shopName, shopId | "Example Store", "7490000000000000001" |
categoryPath | ["Phones & Electronics", "Mobile Phone Accessories", "Phone Holders & Mounts"] |
description | full product description text (with details) |
variations | [{"name": "Color", "options": ["Black", "White"]}] (with details) |
ratingHistogram, available | star breakdown {"5": 412, "4": 88, ...} and true when on sale and in stock (with details) |
sellerRating, sellerProductCount, sellerFollowers | 4.7, 120, 15400 (with details) |
reviews | recent reviews: rating, date, text, photos, verified purchase (with details) |
initial_price, final_price | list and sale price of the cheapest option (with details) |
initial_price_low, initial_price_high, final_price_low, final_price_high | price range across all options (with details) |
colors, sizes, shipping_fee | option values from the Color and Size choices; standard shipping fee, 0 when free (with details) |
specifications | [{"name": "Material", "value": "Silicone"}] (with details) |
videos | product video links (with details; links expire, so they never trigger an update in Incremental mode) |
category, category_url, domain | product category name, its TikTok Shop page and "shop.tiktok.com" (with details) |
store_details | {"name", "id", "url", "rating", "soldCount", "followers", "productCount", "reviewCount", "region"} (with details) |
id, sold, reviews_count, discount_percent | the same values as productId, soldCount, reviewCount, discountPercent, for users moving from other TikTok Shop scrapers |
searchMode, resultSource, scrapedAt | "browse", "search" or "product"; "search" or "recommended" (search mode); "2026-10-02T04:30:00Z" |
Products already stored by an earlier Incremental run pick up the new detail fields once without being counted as updated.
When Incremental mode is on, records also carry changeType, changedFields, firstSeenAt and lastSeenAt.
How to Use
- Pick a mode:
category(a category and all its subcategories, the default),all(every category in the store),search(keywords) orproduct(pasted product links). - Fill in Category links, Search keywords or Product links for that mode. Whole-store mode needs no input.
- Set Max listings and turn Fetch product details on or off.
- Click Start, then download the dataset as JSON, CSV or Excel.
Scrape a category with all its subcategories:
{"mode": "category","categoryUrls": ["https://shop.tiktok.com/us/c/mobile-phone-accessories/909064"],"maxItems": 500}
Walk the whole store:
{"mode": "all","maxItems": 5000,"fetchDetails": false}
Search by keyword:
{"mode": "search","queries": ["phone case", "magsafe case", "iphone 17 case"],"maxItems": 75}
Paste product links:
{"mode": "product","productUrls": ["https://shop.tiktok.com/us/pdp/cosrx/1731369897578565803"]}
Link shapes you can paste
Every link is routed by its shape, whichever of the two link fields it is in.
| Link shape | Example | What happens |
|---|---|---|
| Category page | https://shop.tiktok.com/us/c/cases-screen-protectors-stickers/601925 | Scraped with its subcategories (or only the page if subcategories are off). |
| Another parent category | https://shop.tiktok.com/us/c/audio-video/909320 | Same as above. |
| Category page N | https://shop.tiktok.com/us/c/cases-screen-protectors-stickers/601925?page=2 | Starts at that page; the scan counts as partial, so incremental mode never marks the skipped products as expired. |
| Product page | https://shop.tiktok.com/us/pdp/cosrx/1731369897578565803 | One product. |
| Product page, id only | https://shop.tiktok.com/us/pdp/1732417051041435718 | TikTok Shop redirects to the full link; one product. |
| Product page with tracking parameters | https://shop.tiktok.com/us/pdp/1731845743813890854?utm_source=x&sku_id=1 | Tracking and sku parameters are dropped; one product. |
| Alternate host (view link) | https://www.tiktok.com/view/product/1729407118584156350 | TikTok redirects to the shop host; one product. |
| Alternate host | https://www.tiktok.com/shop/pdp/cosrx/1731369897578565803 | Same product, read from the shop host. |
| Shared product link | https://shop.tiktok.com/view/product/1732406648548856677?region=US&locale=en | One product, opened exactly as pasted. |
| Keyword search page | https://shop.tiktok.com/us/s?q=phone+case | Same as a keyword in search mode (top 25-40 results). The page and sort parameters are ignored by TikTok Shop. |
Other links (a category number without a name, the store home page, other countries' search pages, store and creator pages) are not supported: each one is skipped with a warning in the run log naming the link.
Behaviour change: the two link fields now carry example links by default. Each mode reads only its own field: category mode reads Category links, product mode reads Product links, so the examples in one field never run in the other mode. With the field left untouched, the run scrapes the example links (capped by Max listings) instead of failing on an empty field. Clear the field and paste your own links to scrape only those. A product link pasted into Category links is read in full, as a product link always is, whatever Fetch product details is set to. A category link pasted into Product links is walked like a category link, and its listings follow your Fetch product details choice. Each product row keeps the link exactly as you pasted it in its url field.
Run it from your code
from apify_client import ApifyClientclient = ApifyClient("YOUR_API_TOKEN")run = client.actor("abotapi/tiktok-shop-scraper").call(run_input={"mode": "category","categoryUrls": ["https://shop.tiktok.com/us/c/cases-screen-protectors-stickers/601925"],"maxItems": 20,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_API_TOKEN' });const run = await client.actor('abotapi/tiktok-shop-scraper').call({mode: 'category',categoryUrls: ['https://shop.tiktok.com/us/c/cases-screen-protectors-stickers/601925'],maxItems: 20,});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items);
Which mode returns how much
| Mode | Best for | How many products |
|---|---|---|
category | Everything in a niche | Every subcategory is walked to its end; one subcategory typically holds about 100 products |
all | Store-wide catalog, trend research | Every category in the store; set Max listings to bound the run |
search | Quick lookups by keyword | 25-40 per keyword, TikTok Shop's own limit for visitors: the keyword's own results first, then its recommendations, marked by resultSource |
product | Known products | Exactly the links you paste |
Max listings is the run's cap across all categories, keywords and links (0 = unlimited; in whole-store mode that walks the entire store and can take many hours). Max pages is an optional extra limit on how many result pages are loaded per category (about 10-20 products each); on its own it does not cap results.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one specific interrupted run: paste its run or dataset id and this run skips every product already in that dataset, so it returns only the remaining products and you don't pay twice. - Incremental mode (
incrementalMode) is for a schedule against the same category, store walk or search. The first run returns everything asNEW; later runs return onlyNEW,UPDATED(withchangedFields) andREAPPEAREDproducts, while unchanged ones are suppressed and not billed unlessemitUnchangedis on.EXPIREDproducts (no longer found) are only produced once a run has walked every tracked category to its end, never after a cap or Resume cut it short or after a keyword search (a ranked top slice is not a full scan), and only withemitExpiredon.stateKeynames or shares the stored state; leave it empty and the actor derives one from your setup.
Send results into your apps (MCP connectors)
Optionally pipe results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
- Authorize a connector once under Apify, Settings, API & Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the
mcpConnectorsinput field. Notion gets a rich page-per-item export; other connectors get a best-effort write or a digest. - For Notion, also set
notionParentPageUrlto the page under which item pages should be created.
maxNotifyListings caps how many items are written to each connector per run; it does not affect the dataset. Leave mcpConnectors empty to skip this step entirely.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | category | category for a category and its subcategories, all for every category in the store, search for keywords, product for direct product links. |
categoryUrls | array | one example per link shape | Links for category mode, routed by shape: category pages, product pages or keyword search pages (see the URL shapes table). |
includeSubcategories | boolean | true | Category mode: walk every subcategory under a parent category. Off = only the linked page (about 80 products for a parent). |
queries | array | prefill ["phone case"] | Keywords to search (search mode). |
productUrls | array | four product link forms | Product links to scrape (product mode). |
maxItems | integer | 10 | Maximum products returned across the run. 0 = unlimited. |
maxPages | integer | 0 | Optional page limit per category; does not cap on its own. |
fetchDetails | boolean | true | Read each product's page for description, variations, rating breakdown, seller stats and reviews. |
includeReviews | boolean | true | Nest recent reviews under each product. Requires fetchDetails. |
maxReviewsPerProduct | integer | 20 | Keep at most this many reviews per product (0 to 100). |
resumeFromRunId | string | no default | Continue one specific previous run, skipping products it already collected. |
incrementalMode | boolean | false | Scheduled monitoring: return only new and changed products. |
stateKey | string | no default | Name or share a monitoring campaign's saved state. |
emitUnchanged | boolean | false | Incremental mode only: also return, and bill, unchanged products. |
emitExpired | boolean | false | Incremental mode only: also return products no longer found after a complete scan. |
ignoreFieldsForChanges | array | no default | Incremental mode only: output fields that should not mark a product as UPDATED. images is always ignored. |
proxy | object | residential, US | Connection settings. |
mcpConnectors | array | (none) | Optional: send results into apps you authorized under Integrations. Never changes the dataset. |
notionParentPageUrl | string | no default | Notion connector only: the page under which item pages are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run; does not affect the dataset. |
Output Example
Sample shape: values are illustrative placeholders, not from a live record.
{"productId": "1730000000000000001","title": "Example Phone Stand, Adjustable","url": "https://shop.tiktok.com/us/pdp/example-phone-stand/1730000000000000001","price": 13.99,"currency": "USD","originalPrice": 19.99,"discountPercent": 30,"soldCount": 3500,"rating": 4.6,"reviewCount": 1208,"ratingHistogram": {"5": 412, "4": 88, "3": 20, "2": 6, "1": 9},"images": ["https://example.com/image-1.webp"],"shopName": "Example Store","shopId": "7490000000000000001","categoryPath": ["Phones & Electronics", "Mobile Phone Accessories", "Phone Holders & Mounts"],"description": "Adjustable aluminium stand for phones and small tablets.","variations": [{"name": "Color", "options": ["Black", "Silver"]}],"sellerRating": 4.7,"sellerProductCount": 120,"sellerFollowers": 15400,"reviews": [{"reviewId": "7600000000000000001","reviewAuthor": "A**e","reviewRating": 5,"reviewDate": "2026-09-20","reviewBody": "Sturdy and easy to adjust.","reviewPhotos": [],"verifiedPurchase": true}],"searchMode": "browse","scrapedAt": "2026-10-02T04:30:00Z"}
Plan Requirement
A paid Apify plan is needed, because the run reads TikTok Shop through Apify Proxy (the default is a US residential connection, which Apify free plans do not include). Listing, category, search and product pages were also loaded in testing through a datacenter connection, so you may choose a cheaper datacenter proxy group in the proxy settings; the proxy group is your choice and your cost. Only the TikTok Shop home page shows a "Security Check" page, and the actor does not need it.
If the selected connection is unavailable to the run, it continues on a backup connection and logs: "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable." When that happens a later line reads "Served over the backup connection (the default connection was unavailable)." If no connection can load a page the run ends as failed with the reason, never as an empty success. Own proxy URLs are accepted too.
FAQ
How much does it cost?
You pay per product returned, plus a detail charge per product when product details are on, plus a small per-run start fee. The Pricing tab shows the current rates. Use Max listings to cap the cost of any run, and turn off Fetch product details for the lightest runs (product links you paste are always read in full).
Is it legal to scrape TikTok Shop?
This actor collects only publicly available marketplace data. You are responsible for how you use it: follow TikTok's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution. Reviewer names arrive masked by TikTok Shop itself.
Why did keyword search return fewer products than I asked for?
TikTok Shop shows visitors only its top 25-40 results per keyword, so that is the most any keyword can return. For more, add more specific keywords, or use category mode, which walks every subcategory to its end, or all mode for the whole store. The run log says so when a search ends early for this reason.
How many reviews do I get per product?
TikTok Shop product pages show their most recent reviews, typically the latest few rather than the full history, and that is what the actor returns under reviews, together with the aggregate rating, review count and rating breakdown. The dataset's Reviews view unwinds them to one row per review.
What is the difference between Resume and Incremental mode?
Resume continues one interrupted run from its run or dataset id and skips what it already collected. Incremental mode remembers products across scheduled runs by itself and returns only new and changed ones each time.
Can I get only new or changed products on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated and reappeared products, and unchanged ones are not billed unless you turn that on too.
Why did my run fail instead of returning an empty dataset?
A run is marked failed only when TikTok Shop could not be loaded at all on any connection (the message reads "The proxy connection was refused for this account, so no page could be read", "No results: residential proxies are unavailable on this run ... and the backup connection could not load the requested TikTok Shop pages", or "Could not load any results page (the requests failed), so nothing was collected"), when the Resume id you supplied is not a readable run or dataset from your account, or when a required input for the chosen mode is empty. Run it again shortly in the first case. A run that loads fine but finds nothing for your input completes normally with an empty dataset and a status message explaining why.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration, the Apify API or an MCP client that can run Apify actors.
๐ Want more TikTok data?
Pair this actor with these related scrapers from the same team:
| ๐งฉ TikTok Comments Scraper Scrape comments from TikTok videos using one or more video URLs or IDs. Extract comment... | ๐ฑ TikTok Profile, Hashtag, Search, Video & Trending Scraper Scrape TikTok without login. Extract profiles, bios, follower stats and videos; search by... |
| ๐ฑ Tiktok Live Recorder Record TikTok live streams to MP4 with full metadata, all stream quality URLs, and... | ๐ Etsy Scraper Scrape Etsy listings by keyword, category, or URL. Extract titles, shops, prices... |
| ๐ Depop Scraper Scrape Depop search results, listings, shops, and reviews to JSON, CSV, or Excel. Extract... | ๐งฉ Joom Scraper Scrape Joom products by keyword or URL. Extract product names, prices, discounts... |
๐ Browse all abotapi scrapers
๐ฌ Support
- ๐ Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- ๐ ๏ธ Need another site, extra fields or a private build? Email contact@abotapi.com.
- โญ Enjoying it? A quick review on the actor page helps other users find it.