TikTok Scraper - Videos, Profiles and Hashtags, No Login
Pricing
from $0.25 / 1,000 result returneds
TikTok Scraper - Videos, Profiles and Hashtags, No Login
Scrape TikTok videos, profiles and hashtags. A profile page carries about ten videos, so a profile returns its own row plus those. Hashtag, keyword and video URL modes go deeper. You get play, like, comment, share and save counts. Also the sound, author and hashtags. $0.25 per 1,000.
Pricing
from $0.25 / 1,000 result returneds
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
11
Total users
5
Monthly active users
2 days ago
Last modified
Categories
Share
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
- Open TikTok Scraper and click Try for free.
- Fill in whichever box fits: Profiles, Hashtags, Search queries or Start URLs.
- Set Max videos per input. It is the total for the run, so start at 50 while you look at the output shape.
- Click Start.
- 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_FOUNDrow 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.