TikTok Scraper: Profiles, Videos, Hashtags, Search & Comments
Pricing
from $2.00 / 1,000 result rows
TikTok Scraper: Profiles, Videos, Hashtags, Search & Comments
One actor for TikTok instead of seven. Pick a mode and pass a list: accounts and their posts, a single post in full detail, a hashtag's video feed, keyword search, a video's comments with replies, or account discovery by keyword. Video rows share one shape across every mode. No login, no cookies.
Pricing
from $2.00 / 1,000 result rows
Rating
0.0
(0)
Developer
Muhamed Didovic
Maintained by CommunityActor stats
0
Bookmarked
21
Total users
18
Monthly active users
6 days ago
Last modified
Categories
Share

One actor for TikTok instead of seven. Pick a mode, pass a list, and the rows land in a single dataset you can sort.
Accounts and their posts, one post in full detail, a hashtag's video feed, keyword search, a video's comments with replies, or account discovery by keyword.
Why Use This Scraper
- Seven jobs, one actor and one input shape to learn
- A video row is the same row whether it came from a profile, a hashtag or a search
- Exact limits. Ask for 37 and you get 37, not the 50 a page happens to hold
- Duplicates removed by id, which matters because TikTok's cursors overlap
- A backup source takes over when the primary runs dry mid-keyword
- Partial beats dead. A run near its timeout returns what it has instead of failing
- No login, no cookies, no proxy configuration
Overview
This is for people who already work with TikTok data and are tired of wiring up a different actor, a different input shape and a different output schema for every question. Researchers, agencies, creator-marketing teams and anyone feeding a dashboard.
Every row carries rowType and source, so a mixed run stays parseable and you can branch without guessing where a row came from.
Output is a flat dataset you can export as JSON, CSV or Excel.
Supported Inputs
The input list means whatever the mode says it means.
| Mode | What to pass | Example |
|---|---|---|
profile | usernames or profile URLs | @gymshark |
videos | usernames or profile URLs | https://www.tiktok.com/@khaby.lame |
post | post URLs or bare IDs | 7660964717631999254 |
hashtag | hashtags or tag URLs | #coffee |
search | plain keywords | latte art |
comments | video URLs or bare IDs | https://www.tiktok.com/@gymshark/video/7660964717631999254 |
users | plain keywords | fitness coach |
Short vm.tiktok.com and vt.tiktok.com share links are resolved for you in post and comments modes.
Unsupported inputs
- Live streams. Not covered by any mode.
- Private accounts. A public card is returned where one exists, but private posts are not public data and are reported as such.
- Anything behind a login. This actor never authenticates.
Use Cases
| Audience | What they use it for |
|---|---|
| Creator marketing | Find accounts by keyword, then pull their posts and engagement in the same run |
| Brand monitoring | Watch a hashtag feed and read what commenters actually say |
| Agencies | One input shape across every client request instead of seven actors to explain |
| Researchers | Keyword search with exact limits, so a sample size is a sample size |
| Dashboards | One row shape means one schema to maintain downstream |
How It Works

- You pick a mode and pass a list of things to scrape.
- The actor reads each entry, resolving share links and profile URLs as needed.
- Results are collected page by page, deduplicated by id, and stopped at exactly the count you asked for.
- If the primary source runs dry mid-keyword, a second source continues rather than reporting a thin result as the whole of TikTok.
- Rows are written with
rowTypeandsourceattached, so a mixed run stays sortable.
Input Configuration
| Field | Type | Default | Applies to |
|---|---|---|---|
mode | string | profile | required |
input | array | required | all modes |
maxResults | integer | 100 | hashtag, search, users, comments |
includeVideos | boolean | false | profile |
maxVideosPerProfile | integer | 100 | profile, videos |
strictHashtagMatch | boolean | false | hashtag |
minFollowers | integer | 0 | users |
maxFollowers | integer | none | users |
verifiedOnly | boolean | false | users |
includeReplies | boolean | false | comments |
maxRepliesPerComment | integer | 50 | comments |
includeMediaUrls | boolean | true | post |
includeAuthorStats | boolean | true | post |
includeHashtagsMentions | boolean | true | post |
Example: an account and its recent posts
{ "mode": "profile", "input": ["@gymshark"], "includeVideos": true, "maxVideosPerProfile": 30 }
Example: what a hashtag is actually tagged with
{ "mode": "hashtag", "input": ["#coffee"], "maxResults": 200, "strictHashtagMatch": true }
Example: mid-tier creators in a niche
{ "mode": "users", "input": ["fitness coach"], "minFollowers": 10000, "maxFollowers": 200000 }
Output Overview
Three row types, told apart by rowType.
video comes from profile, videos, hashtag and search. The same 21 core fields in every case, even though those modes read two different TikTok payloads behind the scenes. Hashtag rows carry a few extra fields the web feed provides.
account comes from profile and users.
comment comes from comments mode. Replies carry isReply: true and the parentCommentId they belong to.
post is its own richer type, from post mode only: slideshow images, repost count, ad and AI-generated flags, duet and stitch settings, media URLs.
Output Sample
A video row, from a search run on "latte art":
{"rowType": "video","source": "latte art","postId": "7112843091046010118","postUrl": "https://www.tiktok.com/@tannercolson/video/7112843091046010118","caption": "How to Pour Latte Art - Milk Steaming Basics","createdAt": "2026-06-14T18:22:11.000Z","durationSeconds": 43,"isPinned": false,"playCount": 412254,"likeCount": 28911,"commentCount": 402,"shareCount": 1873,"saveCount": 9204,"authorId": "6749884166599225349","authorUsername": "tannercolson","authorNickname": "Tanner Colson","authorFollowerCount": 288400,"musicId": "7112843060234","musicTitle": "original sound","coverUrl": "https://p16-sign.tiktokcdn-us.com/...","scrapedAt": "2026-08-22T21:14:03.221Z"}
An account row, from users:
{"rowType": "account","source": "fitness coach","username": "stephycrismatt","nickname": "Stephy Crismatt","userId": "6721944883108135942","profileUrl": "https://www.tiktok.com/@stephycrismatt","bio": "Coach · Programs below","isVerified": false,"verificationSource": "search","followerCount": 425074,"followingCount": 812,"likeCount": 9440221,"videoCount": 1204,"region": "US","scrapedAt": "2026-08-22T21:15:40.118Z"}
Key Output Fields
Every row: rowType, source, scrapedAt
Video: postId, postUrl, caption, createdAt, durationSeconds, isPinned, playCount, likeCount, commentCount, shareCount, saveCount, authorId, authorUsername, authorNickname, authorFollowerCount, musicId, musicTitle, coverUrl
Account: username, nickname, userId, secUid, profileUrl, bio, isVerified, followerCount, followingCount, likeCount, videoCount, region
Comment: commentId, text, likeCount, replyCount, isReply, parentCommentId, commenterUsername, commenterVerified, isPinnedByAuthor, isLikedByAuthor
Post: everything a video row has, plus postType, repostCount, isAd, isAigc, duetEnabled, stitchEnabled, hashtags, mentions, videoUrl, imageUrls
FAQ
Why one actor instead of seven separate ones? Because one input shape and one output schema is less work than seven. The specialist actors remain published for anyone who prefers them.
Are video rows really the same across modes? Yes, and it took work. Profile, videos and search read TikTok's mobile payload while the hashtag feed reads its web payload, with different field names for the same things. Both are normalised to one shape here. Hashtag rows carry a few extra fields the web payload genuinely provides.
Why does a hashtag run return posts without that hashtag?
TikTok's hashtag feed is a related-content feed, not a tag index. On a live #coffee feed, 23 of 37 posts actually carried the tag. Set strictHashtagMatch to drop the rest.
I asked for 40 results and got 40. Is that normal? It is here. Limits are honoured exactly rather than rounded up to whatever a page holds.
Why is verificationSource on account rows?
Because account search is a weaker source for the verified badge than a profile lookup. The field tells you which one you are reading, so you know how much to trust it. Run profile mode when the badge has to be authoritative.
What happens if a run hits its time limit? It stops cleanly and returns what it collected, with a warning naming the count. A partial result beats a dead run.
Do I need a proxy or a TikTok account? No. No login, no cookies, no proxy configuration, and nothing to solve.
Support
Found a bug or missing a field? Open an issue on the actor's Issues tab.
Additional Services
Need a mode that is not here, a scheduled feed into your own warehouse, or a custom field set? Describe it on the Issues tab.
Explore More Scrapers
The specialist TikTok actors behind this bundle stay published, along with actors for TikTok Shop, Instagram, YouTube, LinkedIn and more. Browse the publisher profile.
🤖 For AI Agents & LLM Apps
Compact reference for AI agents calling this actor via the Apify MCP server or the Apify API (actor: memo23/tiktok-scraper).
Purpose: one TikTok actor with seven modes over accounts, posts, hashtags, keyword search, comments and account discovery.
Minimal input:
{ "mode": "profile", "input": ["@gymshark"] }
Output: one row per item, tagged by rowType — video, account, comment or post. Video rows: rowType, source, postId, postUrl, caption, createdAt, durationSeconds, isPinned, playCount, likeCount, commentCount, shareCount, saveCount, authorId, authorUsername, authorNickname, authorFollowerCount, musicId, musicTitle, coverUrl, scrapedAt.
Behaviors an agent should know:
modedecides whatinputmeans. Passing usernames with modesearchwill search for them as keywords.- Always set
maxResults(hashtag, search, users, comments) ormaxVideosPerProfile(profile, videos). Uncapped runs on a busy hashtag are large. - Limits are exact, so plan cost from the number you ask for.
- Branch on
rowType, not on the mode you requested:profilewithincludeVideosreturns bothprofileandvideorows. - A target that cannot be delivered yields one row carrying
errorandmessage; the run still ends SUCCEEDED. Check forerrorbefore treating a row as data. - Billing: every delivered row is charged. Error rows are charged too, so filter inputs before large runs.
⚠️ Disclaimer
This Actor accesses publicly available data on TikTok for legitimate research and business-analysis purposes. It does not log in, bypass authentication, or access private content. Use of this Actor must comply with TikTok's Terms of Service and all applicable laws, including data-protection regulations (GDPR, CCPA, etc.). The authors are not responsible for any misuse. Users must:
- Respect rate limits and avoid overloading TikTok's infrastructure
- Not use scraped data to violate user privacy or platform terms
- Process any personal data only with a lawful basis and in compliance with their jurisdiction
- Not republish scraped content in violation of copyright
We do not store scraped data; the Actor returns it directly to your Apify dataset for your authorized use. TikTok is a trademark of ByteDance Ltd.; this Actor is not affiliated with or endorsed by TikTok or ByteDance.
SEO Keywords
tiktok scraper, tiktok api, tiktok profile scraper, tiktok video scraper, tiktok hashtag scraper, tiktok search scraper, tiktok comments scraper, tiktok user search, tiktok data extraction, tiktok analytics tool, tiktok creator discovery, tiktok engagement data, scrape tiktok without login, tiktok influencer research, social media scraper, tiktok content research, tiktok post metrics, tiktok bulk scraper, tiktok no proxy scraper, tiktok mcp server