TikTok Hashtag Views Scraper - Sounds, Profiles, Video Stats avatar

TikTok Hashtag Views Scraper - Sounds, Profiles, Video Stats

Pricing

$2.49 / 1,000 result rows

Go to Apify Store
TikTok Hashtag Views Scraper - Sounds, Profiles, Video Stats

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

Snow Leo Data

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

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:

moderowstimeplatform costper 1 000 rows
full video metrics9815.9 s$0.001554$0.0159
views only (includeVideoDetails: false)984.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_reasonwhat happened
videos-disabled-but-only-videos-wantedoutputTypes asks for videos while includeVideos is off
videos-disabled-but-no-other-sourceonly profiles given, videos off, profile rows not requested
charge-limit-reachedthe run's spending limit was already used up
filtered-outrows were collected and your filters removed all of them
nothing-changedwatch mode: everything had already been delivered
source-refusedTikTok returned nothing usable for any target
source-returned-nothingpages 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

fieldmeaning
profileshandles or profile URLs: nasa, @nasa, https://www.tiktok.com/@nasa
videoUrlsdirect video links or bare IDs; always returned fully detailed
hashtagshashtags without #
soundssound IDs or music URLs
maxItemshard cap on rows written; limits the output, not the crawl
maxVideosPerSourcequota per target, so one account cannot eat the whole run
includeVideoscollect videos at all
includeVideoDetailsopen each video page for the full metrics
outputTypeswhich of profile / video / hashtag / sound rows to keep
minPlayCount, minDiggCount, minCommentCountengagement floors
postedAfter, postedBefore, textContainsdate and caption filters
onlyNewOrChanged, emitUnchangedwatch mode
compactOutput, excludeEmptyFieldsnarrow output for AI agents and spreadsheets
concurrencyparallel 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/search carries no data in the page and api/search/general/full answers 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, isStory or 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 pages
python3 tools/run_live.py # the live suite, executed in the Apify cloud
python3 tests/test_lifecycle.py # interruption, repeat runs, memory, spend limit
python3 tools/verify_readme.py # every number in this file against the code
python3 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.