TikTok Video Scraper - Views, Likes & Hashtags avatar

TikTok Video Scraper - Views, Likes & Hashtags

Pricing

from $1.00 / 1,000 video scrapes

Go to Apify Store
TikTok Video Scraper - Views, Likes & Hashtags

TikTok Video Scraper - Views, Likes & Hashtags

TikTok video scraper that returns views, likes, comments, shares, saves and reposts for any list of video URLs, plus hashtags, sound, exact post date and the creator's follower count. No login, no API key, no browser.

Pricing

from $1.00 / 1,000 video scrapes

Rating

0.0

(0)

Developer

Eimantas V

Eimantas V

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

13 hours ago

Last modified

Categories

Share

TikTok Video Scraper — Views, Likes & Hashtags

TikTok video scraper that returns views, likes, comments, shares, saves and reposts for any list of video URLs, plus hashtags, the sound, the exact post date and the creator's follower count. No login, no API key, no browser.

Paste video URLs, get a spreadsheet of engagement. It is built for the job most TikTok data actually gets bought for: measuring how a specific set of posts performed — a campaign's deliverables, a competitor's last thirty uploads, a hashtag's top posts you collected elsewhere.

What you get

One row per video. Every field below was populated on a real captured video; null means TikTok did not return it, never a stand-in zero.

FieldTypeNotes
playCountinteger | nullViews
likeCountinteger | null
commentCountinteger | null
shareCountinteger | null
collectCountinteger | nullSaves
repostCountinteger | nullOnly present in TikTok's newer stats block
engagementRatenumber | null(likes+comments+shares) ÷ views, as a %
descriptionstring | nullThe caption
createdAtstring | nullA real UTC timestamp, not a relative string
createdAtUnixinteger | null
hashtagsarrayTags the creator typed, in caption order and original casing
challengesarrayEvery challenge TikTok associates — a superset of the above
mentionsarray@-handles in the caption
musicTitle / musicAuthor / musicIdstring | nullThe sound
musicIsOriginalboolean | nullOriginal audio vs a licensed track
durationSeconds / width / heightinteger | null
coverUrlstring | null
authorHandle / authorName / authorIdstring | null
authorFollowerCountinteger | nullThe creator's followers at scrape time
authorHeartCount / authorVideoCountinteger | null
authorVerifiedboolean | null
authorSignaturestring | nullCreator bio
isAdboolean | nullBranded content flag
isAigcboolean | nullAI-generated content flag
locationCreatedstring | nullCountry code
duetEnabled / stitchEnabledboolean | null
commentsDisabledboolean | null

Engagement rate is null when it cannot be computed

If views are missing or zero, engagementRate is null rather than 0 or Infinity. A rate over an unknown denominator is not a measurement, and a buyer sorting on it would otherwise be sorting on an artefact.

hashtags and challenges are different things, and are kept apart

TikTok exposes hashtags in two places that disagree, and the longer list is not the better one.

hashtags is what the creator actually typed. It comes from the caption, with character offsets that prove where each tag appears, so it preserves the creator's own casing rather than TikTok's normalised form.

challenges is TikTok's own association set. It uses canonical casing and it can include tags that appear nowhere in the caption. On the video used to build this Actor the two differed twice over: the creator typed #petsoftiktok, challenges reports it as PetsOfTikTok, and challenges additionally carried bonevoyage — a tag the caption never contained. Merging them would have made every row assert something false about the creator, so the two stay separate.

Use hashtags for "what did they tag this with". Use challenges for reach and discovery analysis, where TikTok's own associations are the point.

Input

{
"videos": [
"https://www.tiktok.com/@scout2015/video/6718335390845095173",
"https://www.tiktok.com/@nasa/video/7016181555718065413",
"6718335390845095173"
],
"maxVideos": 1000,
"requestDelayMs": 1500
}

Full video URLs, photo-post URLs, /v/ and /embed/v2/ links, and bare numeric ids all work; extra query parameters are ignored. You can also chain from another Actor's dataset with sourceDatasetId.

Pricing

EventPriceWhen
video-scraped (primary)$1.00–$2.00 per 1,000Per video row written
apify-actor-start$0.00005Once per run

Your whole bill is videos × row price + $0.00005. One request produces one row, so there is no second event and nothing to forecast around.

Never charged: error rows of any kind; a video TikTok reports as deleted or non-existent; inputs that are not readable video URLs; and any request that came back blocked and was retried. Full arithmetic and the measured cost basis are in docs/PRICING.md.

What this does NOT do

Stated plainly, because a listing that overpromises collects one-star reviews:

  • No comments. TikTok's comment endpoint was measured to answer either a 91-byte status_code: 5 envelope or an HTTP 200 with zero bytes unless the request carries a rotating X-Bogus/msToken signature. Reverse-engineering a rotating signature is a maintenance treadmill, so this Actor does not pretend to offer comments.
  • No video discovery. You supply the video URLs. Profile pages, tag pages, the explore feed and music pages were all measured to carry no video list server-side — zero ids across every route tried. Pair this with a discovery Actor if you need to find videos first.
  • No profile-only scraping. Pass videos. A profile URL is rejected with a message telling you so.
  • No video file downloads or transcripts.
  • No vm.tiktok.com short links. Expanding one needs a redirect this Actor does not follow; it is rejected with a message rather than guessed at.
  • No historical or time-series data. Every count is as of the moment it was scraped. Run it on a schedule if you want a series.
  • Private and deleted videos return an error row, not data.

How it works, and the honest part

One plain HTTP GET per video. TikTok server-renders the full video metadata into the watch page, so there is no browser, no login, no cookie, no API key and — the part that matters for durability — no signed request. Nothing here rotates on a TikTok deploy.

Reliability

  • Measured 19/20 on real videos from Apify datacenter IPs, the single miss a timeout rather than a block. Datacenter is the IP class the platform actually runs on, which is why that is the number quoted rather than a residential one.
  • Deleted is distinguishable from blocked. TikTok answers a missing video with HTTP 200 and statusCode 10204 / "item doesn't exist", where a block has no rehydration payload at all. Those become different rows: a typed video-not-found error that is never billed, versus a retry on a fresh IP.
  • Blocked requests are retried on a different datacenter IP, twice, with a hard backoff. A not-found is never retried — TikTok will say the same thing from every IP, so retrying spends requests to learn nothing.
  • The id is checked on the way out. TikTok serves a video even when the handle in the URL is wrong, so the Actor refuses to emit a row whose returned id does not match the one requested.
  • The response gate never keys on size. A not-found page measured 369 KB against a real page's 394 KB — close enough that any size threshold would misclassify. Only shape is used.

robots.txt

You should know this before you buy, so it is here rather than buried. https://www.tiktok.com/robots.txt disallows a broad set of paths and bans several named crawler user-agents outright. This Actor requests the ordinary public watch page, sends no credentials, and bypasses no authentication or access control — it reads what any logged-out visitor sees. Whether that is acceptable for your purpose is a decision for you and your legal advisers, and it depends on your jurisdiction and what you do with the data.

Proxy

Apify datacenter proxy, on by default, and used to rotate IPs when a video comes back blocked. Residential is deliberately not offered: it is billed per gigabyte, and at 87 KB per video it would dominate the cost of a run for a transport that was measured not to need it.