TikTok Keyword Search Scraper
Pricing
from $4.99 / 1,000 results
TikTok Keyword Search Scraper
TikTok Keyword Search Scraper finds public TikTok posts using targeted keywords and extracts captions, creators, hashtags, views, likes, comments, shares, upload dates, and video URLs. Build structured datasets for trend research, content discovery, and competitor analysis.
Pricing
from $4.99 / 1,000 results
Rating
0.0
(0)
Developer
Scraper Engine
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
a day ago
Last modified
Categories
Share
TikTok Keyword Search Scraper โ Captions, Stats and Author Data
Search TikTok by keyword and get back every matching video as structured JSON โ caption, engagement stats (likes, plays, comments, shares), author profile, hashtags, and video/music metadata, with no login and no API key. Results stream into the dataset the moment each video is found, tagged with the query that produced it. Paste a keyword below and start a run to see it in action.
What is TikTok Keyword Search Scraper?
TikTok Keyword Search Scraper searches TikTok's public video search for one or more keywords and returns each matching video as a structured JSON record โ caption, timestamps, engagement counts, author profile, hashtags, and video/music details. It runs against TikTok's own web search page with no TikTok account, login, or API key required. It's built for developers, marketers, and researchers who need TikTok search results as clean, structured data instead of scraping HTML or reverse-engineering signed API calls themselves.
What TikTok video data is publicly available to scrape?
Everything a visitor sees on TikTok's public search results page โ without logging in โ is fetchable: video captions, engagement counts, author username and follower count, hashtags, and video/music details. TikTok gates some things behind a login instead: its sort-by and date-posted filter controls only render for a signed-in session (this is why this Actor applies both client-side, against the data itself, instead of relying on a filter TikTok never sends to anonymous requests).
| Data Category | Publicly Available (no login) | Requires TikTok Login |
|---|---|---|
| Video caption / description | Yes | โ |
| Engagement counts (likes, plays, comments, shares, saves) | Yes | โ |
| Author username, nickname, avatar, follower count | Yes | โ |
| Hashtags and @mentions on a video | Yes | โ |
| Video dimensions, duration, cover and playback URLs | Yes | โ |
| Music/sound title, artist and playback URL | Yes | โ |
| Server-side sort-by / date-posted filter controls | No | Yes (filters UI only renders for a signed-in session) |
| Private or unlisted videos | No | Never returned to an unauthorized viewer, logged in or not |
TikTok Keyword Search Scraper only returns publicly visible data โ what any visitor sees. Nothing behind a login wall.
What data can I extract with TikTok Keyword Search Scraper?
Each run returns caption and identity fields, engagement and status metrics, and author/media/hashtag detail for every matching video, reshaped into TikTok's own aweme_info field names so the keys match what TikTok's own app schema uses.
| Field Name | Description |
|---|---|
aweme_id | Unique TikTok video ID |
aweme_type | TikTok's internal content-type code; always 0 for a video hit |
group_id | Same value as aweme_id โ TikTok's internal grouping key |
desc | Video caption/description text |
desc_language | Detected caption language code, if TikTok supplies one |
is_description_translatable | Whether TikTok offers a "translate caption" control for this video |
content_type | Always "video" |
create_time | Unix timestamp the video was posted |
create_time_utc | ISO-8601 UTC timestamp the video was posted |
region | Author's region if TikTok reports one, else the region input value |
url / share_url | Canonical TikTok video URL (both keys carry the same value) |
is_ads / is_ad | Whether TikTok flags the item as an ad (both keys carry the same value) |
is_top | Always 0 โ pinned-result flag is not exposed on this endpoint |
is_paid_partnership | Always false โ branded-content flag is not exposed on this endpoint |
is_eligible_for_commission | Always false โ TikTok Shop commission flag is not exposed on this endpoint |
shop_product_url | Always null โ TikTok Shop product link is not exposed on this endpoint |
aigc_info | AI-content label object (see below) |
author | Author profile object (see below) |
music / added_sound_music_info | Sound/music object (both keys carry the same object) |
statistics | Engagement counts object (see below) |
status | Video status-flags object (see below) |
video | Video technical/media object (see below) |
text_extra | Array of hashtag/mention text spans |
cha_list | Array of hashtag objects attached to the video |
aweme_acl | Duet/stitch/share/comment permission flags |
search_query | Which input query this record came from (Actor bookkeeping, not a TikTok field) |
scraped_at | ISO timestamp the record was scraped (Actor bookkeeping, not a TikTok field) |
TikTok's native mobile app returns a much larger object per video (165+ top-level keys) than any browser-reachable endpoint can expose โ that fuller object is served by an app-only, natively-signed endpoint with no public browser equivalent. This Actor returns every field TikTok's public web search page actually carries, and nothing padded out with guessed or fabricated values.
Video identity, timing and hashtags
aweme_id, desc, desc_language, create_time, create_time_utc, region, url, search_query, scraped_at, and the hashtag/mention arrays:
| Field Name | Description |
|---|---|
text_extra[].hashtag_name / hashtag_id | Hashtag text and ID for each #tag span in the caption |
text_extra[].start / end | Character offsets of the span inside desc |
text_extra[].user_id | Tagged user's ID, for an @mention span |
text_extra[].is_commerce | Whether TikTok flags the span as commercial |
cha_list[].cid / cha_name / desc | ID, name and description of each hashtag attached to the video |
Engagement, status and content flags
| Field Name | Description |
|---|---|
statistics.digg_count | Like count |
statistics.comment_count | Comment count |
statistics.share_count | Share count |
statistics.play_count | View/play count |
statistics.collect_count | Save/bookmark count |
statistics.repost_count | Repost count |
statistics.download_count / forward_count / lose_count / lose_comment_count / whatsapp_share_count | Always null โ not exposed on this endpoint |
status.in_reviewing | Whether the video is still under TikTok's moderation review |
status.private_status | 1 if the video is marked private |
status.allow_comment / allow_share | Whether commenting/sharing is enabled |
aweme_acl.duet_enabled / stitch_enabled / share_enabled / download_enabled / comment_enabled | Per-action permission flags |
aigc_info.aigc_label_type | TikTok's AI-content moderation label code, when present |
Author, video and music details
| Field Name | Description |
|---|---|
author.unique_id | Author's @username |
author.nickname | Author's display name |
author.uid / sec_uid | Author's numeric and secure user IDs |
author.follower_count / following_count / aweme_count | Follower, following and video counts |
author.total_favorited | Total likes received across the author's account |
author.verification_type | 1 if the author is verified, else 0 |
author.secret | 1 if the author's account is private |
author.avatar_larger / avatar_medium / avatar_thumb | Avatar image URLs at each size |
video.height / width / ratio | Video resolution and quality tier |
video.duration | Video length in milliseconds |
video.play_addr / download_addr | Playback and download URLs |
video.cover / origin_cover / dynamic_cover | Cover-image URLs |
music.title / author / album | Sound title, artist and album |
music.is_original | Whether the sound is an original creation |
music.play_url / cover_thumb | Sound playback and cover-art URLs |
Add-on: Need additional TikTok data?
Need full profile timelines instead of a keyword search, or posts from a hashtag page? TikTok Posts Scraper covers profiles, hashtags, keyword search and pasted URLs in one Actor. Need a spoken-word transcript of the videos this Actor finds? Best TikTok AI Transcript Extractor turns TikTok videos into timestamped text with the same proxy-escalation approach used here.
Why not build this yourself?
TikTok's web search page requires three request-signing headers (X-Bogus, X-Gnarly, X-Dynosaur) that TikTok's own obfuscated JavaScript computes per request from a live browser fingerprint โ a replayed signed URL comes back HTTP 200 with an empty body rather than an error, so there's no static formula to reverse-engineer once and reuse. Building and maintaining a scraper that generates these correctly means running a real anti-detect browser, keeping up with TikTok's frontend changes, and absorbing proxy costs once TikTok starts challenging requests. This Actor already does all three: Camoufox drives the real search page, the proxy tier escalates automatically only when TikTok actually blocks a request, and the output schema stays the same even after a TikTok frontend change.
How to use TikTok Keyword Search Scraper
This Actor runs on the Apify platform โ no separate signup or SDK installation is required to try it.
- Open TikTok Keyword Search Scraper on its Apify Store listing.
- Fill in
queries(required) with one or more keywords or full TikTok search URLs. - Optionally set
datePosted,sortBy,region, ormaxResultsto narrow the results. - Click Start.
- Watch results stream into the Output tab in real time, or download the finished dataset as JSON or CSV.
How to scale to bulk video extraction
queries is an array โ paste any number of keywords or TikTok search URLs into it in one run, one per line, mixed freely; each is scraped independently and results from all of them land in the same dataset, tagged by search_query. There is no separate "bulk mode" to enable โ a one-keyword run and a hundred-keyword run use the same input field, and concurrency (default 2, max 5) controls how many of them run in parallel.
What can you do with TikTok video data?
- ๐ A trend researcher tracking a niche uses
statistics.play_countandstatistics.digg_countacross a keyword's results to spot which video formats are currently outperforming the rest. - ๐ท๏ธ A brand-safety analyst screening sponsored content uses
is_adsandaweme_acl.duet_enabledto flag ad-labeled videos that also allow duets before a partnership review. - ๐ A social listening team monitoring a competitor's keyword uses
author.unique_id,create_time_utcanddescto build a timeline of who's posting about a topic and when. - ๐ฏ A growth marketer scouting sounds uses
music.titleandmusic.authoracross top-viewed results for a keyword to find trending audio before it saturates. - ๐ค An AI engineer builds a RAG pipeline over TikTok trend data by indexing
descandtext_extra[].hashtag_nameas searchable context, withstatistics.play_countas a relevance signal an agent can reason over directly.
How does TikTok Keyword Search Scraper handle rate limits and blocking?
Every query starts on a direct connection with no proxy. If the search page won't load after maxMountRetries reload attempts, the Actor escalates itself one tier at a time โ Direct โ Datacenter proxy โ Residential proxy โ logging every switch, and stays on Residential for the rest of the run once it's reached. If a user configures their own proxy, that choice is used as-is and the automatic chain never overrides it. Pagination has its own budget: maxScrollRetries consecutive scrolls with no new videos ends a query's pagination, and maxScanned caps how many raw results a single query scans through as a runaway-crawl safety net. If four consecutive queries never load at all, the Actor logs the diagnosis once and stops attempting further queries rather than repeating the same failure โ everything already collected stays saved either way, and a single record that fails to save never stops the rest of the run.
โ ๏ธ If a Residential proxy is also blocked after 3 fresh-session rotations, the Actor gives up on that one query and moves to the next โ the run itself keeps going, and every video already collected for that query has already been saved.
Input
| Parameter | Required | Type | Description | Example Value |
|---|---|---|---|---|
queries | Yes | array | One or more keywords/phrases, or full TikTok search URLs, mixed freely. Each is scraped independently. | ["funny cats", "cooking recipes"] |
datePosted | No | string | Keep only videos published within this window: today, this-week, this-month, this-year. Applied client-side. | "this-month" |
sortBy | No | string | Result order: relevance (default), date, or views. Applied client-side after collection. | "views" |
region | No | string | 2-letter country code sent as an Accept-Language locale hint. Empty by default. | "US" |
maxResults | No | integer | Maximum videos to fetch per query (0โ100000 in the schema; default 10). | 50 |
proxyConfiguration | No | object | Proxy settings. Default is no proxy โ the automatic Direct โ Datacenter โ Residential chain handles most runs. | {"useApifyProxy": false} |
maxMountRetries | No | integer | Page-load retries before escalating the proxy (1โ20, default 5). | 5 |
maxScrollRetries | No | integer | Consecutive empty scrolls allowed before a query is considered exhausted (1โ20, default 4). | 4 |
maxScanned | No | integer | Safety cap on raw rows scanned per query (100โ200000, default 20000). | 20000 |
concurrency | No | integer | Parallel browser tabs, one per query (1โ5, default 2). | 2 |
โ ๏ธ maxResults accepts up to 100000 in the input schema, but the Actor's own validation clamps every query to at most 1000 results โ a higher value logs a warning and is silently capped, not rejected.
Example input
{"queries": ["funny cats", "cooking recipes"],"datePosted": "this-month","sortBy": "views","region": "US","maxResults": 50,"proxyConfiguration": { "useApifyProxy": false },"maxMountRetries": 5,"maxScrollRetries": 4,"maxScanned": 20000,"concurrency": 2}
Output
Results are typed, normalized JSON with a consistent schema across every run, pushed to the dataset the moment each video is found. Download them as JSON, CSV, or Excel from the Output tab, or use the built-in Overview table view for a query/author/stats/link column layout.
Example output
{"aweme_id": "7680270017941835039","aweme_type": 0,"group_id": "7680270017941835039","desc": "we really cooked this up #FunnyCats #CatsOfTikTok","desc_language": "en","is_description_translatable": false,"content_type": "video","create_time": 1788193182,"create_time_utc": "2026-08-31T16:19:42.000Z","region": "US","url": "https://www.tiktok.com/@catorahub/video/7680270017941835039","share_url": "https://www.tiktok.com/@catorahub/video/7680270017941835039","is_ads": false,"is_ad": false,"is_top": 0,"is_paid_partnership": false,"is_eligible_for_commission": false,"shop_product_url": null,"aigc_info": { "aigc_label_type": 0, "created_by_ai": null },"author": {"uid": "7663584039571899406","sec_uid": "MS4wLjABAAAAexample","unique_id": "catorahub","nickname": "catora","avatar_larger": { "url_list": ["https://p16-sign.tiktokcdn-us.com/avatar_larger.jpeg"], "url_prefix": null },"avatar_medium": { "url_list": ["https://p16-sign.tiktokcdn-us.com/avatar_medium.jpeg"], "url_prefix": null },"avatar_thumb": { "url_list": ["https://p16-sign.tiktokcdn-us.com/avatar_thumb.jpeg"], "url_prefix": null },"verification_type": 0,"follower_count": 29603,"following_count": 412,"total_favorited": 1882440,"aweme_count": 318,"secret": 0},"music": {"id": 7680270211014053000,"id_str": "7680270211014053000","title": "original sound - catorahub","author": "catora","album": null,"is_original": true,"duration": 39,"play_url": { "url_list": ["https://sf16-ies-music.tiktokcdn.com/track.mp3"], "url_prefix": null },"cover_thumb": { "url_list": ["https://p16-sign.tiktokcdn-us.com/music_cover.jpeg"], "url_prefix": null }},"added_sound_music_info": {"id": 7680270211014053000,"id_str": "7680270211014053000","title": "original sound - catorahub","author": "catora","album": null,"is_original": true,"duration": 39,"play_url": { "url_list": ["https://sf16-ies-music.tiktokcdn.com/track.mp3"], "url_prefix": null },"cover_thumb": { "url_list": ["https://p16-sign.tiktokcdn-us.com/music_cover.jpeg"], "url_prefix": null }},"statistics": {"aweme_id": "7680270017941835039","digg_count": 150332,"comment_count": 1874,"share_count": 38544,"play_count": 1263171,"collect_count": 14024,"repost_count": 612,"download_count": null,"forward_count": null,"lose_count": null,"lose_comment_count": null,"whatsapp_share_count": null},"status": {"aweme_id": "7680270017941835039","is_delete": false,"is_prohibited": false,"in_reviewing": false,"private_status": 0,"allow_comment": true,"allow_share": true,"self_see": false,"reviewed": 1},"video": {"height": 1280,"width": 720,"duration": 39126,"ratio": "720p","play_addr": { "url_list": ["https://v16.tiktokcdn.com/play/video.mp4"], "url_prefix": null },"download_addr": { "url_list": ["https://v16.tiktokcdn.com/download/video.mp4"], "url_prefix": null },"cover": { "url_list": ["https://p16-sign.tiktokcdn-us.com/cover.jpeg"], "url_prefix": null },"origin_cover": { "url_list": ["https://p16-sign.tiktokcdn-us.com/origin_cover.jpeg"], "url_prefix": null },"dynamic_cover": { "url_list": ["https://p16-sign.tiktokcdn-us.com/dynamic_cover.jpeg"], "url_prefix": null },"has_watermark": null},"text_extra": [{ "start": 20, "end": 30, "type": 1, "hashtag_id": "17001", "hashtag_name": "funnycats", "user_id": "", "is_commerce": false },{ "start": 31, "end": 46, "type": 1, "hashtag_id": "17002", "hashtag_name": "catsoftiktok", "user_id": "", "is_commerce": false }],"cha_list": [{ "cid": "17001", "cha_name": "funnycats", "desc": "" },{ "cid": "17002", "cha_name": "catsoftiktok", "desc": "" }],"aweme_acl": {"duet_enabled": true,"stitch_enabled": true,"share_enabled": true,"download_enabled": true,"comment_enabled": true},"search_query": "funny cats","scraped_at": "2026-09-01T12:00:00.000000Z"}
How does it work?
TikTok Keyword Search Scraper drives Camoufox, an anti-detect Firefox browser, to load TikTok's own search page directly rather than calling any API endpoint by hand. TikTok's web search requires request-signing headers its own JavaScript generates from a live browser fingerprint, so this Actor reads the JSON straight out of the real network responses that page fires โ no header is ever hand-crafted or replayed. Pagination scrolls the page's actual inner results container, not just the outer window, since scrolling the window alone never triggers TikTok's lazy-loaded pages. Every request starts on a direct connection and only escalates to a Datacenter, then a Residential proxy if TikTok actually blocks it. Only what a visitor could see on TikTok's public search page is ever returned, and the output schema stays the same shape run to run, regardless of how TikTok reshuffles its own search page's layout.
Integrations
TikTok Keyword Search Scraper is callable from any environment that can make an HTTP request, including from AI agent frameworks and no-code automation tools.
Calling TikTok Keyword Search Scraper programmatically
from apify_client import ApifyClientclient = ApifyClient("<APIFY_API_TOKEN>")run = client.actor("<YOUR_USERNAME>/tiktok-keyword-search-scraper").call(run_input={"queries": ["funny cats"],"maxResults": 50,})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["desc"], item["statistics"]["play_count"])
Works in Go, Ruby, Node.js, cURL โ any language that can make an HTTP request.
MCP integration for AI agents
Apify publishes a general-purpose MCP server that exposes any Actor on the platform โ including this one โ as a callable tool for MCP-aware clients such as Claude Desktop and Cursor. Point it at this Actor by name (tiktok-keyword-search-scraper) using your Apify API token, and an agent can call it the same way it calls a local tool, no custom integration code required.
No-code tools (n8n, Make, LangChain)
In n8n, use the HTTP Request node pointed at this Actor's run-sync API endpoint with your queries payload as the request body. In Make, the Apify app's "Run an Actor" module takes the same input fields shown above and returns the dataset items as a bundle. In LangChain, the ApifyWrapper can call this Actor by ID and load the resulting dataset directly as documents for a chain or agent.
Is it legal to scrape TikTok videos?
Scraping publicly available data โ the videos, captions and profile fields any visitor can see without logging in โ is generally lawful in most jurisdictions, and TikTok Keyword Search Scraper returns only that kind of data. Because the output includes author profile fields (username, nickname, avatar, follower count), it can count as personal data under regimes like GDPR and CCPA if you store or process it โ you're responsible for having a lawful basis for that use, and for TikTok's own Terms of Service governing how scraped data may be used. Consult legal counsel if your use case involves bulk storage of personal data.
Frequently asked questions
What TikTok video fields does TikTok Keyword Search Scraper return?
It returns desc (caption), statistics (likes/plays/comments/shares), author (username, nickname, followers), video (dimensions, duration, playback URLs), and text_extra/cha_list (hashtags), along with status and permission flags โ see the full field table above.
Does TikTok Keyword Search Scraper require a TikTok account or login?
No. It searches TikTok's public web search page with no TikTok account, login, or API key โ only publicly visible results are returned.
How many videos can I extract in one run?
Each query is capped at 1,000 results by the Actor's own validation (regardless of a higher maxResults value), and you can run as many queries as you like in a single queries array in one run.
What happens if a query returns zero results?
The run finishes normally with 0 records for that query and a log line explaining why โ most often TikTok challenging a fresh session. The Actor already retries and escalates its proxy tier automatically on a block; if a query still comes back empty, retrying with a Residential proxy configured explicitly resolves most remaining cases.
Can I scrape multiple TikTok search queries at once?
Yes. queries is a bulk array field โ add as many keywords or TikTok search URLs as you like, and they're scraped independently (up to concurrency at a time) with results streamed into one shared dataset.
Does TikTok Keyword Search Scraper work with Claude, ChatGPT, and other AI agent tools?
Yes. It's reachable through Apify's general-purpose MCP server for MCP-aware clients, and callable as a plain HTTP endpoint by any agent framework that can make a request and read JSON.
How does this differ from scraping TikTok search results by hand?
Beyond the browser and pagination handling, this Actor enforces sortBy and datePosted correctly by applying them client-side against the actual data โ TikTok's anonymous search request carries no server-side sort or date parameter at all, so a hand-rolled scraper that trusts a URL parameter for either would silently get unfiltered, unsorted results back.
Does TikTok Keyword Search Scraper return data in a format LLMs can use directly?
Yes. Every record is typed, normalized JSON with consistent field names across runs โ no HTML parsing or CSS selectors involved. Pass it directly to an LLM, index it into a vector store, or feed it to an agent tool.
What happens when TikTok changes its layout or anti-bot system?
The Actor is maintained, and the output schema is designed to stay stable across TikTok frontend changes โ the parsing logic targets TikTok's underlying API response shape, not page markup that changes with every redesign.
Can I use TikTok Keyword Search Scraper without managing proxies or browser infrastructure?
Yes. The Actor runs its own anti-detect browser and handles proxy tier escalation (Direct โ Datacenter โ Residential) automatically; you only need to configure a proxy yourself if you want to force a specific tier from the start.
Which fields work best for AI training data and RAG indexing?
For RAG, index desc and text_extra[].hashtag_name as searchable text context. For structured training data, statistics.play_count, statistics.digg_count, and create_time are the most consistently populated numeric fields across records. All fields return as typed primitives (strings, integers, booleans) rather than raw HTML.
Related scrapers
| Scraper Name | What it extracts |
|---|---|
| TikTok Posts Scraper | TikTok posts from profiles, hashtags, keyword search, or pasted URLs, with the same proxy-escalation and real-time output design |
| Best TikTok AI Transcript Extractor | AI-generated transcripts (SRT/VTT, timestamped segments) plus 40+ creator/video metadata fields from TikTok videos |
| Instagram Transcript API & Profile Scraper - AI Video to Text | AI transcripts from Instagram Reels/videos plus bulk public profile posts, for teams tracking both platforms |
| Spotify Play Count Scraper | Exact play/stream counts for Spotify artists, albums and tracks |
Your feedback
Found a bug or a field that's missing? Let us know โ reach out at dev.scraperengine@gmail.com or through the Issues tab on the Actor's Apify Console page, and we'll take a look.