TikTok Discover Scraper
Pricing
$19.99/month + usage
TikTok Discover Scraper
Scrape trending topics, hashtags, sounds, and creators from TikTok Discover. Perfect for spotting trends, researching viral content, and guiding marketing or content strategy. Fast, accurate, and ideal for real-time TikTok trend intelligence.
Pricing
$19.99/month + usage
Rating
0.0
(0)
Developer
Scraper Engine
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
0
Monthly active users
2 days ago
Last modified
Categories
Share
TikTok Discover Scraper — Captions, Engagement and Creator Data
TikTok Discover Scraper turns any keyword, #hashtag, @username or TikTok search/tag/profile link into structured TikTok video rows — caption, exact play/like/share/comment/save counts, creator handle and follower count, sound metadata, hashtags, @mentions and media URLs. Every field keeps the same name and type on every run, so results load straight into a spreadsheet, a database, or an LLM pipeline with no HTML parsing. Start a run on the Actor's Apify Console page to pull TikTok's current search results for your own terms.
What is TikTok Discover Scraper?
TikTok Discover Scraper is an Apify Actor that runs TikTok's own search endpoint for every line you give it and converts each video result into a clean, typed dataset row. It requires no TikTok account, login, cookie or API key — every request is logged out, the same as a visitor searching tiktok.com without signing in. It's built for content researchers and social listening teams tracking a keyword or hashtag, marketers scouting creators in a niche, and developers or AI engineers who need TikTok search-result data as clean structured input for a pipeline or agent.
What TikTok video data is publicly available to scrape?
Everything TikTok Discover Scraper returns is visible to any logged-out visitor who runs the same search on tiktok.com — no account is required to see it.
| Data category | Publicly visible (no login) | Gated behind TikTok login |
|---|---|---|
| Video caption, ID and canonical URL | Yes | — |
| Engagement counts (plays, likes, shares, saves, comments) | Yes, as a current snapshot | Historical/time-series counts are not exposed by the search surface |
| Creator handle, nickname, avatar, verified and private-account flags | Yes | — |
| Creator follower / following / total-likes / video counts | Yes | Full follower and following lists — login required |
| Sound title, credited author, sound ID and playable URL | Yes | — |
| Video playback/download URLs and cover images | Yes (TikTok-signed, expiring) | — |
| Hashtags and @mentions parsed from the caption | Yes | — |
| A specific creator's own full video feed | Not returned by this Actor — every input line is run as a search, never opened as a profile feed | Use a profile-feed Actor instead |
| Comment thread text | Not returned by this Actor | A dedicated comments surface, separate from search |
TikTok Discover Scraper only returns publicly visible data — what any visitor sees without logging in. Nothing behind a login wall.
What data can I extract with TikTok Discover Scraper?
Each row carries the search line that produced it, the video's own identity fields, the creator and sound metadata attached to it, and the full engagement and media set TikTok's search surface exposes.
| Field | Description |
|---|---|
hashtag | The normalised search term (from startUrls) that produced this row |
count | This row's position within that search line's results (1, 2, 3 …) — not a running total across lines |
id | TikTok's numeric video ID |
text | Video caption/description |
createTime / createTimeISO | Unix timestamp and the equivalent UTC ISO-8601 timestamp |
webVideoUrl | Canonical tiktok.com/@<handle>/video/<id> link |
input | The same normalised search term as hashtag, kept for API/JSON consumers |
discoveryInfo.url / .tag / .type | The real tiktok.com/search?q= URL the row came from, the search term, and which internal path served it — search for the primary signed fetch, search-harvest when the Actor recovered rows from the search page's own in-page requests |
isAd | TikTok's own paid-content flag |
isMuted / isPinned | null when TikTok did not ship that flag for the item — never a faked false |
isSlideshow | Whether the item is a photo/slideshow post rather than a video file |
scrapedAt | ISO-8601 UTC timestamp of when the run collected the row |
👤 Creator and sound metadata
| Field | Description |
|---|---|
authorUsername / authorNickname / authorFollowers | Flat copies of the creator's handle, display name and follower count — kept as top-level columns because the dataset's default table view silently drops nested paths like authorMeta.name, so these three would otherwise render empty in the table |
authorMeta.id / .name / .nickName / .secUid | Creator's numeric ID, handle (uniqueId), display name and secUid |
authorMeta.verified / .privateAccount | Verified-badge and private-account flags; null when TikTok omits the key |
authorMeta.signature | Creator's bio text; null when the profile has none |
authorMeta.avatar | Creator avatar image URL |
authorMeta.following / .fans / .heart / .video / .digg | Following count, follower count, total likes received, video count, and likes the creator has given |
authorMeta.profileUrl | The creator's tiktok.com/@<handle> link |
musicMeta.musicName / .musicAuthor / .musicId | Sound title, sound's credited author, and TikTok's sound ID |
musicMeta.musicOriginal | Whether the sound is the creator's own original audio |
musicMeta.musicAlbum | Album name; null when the sound has none |
musicMeta.playUrl / .coverMediumUrl | Playable audio URL and sound cover image |
📊 Engagement, video and media fields
| Field | Description |
|---|---|
diggCount / shareCount / playCount / collectCount / commentCount | Likes, shares, plays, saves and comments, read from TikTok's exact statsV2 values in preference to the rounded stats values; null when TikTok omitted a counter |
mediaUrls | The video's playable URL(s) — playAddr if present, else downloadAddr |
videoMeta.height / .width / .duration | Rendition dimensions in pixels and duration in seconds |
videoMeta.coverUrl / .originalCoverUrl / .dynamicCoverUrl | Thumbnail, original-cover and animated-cover image URLs |
videoMeta.definition / .format | Quality label (e.g. 540p) and container format (e.g. mp4) |
videoMeta.playAddr / .downloadAddr | The video's playback and download addresses |
videoMeta.subtitleUrls | Auto-caption/subtitle tracks, each as { "language", "languageCode", "url", "format" }, when TikTok ships them |
videoMeta.slideshowImages | Image URLs for photo/slideshow posts; empty for ordinary videos |
mentions | @handles mentioned in the caption, each as { "userUniqueId", "userId", "secUid", "profileUrl" } |
hashtags | Every hashtag on the video, each as { "id", "name", "url" }, merged from TikTok's challenge list and the caption |
effectStickers | Effects/stickers used on the video, when TikTok's payload ships them |
🤖 Add-on: Need additional TikTok data?
If you need a specific creator's whole upload history rather than search results, pair this Actor with TikTok Profile Videos API Scraper, which pulls every video from a public profile. If your workflow is hashtag-first rather than mixed keyword/username/URL input, see TikTok Hashtag Scraper.
Why not build this yourself?
TikTok has no public, self-serve API for searching arbitrary keywords or hashtags — its search endpoint (/api/search/general/full/) is an internal, signed surface built for the web app, not third-party developers. Building and maintaining a client for it yourself means solving several problems at once: the endpoint answers HTTP 200 with a completely empty body to any plain HTTP client, even one carrying valid session cookies, because only a signature produced by the page's own patched window.fetch is accepted; a blocked or challenged session also answers HTTP 200, so status-code checks can't tell a real result from a refusal; and paging past the first page silently returns nothing unless you thread TikTok's search_id value from page one into every later request. Getting past IP-based blocking reliably also usually means paying for rotating proxies on top of the engineering time. This Actor has already absorbed that cost: its search engine was rebuilt around a warmed, signed browser session and a proxy ladder that escalates on response shape, not status code, after an earlier request-based approach measured a complete dead end on live TikTok.
How to use TikTok Discover Scraper
TikTok Discover Scraper runs entirely on the Apify platform — no separate signup or credentials beyond your Apify account.
- Open TikTok Discover Scraper on its Apify Console page and click Try for free.
- Enter one or more entries in What to scrape (
startUrls) — the only required input. Mix keywords,#hashtags,@usernamesand TikTok links freely. - Optionally set Max videos per search line (
maxItems) and expand Apify Proxy settings (proxyConfiguration) if you need to force specific proxy groups or a country up front. - Click Start and follow the run log — it reports how many video rows were pushed per search line.
- Open the Dataset tab and export your results as JSON, JSONL, CSV, Excel, HTML table, or XML.
How to scale to bulk video extraction
startUrls is an array, so a single run can hold as many search lines as you want — keywords, hashtags, usernames and URLs can all be mixed in the same list. Each line is searched independently and every row it produces carries that line's normalised term in its own hashtag and input columns, so one dataset can hold results for many different searches without mixing them up. Videos are also deduplicated across every line in the run, so the same video returned by two overlapping search terms is only pushed — and charged — once.
What can you do with TikTok video data?
- 📊 A content researcher studying a keyword uses
text,hashtagsandplayCountto see which videos TikTok's own search actually surfaces for that term this week. - 🎯 An influencer marketer scanning a niche search term uses
authorUsernameandauthorFollowersto shortlist creators already ranking there before reaching out. - 🎵 A trend or sound analyst groups rows by
musicMeta.musicIdto see which sound is carrying a search term's growth. - 📈 A brand monitoring team tracks
diggCount,shareCountandcommentCountacross every video that surfaces for their brand name or product keyword. - 🤖 An AI engineer feeds the typed rows —
text,hashtags,authorMeta— directly into a RAG pipeline or an agent tool, since every field name and type stays fixed across runs and needs no additional parsing.
How does TikTok Discover Scraper handle rate limits and blocking?
The Actor opens a headless, signed browser session, loads the matching TikTok search page to mint the ttwid/msToken trust cookies and let the signing bundle load, then issues an in-page signed fetch against TikTok's own search endpoint. By default it starts with a direct connection — no proxy — and escalates through Apify residential proxy exits in the US, then CA, BR and JP, only when a response comes back in a shape that means "not trusted": a zero-byte body, a small WAF-challenge page, or a JSON refusal with a non-zero status_code. Escalation is driven purely by that response shape, never by HTTP status, because a blocked or dead TikTok surface still answers with status 200. Once at least one row has been pushed for a search line, that line is never retried on a fresh IP, which prevents duplicate — and double-charged — rows. If every proxy tier is exhausted for a line without a usable response, the run log records it as blocked and moves on to the next line; if every line in the run comes back empty, the run itself fails instead of completing with an empty dataset.
⬇️ Input
| Parameter | Required | Type | Description | Example value |
|---|---|---|---|---|
startUrls | Yes | array of strings | One search line per entry. Accepts keywords (skincare), hashtags (#dance), usernames (charlidamelio or @charlidamelio), and TikTok links (tiktok.com/search?q=, /tag/, /@profile). A URL or handle is normalised to the bare term inside it and then searched — this Actor does not open a creator's own profile feed. | ["Cristiano Ronaldo", "football", "https://www.tiktok.com/search?q=football"] |
maxItems | No | integer, minimum 0, maximum 500, default 10 | Videos to keep per search line. 0 switches on deep mode: page as far as TikTok will serve, up to a hard stop of 200 videos per line. Deep mode is not literally unlimited — anonymous TikTok search itself runs dry after roughly 60–200 videos per term, whatever value you set. | 25 |
proxyConfiguration | No | object (proxy editor), default {"useApifyProxy": false} | Optional. Leave it closed for the automatic direct-then-residential chain described above. Expand it to force specific Apify Proxy groups or a country up front — your choice is then tried first, ahead of the automatic escalation. | {"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]} |
Example input
{"startUrls": ["skincare", "#koreanskincare", "https://www.tiktok.com/search?q=retinol"],"maxItems": 25,"proxyConfiguration": { "useApifyProxy": false }}
⬆️ Output
Every run writes one typed JSON row per video to the Actor's dataset — the same field names and types on every run, regardless of which search lines you gave it. The dataset's default table view surfaces 17 of these columns (search line, row number, video ID, caption, posted date, author handle/name/followers, plays, likes, shares, comments, saves, link, your search line and scraped-at); every field below is present in the full JSON row and can be exported as JSON, JSONL, CSV, Excel, HTML table or XML from the Dataset tab or the Apify API.
Example output
{"hashtag": "skincare","count": 1,"id": "7530214477002481000","text": "my 3-step night routine #skincare #koreanskincare","authorUsername": "glowbyana","authorNickname": "Ana","authorFollowers": 99273,"createTime": 1753000000,"createTimeISO": "2025-07-20T08:26:40Z","isAd": false,"isMuted": null,"authorMeta": {"id": "6700123456789012345","name": "glowbyana","nickName": "Ana","secUid": "MS4wLjABAAAAglowbyanaSecUid","verified": false,"signature": "skincare, decoded","avatar": "https://p16-sign.tiktokcdn-us.com/glowbyana-avatar.jpeg","privateAccount": false,"following": 412,"fans": 99273,"heart": 2410558,"video": 318,"digg": 1204,"profileUrl": "https://www.tiktok.com/@glowbyana"},"musicMeta": {"musicName": "original sound","musicAuthor": "glowbyana","musicOriginal": true,"musicAlbum": null,"playUrl": "https://sf16-ies-music.tiktokcdn.com/original-sound.mp3","coverMediumUrl": "https://p16-sign.tiktokcdn-us.com/original-sound-cover.jpeg","musicId": "7100123456789012345"},"webVideoUrl": "https://www.tiktok.com/@glowbyana/video/7530214477002481000","mediaUrls": ["https://v16-webapp-prime.tiktok.com/video/tos/useast5/glowbyana-play.mp4"],"videoMeta": {"height": 1024,"width": 576,"duration": 27,"coverUrl": "https://p16-sign.tiktokcdn-us.com/glowbyana-cover.jpeg","originalCoverUrl": "https://p16-sign.tiktokcdn-us.com/glowbyana-origcover.jpeg","dynamicCoverUrl": "https://p16-sign.tiktokcdn-us.com/glowbyana-dyncover.jpeg","definition": "540p","format": "mp4","playAddr": "https://v16-webapp-prime.tiktok.com/video/tos/useast5/glowbyana-play.mp4","downloadAddr": "https://v16-webapp-prime.tiktok.com/video/tos/useast5/glowbyana-download.mp4","subtitleUrls": [{ "language": "English", "languageCode": "eng-US", "url": "https://tiktokcdn.com/glowbyana.vtt", "format": "webvtt" }],"slideshowImages": []},"diggCount": 99273,"shareCount": 1840,"playCount": 524712,"collectCount": 18402,"commentCount": 733,"mentions": [{ "userUniqueId": "brandhandle", "userId": "6812345678901234567", "secUid": "MS4wLjABAAAAbrandhandleSecUid", "profileUrl": "https://www.tiktok.com/@brandhandle" }],"hashtags": [{ "id": "13714046", "name": "koreanskincare", "url": "https://www.tiktok.com/tag/koreanskincare" }],"effectStickers": [],"isSlideshow": false,"isPinned": false,"input": "skincare","discoveryInfo": {"url": "https://www.tiktok.com/search?q=skincare","tag": "skincare","type": "search"},"scrapedAt": "2026-07-30T09:12:44Z"}
How does it work?
TikTok Discover Scraper opens a real, headless browser session and loads the matching TikTok search page first, so the page's own signing bundle can mint the trust cookies and produce a valid request signature — the same warm-up a real browser goes through before TikTok trusts it. It then runs an in-page fetch of TikTok's own search endpoint with that signature and reads video items out of the response, threading TikTok's search_id so later pages keep returning data instead of coming back empty. If the direct signed fetch is refused, the Actor falls back to reading the same search page's own in-page requests before giving up on that attempt. Every item is passed through a dedicated parser that builds the same fixed set of fields every time. Only what TikTok's public search page shows a logged-out visitor is ever read — there is no login step and no private data is touched — and because parsing lives in its own layer, the output schema stays stable even when TikTok changes its site or app internals.
Integrations
TikTok Discover Scraper runs on the Apify platform, so it works with anything that can call the Apify API or use Apify's existing app integrations.
Calling TikTok Discover Scraper programmatically
from apify_client import ApifyClientclient = ApifyClient("<YOUR_API_TOKEN>")run = client.actor("tiktok-discover-scraper-pay-per-events").call(run_input={"startUrls": ["skincare", "#koreanskincare"],"maxItems": 25,"proxyConfiguration": {"useApifyProxy": False},})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["id"], item["playCount"])
Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request.
No-code tools (n8n, Make, Zapier)
Apify's own apps for Make and Zapier expose a "Run Actor" action — point it at tiktok-discover-scraper-pay-per-events, map your search terms into the startUrls field, and pass the run's dataset into the rest of your flow. In n8n, the community Apify node (or a plain HTTP Request node against the Apify API) can start the Actor and fetch its dataset the same way. See Apify's integrations documentation for the full list of supported apps and webhook events.
Is it legal to scrape TikTok videos?
Scraping publicly available TikTok data is generally lawful, but the creator and video data this Actor returns can qualify as personal data under regimes like GDPR and CCPA because it includes a creator's handle, display name, bio and follower counts alongside their content. TikTok Discover Scraper only collects what any logged-out visitor sees on TikTok's public search page — it uses no login and reaches no private data. If you store or process that data at scale, you are responsible for having a lawful basis to do so and for complying with TikTok's own Terms of Service. Consult legal counsel if your use case involves bulk storage of personal data.
❓ Frequently asked questions
What TikTok video fields does TikTok Discover Scraper return?
The top fields are text (caption), playCount/diggCount/shareCount/commentCount/collectCount (engagement), authorUsername and authorFollowers (creator identity and reach), and hashtags (co-occurring tags). See the field tables above for every field this Actor returns.
Does TikTok Discover Scraper require a TikTok account or login?
No. The Actor makes every request logged out and accepts no credential input of any kind — it bakes in no cookie, API key or session constant.
How many videos can I extract in one run?
As many search lines as you list in startUrls, each returning up to maxItems videos (default 10, maximum 500 per line, or up to 200 in deep mode when maxItems is 0). In practice, anonymous TikTok search itself runs dry after roughly 60–200 videos for a given term, and the Actor caps itself at 12 signed pages per search line regardless of how high maxItems is set, so raising the value further does not add rows once TikTok's own results are exhausted.
What happens if a search returns zero results?
No dataset row is pushed for that line, so no row_result charge applies to it. The run log records the reason — TikTok returning a genuinely empty result set is logged differently from the Actor being blocked on every proxy tier it tried. If every search line in the run comes back with zero rows, the whole run fails explicitly with the reasons attached, rather than completing green with an empty dataset.
Can I scrape multiple TikTok search terms at once?
Yes. Pass as many entries as you like into startUrls — keywords, hashtags, usernames and URLs can all be mixed in the same list. Each is searched independently and deduplicated against every other line in the same run, so a video that two overlapping terms both surface is only pushed once.
Does TikTok Discover Scraper work with Claude, ChatGPT and other AI agent tools?
It is not exposed through a dedicated MCP server, but it is fully callable as an HTTP endpoint through the Apify API by any agent framework that can make an API call — including custom tool definitions for Claude, ChatGPT, or a LangChain/LlamaIndex agent.
How does TikTok Discover Scraper compare to other TikTok search scrapers?
As observed on the Apify Store on 2026-07-30, clockworks' TikTok Discover Scraper documents a similar authorMeta/musicMeta/videoMeta output shape but is built around TikTok's /discover/<hashtag> page and pushes a separate error item with an errorCode field on failures such as SEARCH_QUERY_NOT_FOUND; this Actor instead runs TikTok's real /api/search/general/full/ search endpoint for every input type (keyword, hashtag, username or URL) and pushes no dataset row at all for a line that returns nothing. HypeBridge's Influencer Discovery Agent (Instagram + TikTok), also checked 2026-07-30, targets a different entity — an AI-ranked list of influencer accounts matching a natural-language brief — rather than individual TikTok videos. EasyAPI's TikTok Keywords Discovery Tool, checked the same date, returns TikTok's search-box autocomplete suggestions ({"keyword", "type", "item"}) rather than the videos a search actually surfaces.
Does TikTok Discover Scraper return data in a format LLMs can use directly?
Yes. Every row is typed, normalized JSON with consistent field names across runs — no HTML to parse and no selectors to write. Pass it directly to an LLM prompt, index it into a vector store, or feed it to an agent tool as-is.
What happens when TikTok changes its layout or anti-bot system?
The output schema is maintained to stay stable even when TikTok's site changes underneath it — this Actor's search engine has already been rebuilt once after TikTok's previous /discover/ route stopped returning genuine search results. No specific turnaround time is promised for future changes.
Can I use TikTok Discover Scraper without managing proxies or browser infrastructure?
Yes. The Actor runs its own headless, signed browser session and proxy ladder — starting with a direct connection and escalating through Apify residential proxy exits only if needed — entirely inside the Actor run. You don't configure a browser or a proxy pool yourself.
Which TikTok video fields work best for AI training data and RAG indexing?
For RAG, index text (the caption) alongside hashtags and authorMeta.signature for semantic context. For training data, playCount, diggCount, shareCount, commentCount, collectCount and createTimeISO return as consistently typed primitives across every row, making them reliable numeric and temporal features.
🔗 Related scrapers
| Scraper | What it extracts |
|---|---|
| TikTok Hashtag Scraper | TikTok videos by hashtag or keyword — captions, dates, author/follower counts, sound and full engagement set |
| TikTok Profile Videos API Scraper | Every video posted by a specific TikTok creator, from their public profile |
| Instagram Reel Virality Intelligence Scraper | Instagram Reels with engagement and virality metrics — the same video entity on a different platform |
| YouTube Channel Finder With Creator Analytics | Channel-level creator search and analytics on YouTube |
💬 Your feedback
Found a bug, or need a field this Actor doesn't return yet? Let us know by creating an issue on the Actor's Issues tab in Apify Console — technical feedback directly shapes what gets fixed and built next.