TikTok Shop Scraper — Price, Sales, Rating by URL · $0.006/item
Pricing
from $4.20 / 1,000 detail-items
TikTok Shop Scraper — Price, Sales, Rating by URL · $0.006/item
TikTok Shop product data from product URLs: title, price, units sold, rating, reviews and shop at $0.006/item, plus a $0.01 run fee on success. Keyword search ($0.004/card) is temporarily unavailable and costs $0. Fresh US proxy session per product; failures are never charged.
Pricing
from $4.20 / 1,000 detail-items
Rating
0.0
(0)
Developer
Kyle Wang
Maintained by CommunityActor stats
0
Bookmarked
5
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
TikTok Shop Scraper — Price, Units Sold, Rating & Shop by Product URL · $0.006/item
Turn TikTok Shop product links into price, units-sold, rating and shop data — then find the exact 1688 factory behind any winner.
Status update (October 2026): keyword search is temporarily unavailable. The search engine this Actor uses to discover TikTok Shop product pages now blocks automated queries, so keyword runs end immediately as
SEARCH_UNAVAILABLEand cost $0.00. Product URL mode works normally: paste product links to get full detail rows. Keyword search will come back once a reliable discovery source is in place.
Paste up to 100 TikTok Shop product URLs and get one full detail row per product — title, price with currency, units sold, rating, review count and shop identity ($0.006/item) — plus a transparent $0.01 run fee on successful runs. No TikTok account. No login. Every product is fetched on its own fresh US proxy session. Failed, blocked and empty results are never charged, and a hard budget cap protects every run.
Keywords: TikTok Shop scraper, TikTok product search, TikTok Shop keyword search, viral products, product research, ecommerce data, sold count, social commerce, dropshipping, trend tracking, 1688 supplier lookup
📸 Have a product photo instead? Find the 1688 factory by image with the 1688 Image Search Scraper — snap a TikTok product, match its supplier.
🎯 What you can do with it
- Competitor price monitoring — feed your competitors' product links, get current price + units sold on a schedule and catch price moves early
- Sourcing in one workflow — take any winning product's photo (
imageUrl) or title into the 1688 actors below and find the exact factory behind it (the moat: nobody else ships a paired 1688 lookup) - Trend batch research — paste a batch of links collected from TikTok videos/lives and turn them into a spreadsheet of prices, sales and ratings
- Store audit at scale — up to 100 product URLs per run: your own store or a supplier's, one dataset out
- AI-agent product lookups — one API call per batch, machine-readable failure semantics, hard budget cap — built to be called by software
- Winning-product discovery by keyword (paused with keyword search — see the status note) — type a keyword like "pet grooming brush" and get the product cards going viral on TikTok Shop, relevance-ranked
⚡ Three points that matter
- Two entry points, one honest ledger — product URLs deliver full detail rows ($0.006 each); keyword search delivers
type=searchResultcards ($0.004 each; temporarily unavailable, see the status note). Fill both and they run independently in the same run, billed separately, with a per-keyword and per-URL verdict ledger. - Honest billing — you pay only for what is actually delivered, plus a transparent $0.01 run fee on runs that deliver anything. Zero-result keywords (
NO_MATCH), risk-blocked searches (SEARCH_BLOCKED), truncated cards, captcha-blocked and not-found URLs all cost $0.00. - A budget cap you control — set
maxTotalChargeUsdand billing hard-stops at your ceiling. Items beyond the cap are still delivered but marked uncharged — never silently dropped, never over-billed.
🚀 One-click examples (Tasks)
- Single product check — one product link, full detail row (cheapest trial, and the most reliable URL-mode shape)
The keyword-search Tasks (find trending products by keyword, TikTok product → 1688 supplier lookup, price scan by keyword, weekly trends monitor) are paused together with keyword search and will be republished when it returns.
🔎 Two ways to use it
1. Product URLs — full detail rows for links you already have (up to 100 per run): title, price with currency, units sold, rating, review count, shop identity, image and a data-quality marker.
{"productUrls": ["https://www.tiktok.com/view/product/1729493620818874839"],"region": "US"}
{"productUrls": ["https://shop.tiktok.com/us/pdp/crop-tops-by-automet/1729493620818874839"],"enrichShop": true}
{"productUrls": ["https://www.tiktok.com/view/product/1729493620818874839","https://www.tiktok.com/view/product/1729570313535393936"],"maxTotalChargeUsd": 0.5}
2. Keyword search — find what's going viral. (Temporarily unavailable: keywords currently end as SEARCH_UNAVAILABLE at $0; see the status note above.) Give one or more keywords; every TikTok Shop product card we find comes back as one dataset row (type=searchResult) with title, price, relevance rank and the canonical product URL.
{"searchKeywords": ["pet grooming brush"],"region": "US","maxResultsPerKeyword": 10}
{"searchKeywords": ["tiktok made me buy it", "dog vacuum brush"],"maxResultsPerKeyword": 30,"includeDetails": true}
{"searchKeywords": ["LED face mask"],"sort": "sales","maxResultsPerKeyword": 50}
Fill both in one run? They are processed independently and billed separately — the SUMMARY ledger splits the two columns.
📦 Sample output
Product URLs deliver one detail row per delivered product:
{"productId": "1729493620818874839","title": "AUTOMET Women's 3-Piece Long Sleeve Crop Tops","price": { "value": 39.99, "currency": "USD" },"soldCount": 140700,"rating": 4.8,"reviewCount": 10104,"shop": { "name": "AUTOMET", "id": null },"productUrl": "https://www.tiktok.com/view/product/1729493620818874839","imageUrl": "https://p16-oec-general-useast5.ttcdn-us.com/tos-useast5-i-…webp","region": "US","dataQuality": "FULL","scrapedAt": "2026-09-01T03:23:06.308Z"}
Fields the page doesn't expose are null — and dataQuality (FULL / PARTIAL / MINIMAL) tells you exactly how complete each row is. The SUMMARY key-value record additionally accounts for every input URL (delivered / captcha / 404 / deadline, plus INVALID_URL for non-TikTok links and INVALID_ID for obvious placeholder IDs — nothing is dropped silently) with the billing ledger attached.
Any product-link shape works: www.tiktok.com/view/product/<id>, shop.tiktok.com/view/product/<id>, regional …/pdp/<slug>/<id> links, even partner links full of tracking parameters — the numeric product ID is extracted automatically and duplicates are removed.
Keyword search (temporarily unavailable) delivers type=searchResult cards (fields the source doesn't expose are omitted, never null):
{"type": "searchResult","queryKeyword": "pet grooming brush","productId": "1729493620818874839","title": "Geoorood Dog Grooming All-in-One Kit with Vacuum Brush 2.5L","price": { "value": 5.99, "currency": "USD" },"productUrl": "https://www.tiktok.com/view/product/1729493620818874839","region": "US","similarityRank": 1,"scrapedAt": "2026-09-12T03:23:06.308Z"}
Pricing (pay-per-event)
Three events, one honest promise: failures are never charged. Every charge is itemized in the run's SUMMARY ledger.
| Event | Price | When it's charged |
|---|---|---|
search-item | $0.004 | Per delivered search card (keyword mode) — only cards actually pushed to the dataset. Keyword search is temporarily unavailable, so this event is not charged until it returns |
detail-item | $0.006 | Per delivered product row (URL mode, or includeDetails: true enrichment of a search card) |
run-base-fee | $0.01 | Once per run, at completion — only when ≥1 card/row was delivered |
Fail-not-billed, in full: zero-result keywords (NO_MATCH), risk-blocked searches (SEARCH_BLOCKED), keywords skipped while search is paused (SEARCH_UNAVAILABLE), cards truncated beyond maxResultsPerKeyword, captcha-blocked URLs, not-found URLs and invalid inputs all cost $0.00 — the per-keyword and per-URL SUMMARY ledgers show the verdict for every input.
Subscription discounts apply to the per-item events: BRONZE −10%, SILVER −20%, GOLD / PLATINUM / DIAMOND −30%. The $0.01 run fee is the same on every tier.
| Tier | search-item | detail-item | run-base-fee |
|---|---|---|---|
| FREE | $0.004 | $0.006 | $0.01 |
| BRONZE | $0.0036 | $0.0054 | $0.01 |
| SILVER | $0.0032 | $0.0048 | $0.01 |
| GOLD+ | $0.0028 | $0.0042 | $0.01 |
There is no minimum charge. Small orders bill strictly per event — one delivered product URL costs $0.016 ($0.006 + the $0.01 run fee). The platform price list's minimalMaxTotalChargeUsd ($0.04) is a budget-protection parameter, not a minimum spend. Runs that deliver zero rows/cards are never charged at all (fail-not-billed).
Worked examples (FREE tier, base fee included):
| Order | Calculation | Total |
|---|---|---|
| 1 product URL | $0.01 base + 1 × $0.006 | $0.016 |
| 10 product URLs | $0.01 base + 10 × $0.006 | $0.07 |
| 100 product URLs | $0.01 base + 100 × $0.006 | $0.61 |
| 1 search card | $0.01 base + 1 × $0.004 | $0.014 |
| 10 search cards | $0.01 base + 10 × $0.004 | $0.05 |
| 30 search cards | $0.01 base + 30 × $0.004 | $0.13 |
| 30 cards + detail enrichment | $0.01 + 30 × $0.004 + 30 × $0.006 | $0.31 |
How this compares to alternatives
| This Actor | Other TikTok Shop scrapers | Manual checking | |
|---|---|---|---|
| Entry points | Product URLs today; keyword search temporarily unavailable | Usually search only or URL only | One page at a time |
| Paired 1688 factory lookup | Yes — same-store workflow | No | You build it |
| Billing | Per delivered item; failures cost $0; hard budget cap | Per search / per item, failed searches often billed | Your hours |
| Failure honesty | Per-input verdict ledger (NO_MATCH / SEARCH_BLOCKED / CAPTCHA / …) | — | — |
Limits & caveats (read once, trust us more)
- Keyword search is temporarily unavailable. Its product-discovery source now blocks automated queries for datacenter and residential addresses alike, so keywords are not searched: each ends as
SEARCH_UNAVAILABLE($0) while product URLs in the same run are processed normally. - US-first. The captcha-free detail route is proven for US-marketplace products. Other regions (UK/ID/TH/VN/MY/PH) are accepted and labelled; if a regional page serves a captcha, the row is marked
CAPTCHAand not charged. - Search coverage follows the index (keyword search is paused — see the status note). When available, keyword search surfaces products that TikTok Shop pages have made discoverable for that term — hot, well-indexed keywords return the richest card sets; very long-tail terms can honestly return
NO_MATCH(never charged). Product-intent keywords ("pet grooming brush", "dog vacuum brush") work best. - Visible-data only. What the storefront page shows, we extract; private backend data (exact inventory, ad metrics) is not available to any scraper.
- Pacing by design. Keyword searches are spaced 6–8s per request; URL batches run 12–15s between URLs with a 30s cooldown after any CAPTCHA wall, all on rotating sessions from a dedicated US proxy pool — fast enough for research, gentle enough to stay under the radar. Batch tip: for best results, use 1–2 URLs per run; batch mode is beta — success rate decreases with batch size. If a batch marks a live-looking URL
REGION_UNAVAILABLE, retry it alone — batch-level soft blocks clear on single-URL runs ($0 either way). - Typical delivery rate is ~1 in 3 under the current CAPTCHA wall (URL mode). TikTok Shop serves an intermittent slider puzzle on the product route; our in-page solver clears most of them, but in real batch runs roughly a third of live URLs come back delivered while the rest are marked
CAPTCHA. This is disclosed on purpose: every blocked URL costs $0.00 (fail-not-billed), and the per-URL SUMMARY ledger shows the exact verdict for each link, so you only ever pay for what you receive. Paste more URLs than you strictly need, or re-run the blocked ones — you are never charged for a link we could not open.
FAQ
Do I need a TikTok account? No.
Which keywords work best? Keyword search is paused right now — every keyword ends as SEARCH_UNAVAILABLE at $0 (see the status note). When it returns, product-intent keywords ("pet grooming brush", "tiktok made me buy it") give the richest card sets, and a keyword with zero results ends as NO_MATCH at $0.
What does similarityRank mean? The relevance position of the card within the keyword's result stream — 1 is the strongest match.
Can I get full details for search results? Yes — set includeDetails: true; every card is then enriched through the full product-page pipeline and billed as detail-item on top of search-item.
What if a URL is dead or delisted? It's classified (ROUTE_404), listed in the SUMMARY ledger and never charged.
What if a page hits a captcha? Same: CAPTCHA verdict, honest ledger, no charge for that URL.
Can I schedule this? Yes — run a Task on a schedule (e.g. daily) for price/sold-count tracking; each scheduled run pays only for what it delivers.
How do I get product URLs? Collect links from TikTok video product anchors, live-shopping carts, your store backend export, or any shared product link — every shape is accepted. (Running a keyword search first will work again once keyword search returns.)
For AI agents
Built to be called by software, not just clicked by people:
- Complete output schema — every field typed and documented (input, dataset, key-value and output schemas), so tool-calling loops parse results without guesswork.
- API-first — one POST to
run-sync-get-dataset-itemsreturns the final dataset in a single call; no browser session, login or captcha step. - Agentic payments ready —
maxTotalChargeUsdsets a hard per-run budget the platform enforces, fail-not-billed (zero-delivery runs cost $0), machine-readable per-input verdict semantics in SUMMARY (keywords:OK/NO_MATCH/SEARCH_BLOCKED/SEARCH_UNAVAILABLE/INVALID_KEYWORD/DEADLINE; URLs:OK/CAPTCHA/ROUTE_404/PARSE_EMPTY/RATE_LIMITED/IP_BLOCK/DEADLINE/INVALID_URL/INVALID_ID), and a machine-readable run-levelerrorCode(NO_INPUT/NO_MATCH/SEARCH_BLOCKED/SEARCH_UNAVAILABLE/CAPTCHA/ROUTE_404/PARSE_EMPTY/PARTIAL_DEADLINE). Safe to hand an autonomous agent a budget and let it decide.
Copy to your AI assistant
Use the Apify Actor crawleast/tiktok-shop-product-scraper to fetch TikTokShop product details from product URLs. POST this JSON tohttps://api.apify.com/v2/acts/crawleast~tiktok-shop-product-scraper/run-sync-get-dataset-items?token=<APIFY_TOKEN>body: {"productUrls": ["https://www.tiktok.com/view/product/1729493620818874839"],"region": "US", "maxTotalChargeUsd": 2}.Each dataset row is one product with title, price, soldCount, rating,reviewCount, shop, imageUrl and productUrl; dataQuality says how completethe row is. Keyword search (searchKeywords) is temporarily unavailable andreturns SEARCH_UNAVAILABLE at $0. The SUMMARY key-value record accounts forevery input and the billing ledger. Report title, price, soldCount andrating per product.
Keyword requests sent to the same endpoint come back as SEARCH_UNAVAILABLE at $0 until keyword search returns.
For large batches (100 URLs ≈ 15 minutes), append ?timeout=1500 (seconds) to the sync endpoint or poll runs/{runId} — otherwise the gateway may return 408 while the run keeps working.
Input reference
| Field | Type | Default | Description |
|---|---|---|---|
productUrls | array of strings or a single string | — | Up to 100 TikTok Shop product URLs; any link shape, duplicates removed. A lone string is normalized to a one-item array, and single-value aliases productUrl / url are accepted too. For best results, use 1–2 URLs per run; batch mode is beta — success rate decreases with batch size (anti-bot pressure accumulates across consecutive URLs, so batches pace 12–15s per URL with a 30s cooldown after any wall). In batch runs a REGION_UNAVAILABLE verdict can also reflect a batch-level soft block — retrying that URL in its own single-URL run usually delivers it |
region | select | US | Marketplace label attached to each row (US/UK/ID/TH/VN/MY/PH) |
enrichShop | boolean | false | Best-effort shop identity from on-page signals (shop storefronts themselves are captcha-walled) |
maxTotalChargeUsd | number | 2 | Hard per-run billing ceiling; overflow delivered uncharged and declared |
searchKeywords | array of strings or a single string | — | Temporarily unavailable: keywords are not searched and end as SEARCH_UNAVAILABLE ($0). When available: keywords to search on TikTok Shop (1–64 chars each, e.g. "pet grooming brush"). Each keyword delivers up to maxResultsPerKeyword cards as type=searchResult rows ($0.004/card). Keywords over 64 chars are rejected per-entry (INVALID_KEYWORD, $0) while the rest run. Combine with productUrls — both are processed independently and billed separately. Leaving both entries empty ends the run honestly as NO_INPUT at $0 |
maxResultsPerKeyword | integer | 30 | Ceiling on search cards per keyword (1–100). Results beyond the cap are truncated and recorded in SUMMARY (truncatedItems) — truncation is never charged |
sort | select | default | Search result ordering: default (relevance position), sales, priceAsc, priceDesc. Sales/price sorts need includeDetails data; without it the relevance order is kept and noted |
includeDetails | boolean | false | Enrich every search card through the full product-page pipeline (title, price, sold count, rating, reviews, shop) — billed as detail-item ($0.006) on top of search-item |
filterByRegion | boolean | true | Labeled mode, not a strict filter: biases the keyword's TikTok search stream toward the selected region's marketplace and tags every delivered card with that region — cross-region products are not hard-excluded (product discovery itself is region-agnostic). SUMMARY discloses this explicitly as regionFilterMode: "labeled" on every search run. Turn off for the default US stream |
Related Actors
| Actor | Use it for | Then… |
|---|---|---|
| TikTok Shop Product Scraper (this one) | Price/sold/rating detail from TikTok Shop product URLs | — |
| 1688 Product Scraper | Keyword research across ANY 1688 category: factory prices, MOQ ladders, landed cost | Find the China source behind a TikTok winner |
| 1688 Image Search Scraper | Reverse image search on 1688 — find the factory from a product photo | Screenshot a TikTok product → match its supplier |
Pipeline: search a keyword with this Actor → spot the winning card → find the factory behind it with the Image Search Scraper (photo) or the Product Scraper (keyword) → validate landed cost before you source. While keyword search is unavailable, start from product links you already have.
Data is collected from publicly available pages for legal use — no login, no private data, no video/creator fields.
Reviews & changelog
Found a bug or have a wishlist? Open an Issue — a fixed bug helps you more than a one-star rating, and we answer fast.
If this run saved you time, a quick review on the Store page helps other buyers find it — 10 seconds, hugely appreciated.
Changelog
- 0.2.18 (2026-10-17) — Product URLs lead the input form. The Store's Try form, its API code samples and Apify's daily test all start from the form's prefilled values, which in 0.2.17 still opened on the paused keyword field (0.2.17 changed only the example input that API callers read). Product URLs now come first; the keyword fields sit in a separate "temporarily unavailable" section with nothing prefilled. Billing ledger: SUMMARY now books the events the platform reports as settled (
chargedCount) rather than every event requested, so it can never show a charge the platform declined at its own per-run limit. Removed the link to the retired 1688 Pet Supplies Scraper. The proxy wording in the 0.2.8 and 0.2.10 entries below is kept as written, with a correction note. Prices unchanged. - 0.2.17 (2026-10-16) — Docs-only, product URLs first. The Store title, this README's headline and the example input now lead with product-URL mode (keyword search is still paused); the API example and the copy-to-assistant prompt use a single product URL that delivers a full row, instead of a keyword that ends as
SEARCH_UNAVAILABLE. Pricing-copy corrections (prices unchanged): the $0.01 run fee is the same on every tier — the tier table had shown it discounted to $0.009/$0.008/$0.007 — and there is no $0.04 minimum charge:minimalMaxTotalChargeUsdis a budget-protection parameter, so one delivered product URL costs $0.016, not $0.04. No code changes. - 0.2.16 (2026-10-16) — Keyword search paused, honestly. The product-discovery source behind keyword search (Brave's search results page) now answers HTTP 429 to every automated request, from datacenter and residential addresses alike, so every keyword run since then delivered nothing. Keywords are no longer sent anywhere: each ends at once as
SEARCH_UNAVAILABLE($0, listed in the SUMMARY ledger, with a run status message), and product URLs in the same run are processed normally. The keyword-search Tasks are unpublished until search returns. Correction: earlier versions of this README described the proxy as residential; it is a dedicated US datacenter proxy pool, and the copy now says so. Also, runs that did not name a build had been served an old 0.1.x build; the Actor's default build is nowlatest. - 0.2.15 (2026-09-16) — Docs-only. Every one-click Task link in this README was dead: three tasks had never been created and five existed but were private, so all eight links led nowhere. The list is now five live tasks, all keyword-mode plus the single-URL check. The URL-batch tasks (10/30/100 URLs) stay unpublished on purpose — this README discloses that batch mode is beta with roughly 1-in-3 delivery, so promoting a 100-URL batch as a one-click starting point would contradict our own guidance. Also added a cross-link to the 1688 Image Search Scraper for readers who have a product photo rather than a link, and the comparison table now describes capability differences instead of naming rival Actors. No code changes.
- 0.2.14 (2026-09-14) — Docs-only: disclosed the batch soft-block nuance found in self-test (runs
ZScq9uL0z5FAbNDHz/sjw6Oxi4BQYssRLFF): a URL that delivers FULL in its own run can come backREGION_UNAVAILABLEinside a batch — TikTok's batch-level soft block serves the same empty shells a dead-region id gets, and no in-page signal separates the two. README and theproductUrlsinput description now tell batch users to retry such URLs in a single-URL run (both verdicts stay $0.00). No code changes. - 0.2.13 (2026-09-14) — Soft-shell rotation (self-test run
0lz3il5aKhpfWq6ED): after a solved wall, TikTok can serve a content-less-but-not-blank 200 shell — a hydration blob and footer text with NO product data and NO refusal phrase. 0.2.12 rotated only on fully-blank shells, so dead-region ids died asPARSE_EMPTYafter a single session (and the region-shell hit sometimes captured on session 1 was forgotten). APARSE_EMPTYverdict now rotates through the same 3-session budget: soft-blocked LIVE products get fresh exit IPs (batch delivery-rate recovery), while an id that stays empty through ALL sessions escalates fromPARSE_EMPTYtoREGION_UNAVAILABLE($0).includeDetailsenrichment rotates on soft shells too. Worst-case batch runtime grows accordingly (each empty URL now spends up to 3 sessions ≈ +2 min/URL) — still well inside the default 3600s timeout; failed URLs stay $0.00. - 0.2.12 (2026-09-14) — Blank-shell rotation (self-test evidence, runs
WgY3ZteeugTpsGBQk/xIotlq8OiY8xU7DBh): a solved wall on a dead-region URL serves a completely EMPTY 200 shell — no hydration, no refusal text (the refusal phrase only appears on the no-wall SSR path), so 0.2.11 still classified those idsPARSE_EMPTYon a single session. An empty shell is now a burn signal too — it is genuinely ambiguous (dead ids stay blank forever; live soft-blocked products recover on a fresh exit IP), so the URL rotates through the same 3-session budget: a live product gets fresh chances, while an id that stays blank through ALL sessions escalates honestly fromPARSE_EMPTYtoREGION_UNAVAILABLE($0). A single-observation blank (no rotations spent) keeps the legacyPARSE_EMPTYverdict. Region-refusal shells keep their own, stronger burn path — never double-counted as blank. Search channel unchanged. - 0.2.11 (2026-09-14) — Dead-URL region detection + batch pacing (guardkeeper round-3 evidence, runs
7AMuQC8LX8lhzsuXS/KcaHxoHcUNc2ukB5F/XQhRP9mDKb9syEhpM): (1) D-3 fix — region-refusal dead URLs all collapsed toPARSE_EMPTYin 0.2.10 because the refusal text was matched only against renderedinnerText, which appears only after client hydration (the SSR markup carries the refusal earlier); the refusal is now matched against BOTH the rendered text and the raw SSR markup, a solved wall buys the page a 3s settle plus one bounded re-harvest before classification, andPARSE_EMPTYcarries an internal sub-classification — a subjectless refusal phrase ("Not available in this country or region") flips it toREGION_UNAVAILABLE($0, and a hint can never mislabel a page that has real product content). (2) D-6 batch pacing — URL batches (andincludeDetailsenrichment) now space 12–15s per URL (up from 6–8s) and any wall hit on a URL buys the next one a 30s cooldown; evidence: the SAME URL delivered FULL in a 2-URL batch but died in a 3-URL batch. Worst-case cost for a fully-walled 3-URL batch is ≈+3 min, well inside the default timeout. Keyword-search pacing stays 6–8s — search channel unchanged. For best results, use 1–2 URLs per run; batch mode is beta — success rate decreases with batch size. - 0.2.10 (2026-09-14) — Region-shell rotation (evidence-driven, run vEJBYFiAVrULNi1oF): the SAME live product serves
REGION_UNAVAILABLEon one residential exit IP and a FULL product page on another — TikTok geo-misjudges part of the proxy pool. The region shell is now a burn signal too: the URL retries on fresh one-shot sessions (same 3-session budget), so IP-geo misjudgments get a chance to clear while truly dead ids still land on the honestREGION_UNAVAILABLEverdict ($0).includeDetailsenrichment now uses the exact same burn-driven rotation (and theregionUnavailableclassification) as the URL loop — previously it had a single CAPTCHA-only retry, which is why 4/5 cards failed to enrich; rotations are counted in SUMMARYsessionRotationsfor both channels. (Correction, 0.2.16: the proxy pool is a dedicated US datacenter pool, not residential.) - 0.2.9 (2026-09-14) — 0.2.8 hotfix (found in self-test, never shipped to buyers): (1) post-solve transition wait — after TikTok's verifyV2 endpoint confirms a solve (code 200), the page redirects via JS routing, so harvesting immediately read the stale Security-Check shell and misjudged cleared walls as CAPTCHA (burning the rotation budget for nothing); the page is now polled until it actually leaves the captcha shell; (2) SUMMARY crash —
sessionRotationswas declared inside the URL loop's scope but read after it, FATALing pure-URL runs before OUTPUT was written. Search channel unaffected. - 0.2.8 (2026-09-14) — URL-channel wall hardening. D-1: a CAPTCHA only counts as solved when TikTok's own verifyV2 endpoint confirms it —
captchaSolvedis now a 3-state enum (verifyv2_ok/verifyv2_fail/dom_fallback), so a wall is never reported as "solved" again. D-2: every URL runs on one-shot random residential sessions with burn-driven rotation (verifyV2 reject / webid 503×3 / unsolved CAPTCHA), up to 3 sessions per URL before failing honestly asSESSION_ROTATION_EXHAUSTED($0); SUMMARY reports the run-widesessionRotationscount. D-3: "Product not available in this country or region" pages are classifiedREGION_UNAVAILABLE($0,totals.regionUnavailable) instead of CAPTCHA — dead-region ids get a truthful verdict. D-4:includeDetailsenrichment inherits the same fixes; when cards fail to enrich, SUMMARY warnsenrichment_channel_degradedand the keyword ledger flagsenrichmentDegraded: true. D-5: SUMMARY disclosesregionFilterMode: "labeled"(seefilterByRegionabove). Search-channel behavior is byte-identical to 0.2.7; fail-not-billed untouched. (Correction, 0.2.16: the proxy pool is a dedicated US datacenter pool, not residential.) - 0.2.7 (2026-09-12) — Truncation honesty fix: SUMMARY's
truncatedItemsnow counts the real SERP hits beyondmaxResultsPerKeyword(Brave serves ~20/keyword; at the 0.2.6 build the count was always 0 because discovery pre-truncated to the cap). - 0.2.6 (2026-09-12) — Discovery engine switch DDG → Brave Search: DDG's HTML endpoints began 403-walling every proxy exit (cloud-verified), while Brave serves the same
site:tiktok.com/view/productquery wall-free with clean listing titles — search cards are back to delivering.filterByRegionnow biases the TikTok video stream's region params (US default unchanged, byte-identical). No input/output/price changes. - 0.2.5 (2026-09-12) — Keyword-search mode:
searchKeywords→type=searchResultcards at $0.004/card (relevance-ranked, optionalincludeDetailsenrichment at $0.006/card),maxResultsPerKeyword1–100 with free truncation,sort(default/sales/priceAsc/priceDesc),filterByRegion; new failure semanticsNO_MATCH/SEARCH_BLOCKED/INVALID_KEYWORD; dataset schema anyOf (detail + search rows, 1688 monitor-mode pattern);search-itempricing event registered. URL mode byte-identical (zero-regression). - 0.1.0 (2026-09-01) — Narrow-gate v1: productUrls direct-detail scraper (up to 100/run), www-domain SSR channel (proven captcha-free), 13-field rows with dataQuality markers, per-URL honest ledger, $0.006/item + $0.01 run base fee on success, hard budget cap. Keyword search deferred to v1.5.
Roadmap / post-launch backlog (tracked here for transparency — not yet shipped):
- Bring keyword search back on a reliable product-discovery source; until then keywords are skipped at $0.
- Raise the delivery rate above the ~1-in-3 CAPTCHA baseline. Both queued follow-ups landed in 0.2.8: (1) solver hardening — a solve only counts when TikTok's verifyV2 endpoint confirms it (
captchaSolved: "verifyv2_ok"; DOM transients are demoted todom_fallback), and (2) automatic session rotation — wall-hit URLs retry on fresh one-shot proxy sessions (up to 3 per URL) before failing honestly asSESSION_ROTATION_EXHAUSTED($0). Blocked URLs stay $0.00 and fully auditable in the ledger.