TikTok Shop Scraper - Search, Prices & Reviews
Pricing
Pay per event
TikTok Shop Scraper - Search, Prices & Reviews
Search TikTok Shop by keyword or browse its categories. Returns title, price, discount, brand, shop, rating with review count, units sold and promotion badges, plus the description and seller stats on product pages.
Pricing
Pay per event
Rating
0.0
(0)
Developer
SR
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
Read TikTok Shop as structured data: title, price, the pre-promotion price and discount where one is running, currency, brand, shop, rating with its review count, units sold, and the promotion badges.
Paste category or product links, or run it with nothing and it reads six of the storefront's largest categories.
What you get per product
title,url,product_id,slugprice,currency,currency_symboloriginal_price,discount_percent,saving— when a promotion is runningratingout of 5 andreview_countsold_count— units sold, which is the number most catalogues never publishbrand,seller,seller_idpromotion_labelssuch asFlash saleimage_url,sku_idfound_onandsource— which category, search or product page the row came from
Rows read from a product page carry more: the full description, the
category_path, and the seller's own numbers (seller_followers,
seller_sold_count, seller_product_count). Those come from search results and
from any product you name directly.
A product with no reviews has no rating. TikTok reports 0.0 there, which
sorts as the worst item on the page; the field comes back empty instead, with
review_count: 0 saying why.
sold_count is the field worth the run on its own. Rating tells you how a
product was received; units sold tells you whether anyone bought it. A 4.9 on
twelve reviews and a 4.5 on thirty thousand sales are different products.
An empty discount means no discount
Most products on TikTok Shop are not on promotion, and for those the storefront publishes a price and nothing else.
This Actor leaves original_price, discount_percent and saving empty on
those rows rather than copying the sale price across into the "before" column.
That copy is tempting because it makes the table look complete, and it would
give every ordinary product a 0% discount that reads, once you sort by it, as
though the product had been checked and found not to be on offer. It has not
been checked. There is simply no promotion.
The run summary reports onPromotion so you can see how much of a run carried
one. In testing that was 9 of 26.
Search by keyword
TikTok Shop publishes no search endpoint: /search, /us/search and
/us/s/term all return 404, and the storefront offers a category tree and
nothing else.
Type a keyword anyway. The matching product pages are found in a public web index, and each one is then read live from TikTok. Only the finding is second-hand: every price, rating and sold count in your results comes from TikTok at the moment of the run, which matters because a search index is weeks stale on exactly those fields.
vitamin c serum resolved to eight products with their live ratings, review
counts and units sold in under a minute.
Give a keyword and categories and it works the other way instead: the keyword filters what the categories serve, and the crawl widens automatically to six passes and one subcategory level to give the filter something to work with.
The redacted prices, which is the thing to know before you trust a column
TikTok blanks out digits in the price on some product pages. Not all of them, and there is no pattern to which:
"sale_price_decimal": "2*" redacted"sale_price_decimal": "5*" redacted"sale_price_decimal": "27.17" real
Read carelessly, "2*" becomes 2 and a twenty-nine dollar product appears in
your table at two dollars. That is not a rounding error. It is an order of
magnitude, it looks entirely plausible next to real prices, and it is wrong in
the direction that makes something look like a bargain.
So a redacted price is returned empty, with price_masked: true on the row
and pricesRedactedByTikTok in the run summary. Everything else on that product
survives: the rating, the review count, the units sold, the seller. In a
sample of eight search results, three were redacted.
Category listings are not redacted, so browsing returns prices for everything.
Re-asking is the pagination
This is the other thing worth knowing, because it is not obvious and it is where the volume comes from.
A category page shows 15 products, and ?page=2 appears to fetch the next
fifteen. It does not. ?p=2 returns "new" products too, and so does a made-up
?cursor=15, because the list is rotated per request rather than paged.
Four fetches of the identical URL returned 55 distinct products, not 15.
So Passes per category is the real control over how much of a category you see:
| passes | distinct products from one category |
|---|---|
| 1 | 15 |
| 3 | 45 |
| 4 | 60 |
Add Subcategory depth on top and one category becomes its whole first level: that same category at depth 1 returned 117 products from 21 subcategories.
Ids are enough
Paste a category link, a product link, or just the id. https://shop.tiktok.com/us/c/-/700645
serves the same page as the full slug URL, and /us/pdp/x/<id> the same as the
canonical product URL, so the slug carries no information and is ignored.
A six-to-nine digit number is read as a category, a longer one as a product. Anything shorter is refused rather than guessed at.
Leaving the input empty reads six large categories: beauty and personal care, womenswear, food and beverages, home supplies, health, and phones and electronics.
About the retries, because you will see them
The storefront is a single-page app, and asking for a page returns one of two things. Roughly three times in four you get a small shell with no products in it, at HTTP 200 with no error and nothing that looks like a refusal. The fourth time the same URL returns the full server-rendered catalogue.
So pages are simply requested again. Attempts per page defaults to 10, which
clears about 90% on the measured rate, and the run summary reports
requestsRetried and retriesPerPage so the cost of that is visible rather
than hidden.
This is worth knowing for two reasons. A run taking longer than you expect is
usually this, not a fault. And a retriesPerPage figure that climbs across
scheduled runs is the early warning that something changed, well before the
Actor starts failing.
A page that never comes through in its budget is reported by URL, with the number of attempts spent, rather than quietly dropped.
Filters and scale
- Categories or products — links or bare ids, one per line
- Maximum products — the ceiling on both time and cost, applied after duplicates are removed across pages
- Attempts per page — raise it if a run reports pages it could not read
- Market — two-letter code, which sets the storefront and the exit country. The United States storefront is the one this has been verified against.
A category page carries 15 to 21 products. Three pages and 26 distinct products took seven seconds in a run that needed no retries at all.
What people use this for
Trend spotting. sold_count next to rating and the promotion badges is
what separates a product being pushed from a product being bought. Run the same
categories daily and the movers are the rows whose sold count jumps.
Price and promotion monitoring. Because an empty discount really means no discount, a run tells you exactly which products went on offer since the last one, without having to infer it.
Competitive research. Brand and shop on every row means a category run groups directly into who is selling what, at what price, and with how much volume behind it.
Sourcing. Units sold against price is the crude but effective filter for what a category actually moves.
Notes
Prices, discounts and sold counts are live and change through the day; a run is a snapshot.
Products are read from category and product pages, so this returns what the storefront lists. Reviews are counted but not fetched: a product with 158 reviews gives you the number, not the 158 texts.
A link that is neither a product nor a category is reported by name rather than silently skipped, so a run of fifty tells you exactly which line was wrong.