TikTok Scraper With Keyword & Hashtag Discovery avatar

TikTok Scraper With Keyword & Hashtag Discovery

Pricing

from $4.99 / 1,000 results

Go to Apify Store
TikTok Scraper With Keyword & Hashtag Discovery

TikTok Scraper With Keyword & Hashtag Discovery

TikTok Scraper discovers public videos using keywords and hashtags, extracting titles, captions, creators, views, likes, comments, shares, hashtags, and video URLs. Build structured datasets for trend research, content analysis, influencer discovery, and competitor monitoring.

Pricing

from $4.99 / 1,000 results

Rating

0.0

(0)

Developer

API Empire

API Empire

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

TikTok Scraper โ€” Extract Videos, Reposts and Hashtag Stats as JSON

TikTok Scraper With Keyword & Hashtag Discovery pulls profile videos, reposts, and keyword or hashtag search results straight from TikTok's public web pages and endpoints โ€” no TikTok API key and no login required. Every result comes back as typed, normalized JSON: full engagement stats, author metadata, and structured search items, with no HTML to parse. Two optional add-ons go further โ€” real per-hashtag view/video totals, and TikTok's own related-keyword suggestions. Configure a profile list or a search query, start the run, and structured TikTok data is ready for a spreadsheet, a database, or an LLM pipeline.

What is TikTok Scraper With Keyword & Hashtag Discovery?

TikTok Scraper With Keyword & Hashtag Discovery is an Apify Actor that scrapes public TikTok data across six distinct row types: profile videos, profile reposts, keyword search results, hashtag search results, and โ€” as optional add-ons โ€” per-hashtag statistics and related-keyword suggestions. It runs entirely against TikTok's public web pages and API endpoints; no TikTok account, login, or API key is needed.

  • ๐Ÿ“บ Scrape every public video from one or more profiles
  • ๐Ÿ”„ Scrape a profile's reposted content separately from its own uploads
  • ๐Ÿ” Run a keyword search or a #๏ธโƒฃ hashtag search and collect matching videos
  • ๐Ÿ“ˆ Resolve a hashtag's real platform-wide view/video totals
  • ๐Ÿงญ Discover TikTok's own related-search suggestions for a query
  • ๐Ÿ’พ Every row lands in the dataset the moment it's collected โ€” no waiting for the run to finish

What data does TikTok Scraper With Keyword & Hashtag Discovery collect?

The actor returns six structurally different row types in the same dataset, distinguished by their type field:

Data TypeKey FieldsJSON Field Names
Profile videosTitle, view/like/comment/share counts, author, cover & play URLsvideo.title, video.stats.views, video.author.username, videoViews, videoLikes
Profile repostsOriginal creator, engagement stats, video/music metadatarepost.text, repost.playCount, repost.authorMeta.name, repostViews
Keyword search resultsCaption, engagement stats, author stats, in-caption hashtagsitem.desc, item.stats.playCount, item.authorStats.followerCount, item.textExtra
Hashtag search resultsCaption text, engagement stats, hashtags, mentionsitem.text, item.playCount, item.hashtags, item.mentions
Hashtag stats (add-on)Platform-wide total views, total videos, commerce flaghashtagStats.totalViewCount, hashtagStats.totalVideoCount, hashtagStats.isCommerce
Related keywords (add-on)TikTok's own suggested adjacent search termsrelatedKeywords.sourceQuery, relatedKeywords.suggestions

How does TikTok Scraper With Keyword & Hashtag Discovery differ from the official TikTok API?

TikTok's official developer products (the Research API and the Login Kit / Display API) are not open, self-serve APIs for arbitrary public profile, keyword, or hashtag data โ€” this Actor is. As of 2026-08-15, TikTok's own developer documentation states the Research API is restricted to applicants affiliated with an academic institution or not-for-profit research organization in the US, EEA, UK, Switzerland, or Brazil, conducting research "on a not-for-profit basis with no commercial interests" (developers.tiktok.com/products/research-api, checked 2026-08-15). The Login Kit / Display API instead requires the TikTok account owner to log in and authorize the requesting app (developers.tiktok.com/products/login-kit, checked 2026-08-15) โ€” it is built around a user granting access to their own account, not a developer looking up other public creators, hashtags, or search results.

FeatureTikTok's Official Developer APIsTikTok Scraper With Keyword & Hashtag Discovery
Who can access itResearch API: approved academic/non-profit researchers only, no commercial useAnyone with an Apify account
AuthorizationLogin Kit/Display API: the TikTok account owner must log in and authorize your appNo TikTok login โ€” reads public pages directly
Entity coverageLogin Kit scope is the authorizing user's own account; no documented public keyword/hashtag search endpointProfile videos, reposts, keyword search, hashtag search, hashtag totals, and related-keyword suggestions in one run
Approval processFormal application and review for Research API accessConfigure the input fields and click Start
Output shapeVaries by product/endpoint per TikTok's own schemaOne normalized JSON row shape (type, success, payload) across all six entities

If your use case genuinely qualifies for the Research API's academic/non-profit criteria, or you only need data from a TikTok account you already own and can authorize through Login Kit, those official routes are the right ones. For ad-hoc profile, keyword, and hashtag data where an approval process isn't practical, this Actor covers the same public surface without one.

Why do developers and teams scrape TikTok?

For AI engineers and agent builders

Feed a RAG index or an agent's tool call with structured TikTok search results instead of scraping HTML inside the agent loop. A searchType: "keyword" run returns item.desc, item.stats.playCount, item.authorStats, and item.hashtags as typed JSON โ€” pass it straight into a vector store or an LLM's context window without a parsing step. Every row shares the same type / success / payload-key envelope regardless of which of the six row types produced it, so an agent can branch on type once and reuse the same downstream handling for profile_video, keyword_search, and hashtag_stats rows alike.

For marketers and brand teams

Track a competitor or creator partner by pointing startUrls at their profile with profileScrapeSections: ["videos", "repost"] โ€” you get every public upload plus what they've reposted, each with videoViews/videoLikes for quick engagement comparisons across a channel. Turn on fetchHashtagStats against a campaign hashtag to see its real platform-wide totalViewCount and totalVideoCount, not just the counts on the handful of videos that happen to appear in your own search results.

For researchers and analysts

Every row is public TikTok data, returned exactly as the platform serves it โ€” no login, no private accounts, no gated content โ€” which fits research into hashtag reach or search-result composition without touching account-restricted data. Run a hashtag search with searchType: "hashtag" and fetchHashtagStats on, and the same dataset carries both the sampled videos and the hashtag's true totalViewCount/totalVideoCount, so a sample can be checked against its real population size.

For developers building data products

maxResults, searchType, and profileScrapeSections are plain input fields, so this Actor slots into a scheduled Apify pipeline: run it nightly against a fixed list of profiles or hashtags and build a trend-tracking product on top of the dataset's stable type / success / summary / scrapedAt shape, without building or maintaining a TikTok scraper of your own.

How to scrape TikTok (step by step)

  1. Open TikTok Scraper With Keyword & Hashtag Discovery on the Apify Store, or find it in your Apify account if you've already added it.
  2. Provide input: add one or more entries to startUrls, and/or set searchQuery โ€” you need at least one of the two; leaving both empty stops the run immediately with an uncharged error row.
  3. Choose what to collect: set profileScrapeSections (videos, repost, or both) for profile input, and searchType (keyword or hashtag) for search input. Toggle fetchHashtagStats and/or discoverRelatedKeywords for the optional discovery add-ons.
  4. Click Start and watch rows land in the Output tab in real time as they're scraped.
  5. Export the dataset as JSON, CSV, or Excel from the Apify Console, or pull it through the Apify API into your own pipeline.

What to do when TikTok changes its structure

TikTok's page and endpoint structure changes over time, and this Actor is maintained against those changes. The output schema โ€” each row's type, success, and payload-key fields โ€” stays stable across updates, so an integration built against video.stats.views or item.hashtags keeps working without changes on your end.

โฌ‡๏ธ Input

All eight input parameters are optional at the schema level, but the Actor needs at least one of startUrls or searchQuery to have anything to scrape.

ParameterRequiredTypeDescriptionExample Value
startUrlsNoArrayTikTok profile URLs (e.g. https://www.tiktok.com/@username) or plain usernames. Supports bulk input. Leave empty for search-only runs.["https://www.tiktok.com/@mrbeast"]
profileScrapeSectionsNoArray (items enum: videos, repost)Which profile sections to scrape: videos (all profile videos) and/or repost (reposted content). Select one or both. Default: ["videos"].["videos", "repost"]
searchQueryNoStringA search query for hashtag or keyword search. Leave empty for profile-only runs. When set, also seeds the Discovery & Hashtag Intelligence add-ons below. Default: ""."cooking tips"
searchTypeNoString (enum: keyword, hashtag)Search mode: keyword (general TikTok search) or hashtag (hashtag-focused search). Default: "keyword"."keyword"
maxResultsNoInteger (min 1, max 1000)Maximum results to collect per profile/search query. Default: 100.100
fetchHashtagStatsNoBooleanWhen on, resolves every hashtag involved in the run (your hashtag query, plus hashtags found inside keyword/hashtag search results) to its real platform-wide totals: total view count, total video count, and whether it's a commerce hashtag. Adds one hashtag_stats row per unique hashtag, up to 6 per run. Default: false.true
discoverRelatedKeywordsNoBooleanBest-effort: when on and a search query is provided, attempts to fetch TikTok's own related-search suggestions for that query and adds a related_keywords row. This surface has proven unreliable in testing โ€” treat any returned suggestions as a bonus, not a guarantee; some runs return a success: false row instead. Default: false.false
proxyConfigurationNoObjectOptional proxy settings. By default no proxy is used (direct connection); the Actor automatically switches to a backup connection if a request needs one.{}

Example JSON input

{
"startUrls": ["https://www.tiktok.com/@mrbeast"],
"profileScrapeSections": ["videos", "repost"],
"searchQuery": "cooking tips",
"searchType": "keyword",
"maxResults": 100,
"fetchHashtagStats": true,
"discoverRelatedKeywords": true,
"proxyConfiguration": {}
}

โš ๏ธ Common pitfall: leaving both startUrls and searchQuery empty. The Actor doesn't scrape anything by default โ€” it needs at least one of the two, or it stops immediately with an uncharged error row and no data collected.

โฌ†๏ธ Output

Every result is one JSON row pushed to the dataset the moment it's collected โ€” nothing is held back until the run ends. All six row types share the same envelope โ€” type, isChild, username, query, success, summary, scrapedAt, error โ€” then add their own payload key (video, repost, item, hashtagStats, or relatedKeywords). The four core scraping row types also add a set of flat top-level fields alongside the nested payload object; the two discovery add-on rows (hashtag_stats, related_keywords, both with isChild: true) do not. Export the dataset as JSON, CSV, or Excel.

Pay-per-event billing: only rows pushed with success: true are billed as one row_result charged event. Rows pushed with success: false โ€” a profile with no public videos, a hashtag-stats lookup that couldn't resolve, a related-keyword attempt with no suggestions, or the top-level "no input provided" guard row โ€” are still written to the dataset, but are not charged. Filter the dataset on success = true to see only billed rows.

Scraped profile videos

{
"type": "profile_video",
"isChild": false,
"username": "mrbeast",
"query": null,
"success": true,
"summary": "I gave people $1,000,000 if they could survive... - 45230000 views",
"scrapedAt": "2026-08-15T10:22:03Z",
"error": null,
"video": {
"id": "7345678901234567890",
"url": "https://www.tiktok.com/@mrbeast/video/7345678901234567890",
"title": "I gave people $1,000,000 if they could survive...",
"description": "I gave people $1,000,000 if they could survive...",
"create_time": 1755123723,
"duration": 58,
"width": 1080,
"height": 1920,
"cover_url": "https://p16-sign-va.tiktokcdn.com/example-cover.jpeg",
"dynamic_cover_url": "https://p16-sign-va.tiktokcdn.com/example-dyncover.jpeg",
"play_url": "https://v16-webapp.tiktok.com/example-play.mp4",
"download_url": "https://v16-webapp.tiktok.com/example-download.mp4",
"author": {
"username": "mrbeast",
"nickname": "MrBeast",
"avatar": "https://p16-sign-va.tiktokcdn.com/example-avatar.jpeg",
"verified": true
},
"stats": { "views": 45230000, "likes": 3120000, "comments": 41230, "shares": 98500 },
"music": { "title": "original sound", "author": "MrBeast", "duration": 58 }
},
"videoId": "7345678901234567890",
"videoTitle": "I gave people $1,000,000 if they could survive...",
"videoUrl": "https://www.tiktok.com/@mrbeast/video/7345678901234567890",
"videoCreatedAt": "2026-08-13T18:22:03Z",
"videoAuthor": "mrbeast",
"videoViews": 45230000,
"videoLikes": 3120000,
"videoComments": 41230,
"videoShares": 98500
}

Scraped profile reposts

repost uses dotted string keys (e.g. "authorMeta.name"), not nested objects โ€” the row is pushed exactly as the scraper extracts it.

{
"type": "profile_repost",
"isChild": false,
"username": "mrbeast",
"query": null,
"success": true,
"summary": "Reacting to the craziest bet ever... - 812000 plays",
"scrapedAt": "2026-08-15T10:24:11Z",
"error": null,
"repost": {
"authorMeta.avatar": "https://p16-sign-va.tiktokcdn.com/example-avatar.jpeg",
"authorMeta.name": "someoriginalcreator",
"text": "Reacting to the craziest bet ever...",
"diggCount": 55000,
"shareCount": 3200,
"playCount": 812000,
"commentCount": 1450,
"videoMeta.duration": 34,
"musicMeta.musicName": "original sound",
"musicMeta.musicAuthor": "someoriginalcreator",
"musicMeta.musicOriginal": true,
"createTimeISO": "2026-08-10T09:15:00Z",
"webVideoUrl": "https://www.tiktok.com/@someoriginalcreator/video/7344001122334455667",
"authorMeta.nickname": "Some Original Creator",
"authorMeta.verified": false,
"authorMeta.signature": "",
"authorMeta.following": 120,
"authorMeta.fans": 890000,
"authorMeta.heart": 21000000,
"authorMeta.video": 640,
"authorMeta.digg": 5400,
"stats.collectCount": 6700,
"videoMeta.width": 1080,
"videoMeta.height": 1920,
"videoMeta.ratio": "1080p",
"videoMeta.cover": "https://p16-sign-va.tiktokcdn.com/example-cover.jpeg",
"videoMeta.originCover": "https://p16-sign-va.tiktokcdn.com/example-origcover.jpeg",
"videoMeta.dynamicCover": "https://p16-sign-va.tiktokcdn.com/example-dyncover.jpeg",
"videoMeta.playAddr": "https://v16-webapp.tiktok.com/example-play.mp4",
"videoMeta.downloadAddr": "https://v16-webapp.tiktok.com/example-download.mp4",
"videoMeta.shareCover": [],
"musicMeta.musicId": "7344001199887766554",
"musicMeta.musicAlbum": "",
"musicMeta.musicCover": "https://p16-sign-va.tiktokcdn.com/example-musiccover.jpeg",
"musicMeta.musicPlayUrl": "https://sf16-ies-music.tiktokcdn.com/example.mp3",
"musicMeta.musicDuration": 34,
"id": "7344001122334455667",
"secretID": "",
"isAd": false,
"itemCommentStatus": 0,
"privateItem": false,
"duetEnabled": true,
"stitchEnabled": true,
"shareEnabled": true,
"locationCreated": "",
"forFriend": false,
"officalItem": false,
"originalItem": false,
"duetDisplay": 0,
"stitchDisplay": 0,
"stickersOnItem": [],
"effectStickers": []
},
"repostId": "7344001122334455667",
"repostText": "Reacting to the craziest bet ever...",
"repostUrl": "https://www.tiktok.com/@someoriginalcreator/video/7344001122334455667",
"repostCreatedAt": "2026-08-10T09:15:00Z",
"repostAuthor": "someoriginalcreator",
"repostViews": 812000,
"repostLikes": 55000
}

Keyword search results

{
"type": "keyword_search",
"isChild": false,
"username": null,
"query": "cooking tips",
"success": true,
"summary": "5-minute pasta hack you need to try #cookingtips - 1204500 plays",
"scrapedAt": "2026-08-15T10:26:40Z",
"error": null,
"item": {
"url": "https://www.tiktok.com/@chefcarla/video/7343112233445566778?is_copy_url=1&is_from_webapp=v1",
"id": "7343112233445566778",
"desc": "5-minute pasta hack you need to try #cookingtips",
"createTime": "1755012345",
"scheduleTime": 0,
"video": {
"id": "7343112233445566778",
"height": 1024,
"width": 576,
"duration": 27,
"ratio": "540p",
"cover": "https://p16-sign-va.tiktokcdn.com/example-cover.jpeg",
"originCover": "https://p16-sign-va.tiktokcdn.com/example-origcover.jpeg",
"dynamicCover": "https://p16-sign-va.tiktokcdn.com/example-dyncover.jpeg",
"playAddr": "https://v16-webapp.tiktok.com/example-play.mp4",
"downloadAddr": "https://v16-webapp.tiktok.com/example-download.mp4",
"shareCover": [],
"reflowCover": "https://p16-sign-va.tiktokcdn.com/example-cover.jpeg",
"bitrate": 745200,
"encodedType": "normal",
"format": "mp4",
"videoQuality": "normal",
"encodeUserTag": "",
"codecType": "h264",
"definition": "540p",
"subtitleInfos": [],
"zoomCover": {},
"volumeInfo": {},
"bitrateInfo": []
},
"author": "chefcarla",
"music": {
"id": "7343100099887766554",
"title": "original sound",
"playUrl": "https://sf16-ies-music.tiktokcdn.com/example.mp3",
"coverLarge": "https://p16-sign-va.tiktokcdn.com/example.jpeg",
"coverMedium": "https://p16-sign-va.tiktokcdn.com/example.jpeg",
"coverThumb": "https://p16-sign-va.tiktokcdn.com/example.jpeg",
"authorName": "chefcarla",
"original": true,
"duration": 27,
"album": "",
"scheduleSearchTime": 0
},
"challenges": [],
"stats": { "diggCount": 88400, "shareCount": 5200, "commentCount": 1330, "playCount": 1204500 },
"isActivityItem": false,
"duetInfo": { "duetFromId": "0" },
"warnInfo": [],
"originalItem": true,
"officalItem": false,
"textExtra": [
{
"awemeId": "",
"start": 32,
"end": 45,
"hashtagId": "1234567",
"hashtagName": "cookingtips",
"type": 1,
"subType": 0,
"userId": "",
"isCommerce": false,
"userUniqueId": "",
"secUid": ""
}
],
"secret": false,
"forFriend": false,
"digged": false,
"itemCommentStatus": 0,
"showNotPass": false,
"vl1": false,
"takeDown": 0,
"itemMute": false,
"effectStickers": [],
"authorStats": {
"followerCount": 412000,
"followingCount": 210,
"heart": 8900000,
"heartCount": 8900000,
"videoCount": 340,
"diggCount": 1200
},
"privateItem": false,
"duetEnabled": true,
"stitchEnabled": true,
"stickersOnItem": [],
"isAd": false,
"shareEnabled": true,
"comments": [],
"duetDisplay": 0,
"stitchDisplay": 0,
"indexEnabled": true,
"diversificationLabels": [],
"adAuthorization": false,
"adLabelVersion": 0,
"locationCreated": "",
"nickname": "Chef Carla",
"authorId": "6820011223344556677",
"authorSecId": "MS4wLjABAAAA_example_secid",
"avatarThumb": "https://p16-sign-va.tiktokcdn.com/example.jpeg",
"downloadSetting": 0,
"authorPrivate": false
},
"itemId": "7343112233445566778",
"itemText": "5-minute pasta hack you need to try #cookingtips",
"itemUrl": "https://www.tiktok.com/@chefcarla/video/7343112233445566778?is_copy_url=1&is_from_webapp=v1",
"itemCreatedAt": "2025-08-12T14:25:45Z",
"itemViews": 1204500,
"itemLikes": 88400,
"itemComments": 1330
}

Hashtag search results

{
"type": "hashtag_search",
"isChild": false,
"username": null,
"query": "cookingtips",
"success": true,
"summary": "Day 12 of my #cookingtips series, this one flopped ๐Ÿ˜‚ - 210500 plays",
"scrapedAt": "2026-08-15T10:28:15Z",
"error": null,
"item": {
"id": "7342001122334455667",
"text": "Day 12 of my #cookingtips series, this one flopped ๐Ÿ˜‚",
"createTime": 1754901234,
"createTimeISO": "2025-08-11T06:33:54Z",
"isAd": false,
"isMuted": false,
"authorMeta": {
"id": "6819900112233445566",
"name": "homecookhannah",
"nickName": "Hannah Cooks",
"verified": false,
"signature": "Simple recipes, real fails",
"bioLink": null,
"avatar": "https://p16-sign-va.tiktokcdn.com/example.jpeg",
"privateAccount": false,
"ttSeller": false,
"following": 340,
"fans": 98000,
"heart": 2100000,
"video": 210,
"digg": 4300
},
"musicMeta": {
"musicName": "original sound",
"musicAuthor": "homecookhannah",
"musicOriginal": true,
"musicAlbum": "",
"playUrl": "https://sf16-ies-music.tiktokcdn.com/example.mp3",
"coverMediumUrl": "https://p16-sign-va.tiktokcdn.com/example.jpeg",
"musicId": "7342000099887766554"
},
"webVideoUrl": "https://www.tiktok.com/@homecookhannah/video/7342001122334455667",
"mediaUrls": ["https://v16-webapp.tiktok.com/example-play.mp4"],
"videoMeta": {
"height": 1920,
"width": 1080,
"duration": 41,
"coverUrl": "https://p16-sign-va.tiktokcdn.com/example.jpeg",
"originalCoverUrl": "https://p16-sign-va.tiktokcdn.com/example.jpeg",
"definition": "540p",
"format": "mp4",
"originalDownloadAddr": "https://v16-webapp.tiktok.com/example-download.mp4",
"downloadAddr": "https://v16-webapp.tiktok.com/example-download.mp4"
},
"diggCount": 15200,
"shareCount": 640,
"playCount": 210500,
"collectCount": 980,
"commentCount": 512,
"mentions": [],
"hashtags": [{ "name": "cookingtips" }]
},
"itemId": "7342001122334455667",
"itemText": "Day 12 of my #cookingtips series, this one flopped ๐Ÿ˜‚",
"itemUrl": "https://www.tiktok.com/@homecookhannah/video/7342001122334455667",
"itemCreatedAt": "2025-08-11T06:33:54Z",
"itemViews": 210500,
"itemLikes": 15200,
"itemComments": 512
}

Hashtag stats (discovery add-on)

{
"type": "hashtag_stats",
"isChild": true,
"username": null,
"query": "cookingtips",
"success": true,
"summary": "#cookingtips - 3200450000 views, 890120 videos",
"scrapedAt": "2026-08-15T10:31:44Z",
"error": null,
"hashtagStats": {
"hashtagId": "1234567",
"hashtagName": "cookingtips",
"totalViewCount": 3200450000,
"totalVideoCount": 890120,
"isCommerce": false,
"description": "Share your cooking tips and tricks!"
}
}

A failed lookup is pushed instead of being silently skipped:

{
"type": "hashtag_stats",
"isChild": true,
"username": null,
"query": "cookingtips",
"success": false,
"summary": "No hashtag stats available for #cookingtips.",
"scrapedAt": "2026-08-15T10:31:44Z",
"error": "No hashtag stats available for #cookingtips."
}
{
"type": "related_keywords",
"isChild": true,
"username": null,
"query": "cookingtips",
"success": true,
"summary": "cookingtips -> 4 suggestion(s)",
"scrapedAt": "2026-08-15T10:32:10Z",
"error": null,
"relatedKeywords": {
"sourceQuery": "cookingtips",
"suggestions": ["cooking tips for beginners", "cooking tips and tricks", "easy cooking tips", "quick cooking tips"]
}
}

โš ๏ธ This surface has proven unreliable in testing. Many runs instead get a clearly-flagged failure row rather than a fake empty success:

{
"type": "related_keywords",
"isChild": true,
"username": null,
"query": "cookingtips",
"success": false,
"summary": "No related keyword suggestions could be resolved for 'cookingtips'.",
"scrapedAt": "2026-08-15T10:32:10Z",
"error": "No related keyword suggestions could be resolved for 'cookingtips'."
}

How many results can you scrape with TikTok Scraper With Keyword & Hashtag Discovery?

maxResults (default 100, range 1โ€“1000) caps how many videos or search items the Actor collects per profile or per search query โ€” not as a single global cap across the whole run. Point startUrls at five profiles with maxResults: 200 and you can get up to 1,000 profile_video rows, plus more from a search query if one is set.

Profile videos paginate through TikTok's own cursor, page by page, until either maxResults is reached or TikTok stops returning new videos. Reposts, keyword search, and hashtag search scroll a live TikTok page and collect from the API responses that scrolling triggers, stopping once maxResults is hit or several scrolls in a row return nothing new.

The fetchHashtagStats add-on is capped independently at 6 unique hashtags per run, regardless of how many appear across your query and results โ€” that limit is in the Actor's own code, not a TikTok platform limit. Beyond these, there's no hard cap in the Actor itself; the practical ceiling for any one profile or query is however much TikTok's public pages return before pagination or scrolling stops advancing.

Integrate TikTok Scraper With Keyword & Hashtag Discovery and automate your workflow

TikTok Scraper With Keyword & Hashtag Discovery works with any language or tool that can send an HTTP request โ€” it runs as a standard Apify Actor, callable through the Apify API and the apify-client SDKs.

REST API integration

from apify_client import ApifyClient
client = ApifyClient("<APIFY_API_TOKEN>")
run = client.actor("your-username/tiktok-scraper-with-keyword-and-hashtag-discovery").call(
run_input={
"startUrls": ["https://www.tiktok.com/@mrbeast"],
"searchQuery": "cooking tips",
"maxResults": 100,
}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item["type"], item.get("summary"))

Works in Python, Node.js, Go, Ruby, cURL โ€” anything that can call a REST endpoint.

Automation platforms and AI frameworks

Apify publishes an official Apify integration for n8n (@apify/n8n-nodes-apify), so you can run this Actor and read its dataset directly inside an n8n workflow (docs.apify.com/platform/integrations/n8n, checked 2026-08-15). For LangChain, Apify's own ApifyWrapper/ApifyActorsTool integration (langchain-apify on PyPI) lets an agent call this Actor as a tool and load its dataset as documents for a vector store (python.langchain.com/docs/integrations/providers/apify, checked 2026-08-15).

Yes โ€” scraping publicly available TikTok data is generally legal, and TikTok Scraper With Keyword & Hashtag Discovery only ever returns data from public profiles, public videos, and public search/hashtag results; it never accesses private accounts or logged-in-only content. Because the returned rows include personal data tied to identifiable individuals โ€” usernames, nicknames, avatars, and engagement figures for the people who post the videos โ€” GDPR (in the EU/UK) and CCPA (in California) considerations apply to how you store, process, and reuse that data, alongside TikTok's own Terms of Service. Consult legal counsel for commercial use cases involving bulk personal data.

โ“ Frequently asked questions

Does TikTok Scraper With Keyword & Hashtag Discovery work without a TikTok account?

Yes. It reads TikTok's public web pages and API endpoints directly โ€” no TikTok login, account, or API key is required to run it.

How often is the scraped data updated?

Every run fetches live data from TikTok at the moment it runs; nothing is served from a cache. Run it again, or on a schedule, to get current numbers.

What happens if a profile has no public videos, or a search returns nothing?

The Actor pushes a success: false row with a descriptive error message instead of silently returning nothing โ€” for example, "No videos could be collected for this profile." for an empty profile. These rows are written to the dataset but not charged.

Can I scrape private TikTok accounts?

No. Only publicly accessible profiles, videos, and search results are returned โ€” private accounts and their content are out of scope.

Is there a free trial or a fixed price per run?

The Actor is billed per event โ€” one row_result charged event per successful row. Current pricing is set on the Actor's Pricing tab on its Apify Store listing.

Does TikTok Scraper With Keyword & Hashtag Discovery work for AI agent workflows and LLM pipelines?

Yes. It's callable as an HTTP endpoint through the Apify API by any agent framework, and every response is typed JSON โ€” no HTML, no selectors, no parsing step before passing rows to an LLM or indexing them into a vector store.

How does TikTok Scraper With Keyword & Hashtag Discovery handle TikTok's anti-bot defenses?

Profile-video scraping uses a direct API call with a content-based challenge detector, escalating to a different connection tier if the response looks like a challenge page. Reposts, keyword search, and hashtag search use a real browser session (patchright) that first warms up TikTok's own device-trust cookies before scraping. All paths retry with exponential backoff on transient failures and step up through connection tiers (direct โ†’ backup โ†’ backup) if a request keeps coming back empty.

A hashtag or keyword search only tells you about the sample of videos it returned. fetchHashtagStats separately resolves the hashtag's own real, platform-wide totalViewCount and totalVideoCount โ€” independent of how many videos you scraped. discoverRelatedKeywords attempts to surface TikTok's own suggested next-search terms for your query; this second surface is best-effort and has proven unreliable in testing, so expect some runs to return an honestly-flagged success: false row instead of suggestions.

Does TikTok Scraper With Keyword & Hashtag Discovery return data in a format LLMs can use directly?

Yes. Every row is typed, normalized JSON with stable field names โ€” no HTML, no selectors. Pass it directly into an LLM's context window, index it into a vector store, or route it through an agent tool call.

Can I use TikTok Scraper With Keyword & Hashtag Discovery without managing proxies?

Yes. By default the Actor connects directly with no proxy configured, and automatically escalates to a backup connection if a request needs it. You can also supply your own proxyConfiguration (Apify Proxy).

What happens when TikTok changes its structure or blocks the scraper?

TikTok Scraper With Keyword & Hashtag Discovery is maintained against TikTok's changes, and the output schema stays stable โ€” the row's type, success, and payload-key fields don't change on your end, even when the Actor's internals are updated to match a TikTok change.

๐Ÿ’ฌ Your feedback

Found a bug, or missing a field you need? We want to know. Use the Issues tab on this Actor's Apify Store listing to report it, or message the developer directly through the Store page โ€” active maintenance is how this Actor keeps working as TikTok changes.