TikTok Hashtag Views Scraper - Sounds, Profiles, Video Stats
Pricing
$2.49 / 1,000 result rows
TikTok Hashtag Views Scraper - Sounds, Profiles, Video Stats
68 columns per video, 59 filled on average, and 40 per profile, measured on live accounts with no proxy and no login. TikTok video metrics, TikTok hashtag views and captions to filter on; watch mode returns only new or changed videos, and unchanged items are not charged.
Pricing
$2.49 / 1,000 result rows
Rating
0.0
(0)
Developer
Snow Leo Data
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
7 days ago
Last modified
Categories
Share
TikTok Scraper — Profiles, Videos, Hashtags
Scrape TikTok profiles, videos, hashtags and sounds straight from the public pages. No login, no cookies, no proxies, no browser — a plain HTTP client and the Python standard library.
Every number below was measured on 2026-09-17 and can be reproduced with the commands at the bottom of this page.
What you get
Profile rows — 40 columns. Handle, display name, bio, bio link, avatar, verification, private flag, followers, following, total likes, video count, diggs, friends, account creation date, secUid, language, seller and commerce flags, comment / duet / stitch / download settings, following visibility. On live profiles 33 of the 40 columns come back filled.
Video rows — 68 columns, 59 filled on average. Views, likes, comments, shares, saves and reposts; caption, hashtags, mentions, publication time, duration; music id, title, author, duration, copyright and original flags; cover, dynamic cover and download links; width, height, definition, format, codec, bitrate, file size and TikTok's own video quality score; content categories, caption language, country of creation, AI-generated flag, slideshow images, duet / stitch / share / comment permissions.
Hashtag rows. The hashtag's own totals — total views and total video count
— which the public hashtag page itself does not show anywhere. Measured:
#funny 8 645 247 703 414 views over 341 846 664 videos, #fyp
128 091 069 010 621 views over 9 291 323 819 videos, #cooking
548 013 780 675 views over 18 922 488 videos.
Sound rows. Sound id, title, author and how many videos use it.
What it costs to run
Two measured runs, both at 1024 MB, five profiles and three hashtags:
| mode | rows | time | platform cost | per 1 000 rows |
|---|---|---|---|---|
| full video metrics | 98 | 15.9 s | $0.001554 | $0.0159 |
views only (includeVideoDetails: false) | 98 | 4.7 s | $0.000867 | $0.0088 |
The full-metrics run made 103 requests and downloaded 8.5 MB. Requests are
sent with Accept-Encoding: gzip, which is not a detail: the profile page is
370 091 bytes uncompressed and 84 941 compressed, the video page 405 896
against 89 333 — 4.36 times less traffic for the same data.
The one limit you should know before you buy
TikTok publishes 10 to 13 videos per creator without a signature, and this actor returns those. Measured on eight accounts: nasa 11, tiktok 10, khaby.lame 10, zachking 12, bbc 13, nba 13, gordonramsayofficial 12, duolingo 11. A hashtag gives 10 videos, a sound gives 6.
This is a wall in the source, not a setting. count, cursor, page,
offset and the path form /page/N were all tried: the response is
byte-identical, and the union over eight pages is still the same 11 videos.
The signed endpoint that would return more (tiktok.com/api/post/item_list/)
answers HTTP 200 with exactly zero bytes without a browser-generated
signature — a polite refusal that looks like success, and this actor treats it
as the failure it is.
If you need the full back catalogue of a creator, you need a browser-based scraper with residential proxies, and it will cost you accordingly. If you need current numbers for accounts, recent videos, hashtags and sounds, this actor does it without either.
Watch mode
onlyNewOrChanged remembers what earlier runs delivered in a named key-value
store and returns only what is new or what moved, marked NEW or UPDATED in
change_type. Unchanged items are not returned and not charged. Set
emitUnchanged to see them anyway.
Two honest notes. Cover and file links are signed afresh on every request, so
they are deliberately left out of the change fingerprint — otherwise every
video would look updated every run. And hashtag totals move continuously: two
requests seconds apart returned different view counts for #cooking, so
hashtag rows will nearly always be UPDATED.
Filters, and which of them are free
minPlayCount, postedAfter, postedBefore and textContains work without
opening a single video page: views, caption and the publication time all come
from the creator card, the last one read out of the video ID itself.
minDiggCount and minCommentCount exist only on the video page. Asking for
them with includeVideoDetails: false would otherwise return zero rows, so the
run switches details on by itself and says so in the log and in the report
field details_forced_by.
Publication time from the video ID is a day-level estimate, and rows that use
it carry created_at_is_estimated: true. Measured against the exact value on
nine videos: six matched within 25 seconds, three drifted by 37 minutes,
86 minutes and 18.5 hours — scheduled posts. With full video metrics on, the
exact time from the page is always used.
A filter never drops a row whose field is empty. Missing data is not a mismatch.
Empty results always name their cause
A green run with an empty dataset is the worst kind of failure, so this actor
never stays silent about one. The report record REPORT carries
empty_reason, and the log carries the same sentence in words:
empty_reason | what happened |
|---|---|
videos-disabled-but-only-videos-wanted | outputTypes asks for videos while includeVideos is off |
videos-disabled-but-no-other-source | only profiles given, videos off, profile rows not requested |
charge-limit-reached | the run's spending limit was already used up |
filtered-out | rows were collected and your filters removed all of them |
nothing-changed | watch mode: everything had already been delivered |
source-refused | TikTok returned nothing usable for any target |
source-returned-nothing | pages opened but held no profiles, videos or hashtags |
The first two are decided from the input alone, before a single request is sent, so a contradictory input costs you nothing.
A run with no targets at all is not an error: it scrapes the demo profile
@nasa, says so in the log and records demo_target in the report, so a
scheduled run never looks broken just because a field was left blank.
Input
| field | meaning |
|---|---|
profiles | handles or profile URLs: nasa, @nasa, https://www.tiktok.com/@nasa |
videoUrls | direct video links or bare IDs; always returned fully detailed |
hashtags | hashtags without # |
sounds | sound IDs or music URLs |
maxItems | hard cap on rows written; limits the output, not the crawl |
maxVideosPerSource | quota per target, so one account cannot eat the whole run |
includeVideos | collect videos at all |
includeVideoDetails | open each video page for the full metrics |
outputTypes | which of profile / video / hashtag / sound rows to keep |
minPlayCount, minDiggCount, minCommentCount | engagement floors |
postedAfter, postedBefore, textContains | date and caption filters |
onlyNewOrChanged, emitUnchanged | watch mode |
compactOutput, excludeEmptyFields | narrow output for AI agents and spreadsheets |
concurrency | parallel page requests, 1 to 8 |
What this actor does not do
Named plainly, because finding out after paying is worse than reading it here:
- no keyword search.
tiktok.com/searchcarries no data in the page andapi/search/general/fullanswers 200 with zero bytes without a signature. - no comments. The comment endpoint is signed.
- no follower or following lists. Same reason.
- no video, image or subtitle file downloads, no transcripts, no AI descriptions. Cover and download links are in the output; fetching the media is not.
- no full back catalogue per creator — see the limit section above.
- no
isPinned,isSponsored,isStoryor place-of-posting fields. They are not on the public pages this actor reads.
Reproducing the numbers
python3 tests/test_logic.py # 60 checks on payloads captured from live pagespython3 tools/run_live.py # the live suite, executed in the Apify cloudpython3 tests/test_lifecycle.py # interruption, repeat runs, memory, spend limitpython3 tools/verify_readme.py # every number in this file against the codepython3 tools/prove.py # breaks the code on purpose; the suites must fail
The live suite runs in the cloud on purpose. From a home address
tiktok.com/@user returns a 1 462-byte stub; from Apify it returns 370 273
bytes with the data. A local "success" here would be a lie.