TikTok Scraper - Profiles, Videos, Hashtags & Search
Scrape TikTok profiles, videos, hashtags and search. Play, like, comment and share counts. No login needed from you. $0.25 per 1,000.
How it works
- 1Open it on Apify
Hit Run on Apify — it opens the tool in the cloud, no install.
- 2Set the inputs
Adjust
profiles,hashtags,searchQueries(sensible defaults are pre-filled). - 3Click Run
The tool runs on Apify’s cloud and collects the data for you.
- 4Export the results
Download as JSON, CSV or Excel, or pipe straight into your app, Google Sheets, or an AI agent.
Pricing
$0.00025 per result = $0.25 per 1,000
| You are charged for | When | Price |
|---|---|---|
| Result returned | Charged once per profile or video returned in the dataset. Failed or empty runs are not charged. | $0.00025 |
Pay-per-event pricing: you are billed per result, not per subscription. Billing is handled by Apify on your own account. These are the live Apify store prices, in effect since 2026-08-19, and they are what you are actually charged.
Inputs
| Field | What it does | Type |
|---|---|---|
profiles | TikTok usernames (with or without @) to scrape. Each one returns a profile row (followers, likes, bio, verified) plus that creator's ~10 newest videos, that is all TikTok publishes for a creator without a login. | array |
hashtags | Hashtags (with or without #) to scrape videos from. | array |
searchQueries | Keywords to search TikTok for. | array |
startUrls | Paste TikTok URLs directly, a profile URL, a /video/ URL (single video), or a /tag/ URL (hashtag). | array |
resultsPerPage | Maximum number of videos/results to collect per profile, hashtag or search. You are charged per result returned. Note: a single profile yields about 11 rows maximum (1 profile + ~10 videos) no matter how high this is set; hashtag and search page much deeper. | integer |
maxRunSeconds | Safety cap on total scrape time. If a slow query (e.g. a search/feed that keeps paginating with few results) hits this, the run stops and returns what it has so far. Prevents runaway cost on pathological queries. | integer |
notionConnector | Optional. Deliver the results to your connected Notion via Apify MCP connectors. | string |
notionParentId | Optional Notion database/data-source id to create the pages in. | string |
sessionCookies | Optional. Runs work without your account. Paste your own TikTok account cookie here and the run uses your account. In Chrome: F12 → Application → Cookies → tiktok.com, and copy at least `sessionid` (e.g. `sessionid=abc123; sid_tt=abc123`). Only used for TikTok's own pages, it is never sent anywhere else. | array |
What you get
A structured dataset — each result includes fields like:
typeidwebVideoUrltextcreateTimehashtagsplayCountdiggCountcommentCountshareCountvideomusicauthorExport every run as JSON, CSV or Excel, or send it to your app, a database, Google Sheets, or an AI agent.
5 ready-to-run use cases
TikTok Profile Scraper - Export a Creator's Videos
Export a public TikTok creator's videos: caption, play, like, comment and share counts, duration and video URL. Swap in any handle. No login needed.
TikTok Hashtag Scraper - Trending Videos by Tag
Pull the videos running under any TikTok hashtag, with play, like, comment and share counts. Change the tag and run it. No login and no API key.
Search TikTok Videos Without an Account
Search TikTok by keyword and get the matching videos as rows: caption, creator, play and like counts and the video URL. No account, no login.
TikTok Competitor Analysis - Track a Rival Account
See what a competitor posts on TikTok and how it performs: captions, play counts and engagement per video. Works on any public account.
TikTok Data Scraper - Export Videos From a URL
Paste a TikTok profile or video URL and export the videos behind it: caption, creator, play, like and comment counts, duration and URL.
Related tools in Social Media Scrapers
Other ready-to-run tools in the same category — all pay-per-use on the Apify cloud.
Instagram Scraper - Profiles, Posts & Reels (No Login)
Scrape Instagram profiles, posts and reels as JSON: followers, caption, likes, comments, media URLs. No login or API key. $0.45 per 1,000 items.
Tweet Scraper
Scrape X (Twitter) tweets by handle or URL, no API key. Rows carry text, likes, retweets, views and author. Search needs your X cookie.
Twitter (X) User Scraper - Profiles & Followers, No Login
Scrape X (Twitter) profiles: followers, following, post count, name, bio and verification. No API key, no login. $0.14 per 1,000 profiles.
TikTok User Scraper - Profiles, Followers & Stats (No Login)
Scrape TikTok profiles without a login. Get follower, following, likes and video counts, bio, verified flag and avatar. $0.35 per 1,000 profiles.
Reddit Scraper
Scrape Reddit posts with no login or API key. Rows carry titles, selftext, scores, authors, comment counts and permalinks. $0.50 per 1,000 rows, flat.
Reddit Posts Search Scraper
Search Reddit by keyword: title, post text, author, subreddit, permalink and dates. Add a free Reddit app for scores. $0.891 per 1,000 posts.
Where this tool sits
- Categories
- Social Media Scrapers
- Platforms
- TikTok
TikTok Scraper: videos and profiles by handle, hashtag, keyword or link
One actor for four ways into TikTok. Give it handles, hashtags, search terms or pasted links and you get flat rows back: videos with plays, likes, comments, shares and saves, the caption, the sound, the author and the file links, and profiles with followers, lifetime likes, bio and the verified flag. Nothing to log into.
The limit to know before you spend anything: a profile returns about a dozen rows, the profile itself plus its ten or eleven newest videos. That is what TikTok publishes for a creator to a signed-out visitor, and no value of resultsPerPage gets past it. Hashtags and keyword searches page much deeper, so those are the modes to use when you want volume.
| Input | Handles, hashtags, keywords, or TikTok links |
| Output | One row per profile or video |
| Ceiling | 2,000 rows per run, of which a profile gives about 12 |
| Account needed | None from you |
| Price | $0.25 per 1,000 rows, flat on every plan |
🔍 What TikTok Scraper does
Four modes, and you can mix them in one run:
| You give it | You get |
|---|---|
profiles | The profile row, then its newest videos, about a dozen rows per handle |
hashtags | Videos posted under the tag, paging as deep as your limit allows |
searchQueries | Videos TikTok returns for the keyword |
startUrls | A profile link, a /video/ link for one video, or a /tag/ link |
resultsPerPage is the total for the whole run, not per input, which matters when you list several: once the first hashtag has used the allowance, the second returns nothing. Run them separately if you want a fair split.
Rows are deduplicated inside a run, so a video appearing under two of your hashtags is returned and billed once. maxRunSeconds stops a slow feed and hands back what it has so far, which keeps a pathological search from running up a bill.
📥 What you give it
{
"profiles": ["nasa"],
"hashtags": ["spacex"],
"resultsPerPage": 50,
"maxRunSeconds": 90
}
| Field | Default | What it is |
|---|---|---|
profiles | none | Handles with or without @. The form opens with nasa filled in as an example, which is a starting point rather than a default. |
hashtags | none | Tags with or without #. |
searchQueries | none | Keywords to search TikTok for. |
startUrls | none | Links pasted straight in: a profile, a /video/ link, or a /tag/ link. |
resultsPerPage | 50 | Rows for the whole run, 1 to 2,000, despite what the field name suggests. This is also your spend cap. |
maxRunSeconds | 90 | Stops the scrape at this point and returns what it has, 10 to 180. Raise it if you would rather have the rows than the time back. |
sessionCookies | none | Optional. Your own TikTok sessionid, which mainly helps on age-restricted or otherwise gated videos. Use a throwaway account: the value sits in the run input, which anyone who can open the run can read. |
proxyConfiguration | off | Leave it off. It exists for people routing through their own servers at high volume. |
notionConnector, notionParentId | none | Optional. Write each row into a Notion database as well as the dataset. |
Run it with nothing at all and you get one labelled sample row, free, so you can see the shape first.
📤 What you get back
A real video row from a real run. The caption ends with an emoji, so it is cut short here, and the media links are trimmed:
{
"ok": true,
"type": "video",
"id": "7358577498319342891",
"webVideoUrl": "https://www.tiktok.com/@francov9/video/7358577498319342891",
"text": "Got me feeling like Snow White and shii... #fyp #cats #disneyprincess",
"createTime": "2024-04-16T21:19:04.000Z",
"hashtags": ["fyp", "cats", "disneyprincess"],
"region": "US",
"playCount": 17912733,
"diggCount": 3674504,
"commentCount": 12854,
"shareCount": 244131,
"collectCount": 282047,
"downloadCount": 8092,
"isAd": false,
"video": { "duration": 11, "cover": "https://p16-common-sign.tiktokcdn-us.com/...", "playAddr": "https://v45.tiktokcdn-us.com/...", "downloadAddr": "https://v45.tiktokcdn-us.com/..." },
"music": { "id": "7402610556690860833", "title": "kagefumi", "authorName": "-", "original": true, "duration": 36 },
"author": { "id": "6806757644620350470", "uniqueId": "francov9", "nickname": "Franco V.", "avatar": "https://p19-common-sign.tiktokcdn-us.com/..." }
}
Check type to tell the two shapes apart.
| Field | On which row | What it is |
|---|---|---|
id, webVideoUrl | video | Unique per video, and the link a person can open. |
text, hashtags | video | The caption, and the tags parsed out of it. Empty when the creator used none. |
playCount, diggCount, commentCount, shareCount, collectCount, downloadCount | video | Views, likes, comments, shares, saves and downloads at read time. |
video, music, author | video | Duration and file links, the sound (or null), and the account that posted it. |
uniqueId, nickname, signature, verified | profile | Handle, display name, bio and the blue tick. |
followerCount, heartCount, videoCount | profile | Audience, lifetime likes and how many videos are on the account. |
secUid, url | profile | The id that survives a rename, and the canonical profile link. |
🧾 Reading the output
Three kinds of row can land in your dataset.
| Row | How to spot it | Billed |
|---|---|---|
| A profile or a video | ok: true and a type | yes |
| The sample row | _sample: true | no |
| A diagnostic | ok: false and an errorCode | no |
Filter on ok == true and you have your data. NOT_FOUND means TikTok showed the handle, video or tag as gone or private. BAD_INPUT means a handle carried characters TikTok does not use. RATE_LIMITED, BLOCKED, SERVER_ERROR and NETWORK all mean that item would not answer this run, which re-running usually clears. NO_RESULTS is the row you get when nothing came back at all. None of them is charged, and the run carries on to the next input.
One quirk of the Overview table: its columns are the video ones, so a profile row shows almost nothing there and a diagnostic reads as a blank line. Open the row itself or download the JSON and everything is present.
▶️ How to run it
1. Open TikTok Scraper and click Try for free. 2. Fill in whichever box fits: Profiles, Hashtags, Search queries or Start URLs. 3. Set Max videos per input. It is the total for the run, so start at 50 while you look at the output shape. 4. Click Start. 5. Download the dataset as JSON, CSV or Excel, or pull it from the Apify API.
💰 How much does it cost?
$0.25 per 1,000 rows. Flat on every Apify plan, no volume tiers. A profile row and a video row cost the same.
You pay for rows that carry data. The sample row, diagnostic rows and duplicates caught inside a run are not charged. resultsPerPage is the ceiling on both the rows and the spend.
💡 What people use it for
- Watching a set of creators: run the handles weekly and diff the counts on their newest videos.
- Pulling everything under a campaign hashtag, then reading the captions for how people talk about it.
- Keyword research: search a phrase and see which videos TikTok actually surfaces for it.
- One-off checks on a single video from a link somebody dropped in a channel.
🚧 What it does not do
- A profile is not an archive. About a dozen rows per handle, and no input value changes that.
- No comments, followers or reply threads. Comments are a separate actor, linked below.
- The limit is shared across your inputs. One greedy hashtag can use the whole run.
- A private account still costs you its profile row. You get the profile, then a
NOT_FOUND
row telling you the videos are private.
- A video row can arrive with
nullcounters when only the short public entry was available,
and it is still a delivered row.
- A missing counter on hashtag and search rows reads as
0. maxRunSecondscuts quietly. When it fires you get a partial result and no row saying so, so
check the log if a count looks short.
- Media links expire. They are signed and short lived. Fetch the file during the run if you
want to keep it.
🧭 Which TikTok scraper do you need?
| If you want | Use |
|---|---|
| A bit of everything: profiles, hashtags, search, single videos | This one |
| Follower and likes counts for a long list of handles | TikTok Profile Scraper |
| To page deep into one hashtag | TikTok Hashtag Scraper |
| Comments under a video | TikTok Comments Scraper |
| Which hashtags are climbing right now | TikTok Trending Hashtags |
❓ Questions people ask
Why did a profile only return 12 rows? Because that is what TikTok publishes for a creator to a signed-out visitor. The limit is TikTok's, not the actor's.
Is resultsPerPage per input or per run? Per run. The field reads "Max videos per input", but the number you set is the total the run will deliver.
Can I get every video an account ever posted? No signed-out route reaches the full back catalogue. Hashtag and search modes are where the depth is.
What happens when a run hits maxRunSeconds? It stops and keeps what it already collected. You are charged for the rows you got and nothing else.
Is scraping TikTok legal? This reads public profiles and public videos only, never private accounts or messages. Results can still contain personal data, which GDPR and similar laws cover, so have a reason for collecting it. Apify's write-up on the legality of web scraping is a good starting point, and we are not lawyers.
Can I run it on a schedule? Yes. Use Apify's scheduler, or start it from the API and read the dataset when it finishes.
🆘 If something breaks
Open the Issues tab on the actor page. Include the handles, tags or links you used and the run ID, and the log is usually enough for us to see what happened.