TikTok User Profile and Video Insights Scraper avatar

TikTok User Profile and Video Insights Scraper

Pricing

from $5.99 / 1,000 results

Go to Apify Store
TikTok User Profile and Video Insights Scraper

TikTok User Profile and Video Insights Scraper

Scrape TikTok user profiles and video insights, including usernames, bios, followers, likes, video views, captions, hashtags, engagement metrics, and posting details. Ideal for creator research, competitor analysis, content trends, and audience insights.

Pricing

from $5.99 / 1,000 results

Rating

0.0

(0)

Developer

Scrapier

Scrapier

Maintained by Community

Actor stats

0

Bookmarked

3

Total users

1

Monthly active users

a day ago

Last modified

Share

TikTok Profile Scraper — Videos, Engagement and Posting Cadence

TikTok User Profile and Video Insights Scraper pulls a creator's full profile plus recent videos from a handle, numeric ID, or profile URL — no TikTok login needed. Each run returns one profile row per creator (followers, likes, verification, bio, business flags) plus linked video rows (views, likes, comments, shares, music), with posting cadence and average engagement computed automatically. Every response is structured JSON, ready to pass to an LLM, index into a vector store, or feed a monitoring pipeline. Re-run the same list to track how the numbers move.


🧭 What is TikTok User Profile and Video Insights Scraper?

TikTok User Profile and Video Insights Scraper queries public creator identifiers — a @handle, a numeric user ID, or a profile URL — and returns two linked result types per creator: one profile row and, optionally, up to 50 recent-video rows. Output is delivered as structured JSON dataset rows, exportable as JSON, CSV, Excel, XML or RSS. No TikTok account, login, or cookies are used or required anywhere in the run — profile pages and the video list are both fetched as a logged-out visitor would see them.

What sets this scraper apart from a plain profile lookup is that it doesn't stop at the profile: it also fetches the creator's most recent videos and computes video-derived engagement analytics — average views/likes/comments per video and posting cadence in days — directly onto the profile row, in the same run, with no second tool or manual spreadsheet formula required.

  • 👤 Full public profile per creator: handle, display name, numeric ID, avatars, bio, follower/following/friend counts, total likes, video count, verification and TikTok Shop/business flags
  • 🎞️ Up to 50 of each creator's newest videos, as linked child rows — views, likes, comments, shares, cover image, music, pin status
  • 📊 Video-derived analytics computed automatically: average views/likes/comments per video, posting cadence, pinned-video detection
  • 🔀 Three ways to identify a creator in the same run — handle, numeric user ID, or profile URL — mixed freely
  • 🛡️ Optional Apify Proxy with an automatic direct → datacenter → residential fallback ladder when TikTok pushes back

📦 What data can you get with TikTok User Profile and Video Insights Scraper?

Every run extracts two linked result types — a creator profile and that creator's recent videos — with the video-derived analytics folded directly into the profile row.

Result TypeExtracted FieldsPrimary Use Case
Creator profileHandle, numeric ID, nickname, avatars, bio, follower/following/friend counts, total likes, video count, verification & business/TikTok-Shop flags, plus video-derived analytics (below)Creator vetting, lead lists, CRM enrichment
Recent videoVideo ID, caption, post date, views, likes, comments, shares, video & cover URLs, music, pin statusContent and engagement benchmarking, competitive monitoring

📊 Video-derived engagement analytics

Every profile row carries videosFetched, avgViewsPerVideo, avgLikesPerVideo, avgCommentsPerVideo, postingCadenceDays, hasPinnedVideo and pinnedVideoCount — computed from the same batch of recent videos the run just fetched for that creator, not looked up from a separate TikTok analytics endpoint. postingCadenceDays is the average number of days between consecutive posts across the fetched videos; the averages are plain means over whatever was fetched (videosFetched, capped by maxVideosPerProfile). All seven fields are null/0/false when includeRecentVideos is off or no videos could be fetched, so you can tell "not computed" apart from "zero engagement."

{
"videosFetched": 10,
"avgViewsPerVideo": 812345.6,
"avgLikesPerVideo": 45210.3,
"avgCommentsPerVideo": 612.8,
"postingCadenceDays": 2.14,
"hasPinnedVideo": true,
"pinnedVideoCount": 1
}

🎞️ Recent video rows

Each fetched video becomes its own dataset row: video_id, description (caption), createdAt/createTime (post date, as ISO string and raw Unix seconds), playCount, likeCount, commentCount, shareCount, video_url, cover_url, duration, a music object (id, title, author, is_original), and isPinned. Every video row carries parentId pointing back to its creator's uid, so you can join profile and video rows without a lookup table — useful for building a "top videos per creator" view straight out of the raw dataset.


🛠️ Why not build this yourself?

TikTok doesn't publish a general-purpose API for looking up an arbitrary public creator's profile and recent videos — its Display and Content Posting APIs operate on your own authenticated account, not third-party creators. Building this yourself means reverse-engineering the __UNIVERSAL_DATA_FOR_REHYDRATION__ script embedded in the profile page (its key names and shape shift without notice) and the item_list video endpoint's browser-shaped query parameters and cursor pagination, then keeping both working as TikTok changes them. It also means handling TikTok's anti-bot escalation yourself — this Actor retries failed requests and automatically falls back from a direct request to a datacenter proxy and then a residential proxy when TikTok blocks or challenges a request, without any extra configuration.


🔍 What is the difference between a TikTok profile scraper and a TikTok analytics scraper?

A TikTok profile scraper answers "who is this creator" — handle, follower count, bio, verification. A TikTok analytics scraper answers "how is this creator performing" — views, likes, comments and posting frequency across their recent output. The distinction matters because a follower count is a snapshot, but engagement and posting cadence only mean something measured across several videos and, ideally, several runs over time.

TikTok User Profile and Video Insights Scraper returns both in the same run instead of forcing a choice: the profile fields arrive in the top-level row (follower_count, verified, bio_url, and the rest), and the analytics fields (avgViewsPerVideo, avgLikesPerVideo, avgCommentsPerVideo, postingCadenceDays, pinnedVideoCount) are computed from the linked type: "video" rows and attached to that same profile row — no separate export or manual join needed to go from "who" to "how are they doing."


⚡ How to scrape TikTok profiles with TikTok User Profile and Video Insights Scraper?

  1. Open TikTok User Profile and Video Insights Scraper on Apify, or start it via the Apify API / apify_client.
  2. Add creators under usernames, userIds, or urls — one per line, mixed freely, or paste a whole list with Bulk edit.
  3. Set the real query controls: toggle includeRecentVideos, set maxVideosPerProfile (0–50), and adjust maxRetries / requestGapMs / proxyConfiguration if the defaults don't fit.
  4. Start the run.
  5. Read rows from the dataset live as they're written, or export the finished dataset as JSON, CSV, Excel, XML or RSS.
{
"usernames": ["nike", "nickiminaj"],
"includeRecentVideos": true,
"maxVideosPerProfile": 10
}

🧺 How to run multiple creators in one job

List every creator in usernames, userIds, and/or urls — all three arrays are read in the same run, so a mixed list of handles, IDs and links works in one job. requestGapMs (default 750 ms, plus up to 350 ms of random jitter) is the pause the Actor waits between finishing one creator and starting the next. ⚠️ Creators are fetched one at a time, in the order given — there is no parallel/concurrent fetching across creators — so total run time scales roughly with (number of creators) × (gap + fetch time), not divided across workers.


⬇️ Input

None of the fields below are required by the schema, but the run needs at least one usable entry across usernames, userIds, or urls — a run with all three empty logs an error and exits immediately.

ParameterRequiredTypeConstraintsDescription
usernamesNoarray of stringseditor: stringListOne TikTok handle per line, with or without @ (e.g. nike, @nike). Leave blank if using IDs or URLs instead.
userIdsNoarray of stringseditor: stringListDigits-as-text numeric TikTok user IDs only, one per row. Skip if using handles or URLs.
urlsNoarray of stringseditor: stringListFull TikTok profile page URLs. https:// is optional — a bare domain is auto-prefixed.
includeRecentVideosNobooleandefault trueWhen on, fetches each creator's newest videos as linked child rows and computes video-derived analytics onto the profile row. Turn off to collect only the profile row.
maxVideosPerProfileNointegerdefault 10, min 0, max 50Cap on newest videos fetched per creator. Does not reduce how many profiles are collected — profiles and videos are counted separately.
maxRetriesNointegerdefault 3, min 0, max 10Per-request retries on network errors, applied to both the profile fetch and the video fetch.
requestGapMsNointegerdefault 750, min 0Pause between each creator's fetch, in milliseconds.
proxyConfigurationNoobjecteditor: proxy, prefill {"useApifyProxy": true}Standard Apify Proxy picker — choose groups or turn Apify Proxy off.
{
"usernames": ["nike"],
"userIds": ["208464585232822272"],
"urls": ["https://www.tiktok.com/@nickiminaj"],
"includeRecentVideos": true,
"maxVideosPerProfile": 10,
"maxRetries": 3,
"requestGapMs": 750,
"proxyConfiguration": { "useApifyProxy": true }
}

Common pitfall: maxVideosPerProfile only limits videos, not creators — setting it to 0 (or turning includeRecentVideos off) still collects every profile you listed, just without any video rows or analytics on them. And if the same creator is reachable two different ways (say, listed once by handle and once by URL), it's saved once — the second match is logged and skipped, not duplicated.


⬆️ Output

Every run pushes typed, normalized JSON rows to the Apify dataset — one schema for profile rows, another for video rows, distinguished by type and isChild. Export the dataset as JSON, CSV, Excel, XML or RSS from the Apify Console or API once the run finishes, or read rows live while the run is still going.

🗂️ Scraped results

Profile row (type: "profile", isChild: false, parentId: null) — every key the row-building code writes, grouped by theme:

GroupFields
Identityunique_id, uid, nickname, profile_url, sec_uid, short_id
Verification & account flagsverified, is_private, tt_seller, account_type, verification_type, custom_verify, enterprise_verify_reason, is_star, is_effect_artist, secret, watch_status, ad_virtual
Statsfollower_count, following_count, friend_count, total_favorited, aweme_count, visible_videos_count, favoriting_count, forward_count, mplatform_followers_count, follow_status, follower_status
Bio & linkssignature, signature_language, bio_url, bio_secure_url, category, twitter_id, twitter_name, youtube_channel_id, youtube_channel_title, ins_id
Avatars (each {uri, url_list, url_prefix})avatar_thumb, avatar_medium, avatar_larger, avatar_168x168, avatar_300x300
Business / commercebiz_account_info (added_contact_and_link_list, android_download_app_link, coupon_list, ios_download_app_link, leads_gen{action_name, business_data, has_leads_gen, page_id, schema_url}, permission_list, rba_user_info{company_name}), commerce_user_info{ad_revenue_rits}, commerce_user_level, with_commerce_entry, with_commerce_enterprise_tab_entry, with_new_goods, live_commerce, original_musician{digg_count, music_count, music_used_count, new_release_clip_ids}, music_tab_info{show_artist_pick_videos}
Privacy, notifications & tabsprivacy_setting{following_visibility}, tab_settings{private_tab{private_tab_style, show_private_tab}, repost_tab{repost_tab_all_visible, show_repost_tab_other}}, live_push_notification_status, post_push_notification_status, message_chat_entry, show_messaging_entrance_on_profile, show_effect_list, show_favorite_list, has_open_favorite, is_acquaintance, is_block, is_blocked, profile_tab_type, story_status, room_id, recommend_reason_relation, supporting_ngo, can_message_follow_status_list (fixed [0, 1, 2, 4]), share_info{now_invitation_card_image_urls, share_desc, share_title, share_url}
Video-derived analytics (this Actor's own, computed from the fetched videos)videosFetched, avgViewsPerVideo, avgLikesPerVideo, avgCommentsPerVideo, postingCadenceDays, hasPinnedVideo, pinnedVideoCount
Row metadatatype, isChild, parentId, scrapedAt

Video row (type: "video", isChild: true): type, isChild, parentId (the creator's uid), video_id, description, createTime (Unix epoch seconds or null), createdAt (ISO 8601 UTC or null), playCount, likeCount, commentCount, shareCount, video_url, cover_url, duration (raw value from TikTok's video object, passed through unmodified), music ({id, title, author, is_original} or null), isPinned, scrapedAt.

[
{
"type": "profile",
"isChild": false,
"parentId": null,
"unique_id": "nike",
"uid": "208464585232822272",
"nickname": "Nike",
"profile_url": "https://www.tiktok.com/@nike",
"sec_uid": "MS4wLjABAAAA...",
"verified": true,
"is_private": false,
"tt_seller": false,
"follower_count": 10800000,
"following_count": 120,
"friend_count": 15,
"total_favorited": 89500000,
"aweme_count": 412,
"signature": "Just Do It.",
"bio_url": "",
"avatar_larger": { "uri": "tos-maliva-avt-0068/abc123", "url_list": ["https://..."], "url_prefix": "https://p16-sign-va.tiktokcdn.com/" },
"videosFetched": 10,
"avgViewsPerVideo": 812345.6,
"avgLikesPerVideo": 45210.3,
"avgCommentsPerVideo": 612.8,
"postingCadenceDays": 2.14,
"hasPinnedVideo": true,
"pinnedVideoCount": 1,
"scrapedAt": "2026-07-30T09:12:41Z"
},
{
"type": "video",
"isChild": true,
"parentId": "208464585232822272",
"video_id": "7391234567890123456",
"description": "New drop, out now.",
"createTime": 1753776000,
"createdAt": "2025-07-29T08:00:00Z",
"playCount": 950230,
"likeCount": 51230,
"commentCount": 890,
"shareCount": 1230,
"video_url": "https://www.tiktok.com/@nike/video/7391234567890123456",
"cover_url": "https://p16-sign-va.tiktokcdn.com/cover1.jpeg",
"duration": 18,
"music": { "id": "7391234500000000000", "title": "original sound", "author": "nike", "is_original": true },
"isPinned": true,
"scrapedAt": "2026-07-30T09:12:41Z"
},
{
"type": "video",
"isChild": true,
"parentId": "208464585232822272",
"video_id": "7391234567890123457",
"description": "Training day.",
"createTime": 1753603200,
"createdAt": "2025-07-27T08:00:00Z",
"playCount": 674120,
"likeCount": 39012,
"commentCount": 540,
"shareCount": 980,
"video_url": "https://www.tiktok.com/@nike/video/7391234567890123457",
"cover_url": "https://p16-sign-va.tiktokcdn.com/cover2.jpeg",
"duration": 22,
"music": { "id": "7391234500000000001", "title": "gym mix", "author": "unknown", "is_original": false },
"isPinned": false,
"scrapedAt": "2026-07-30T09:12:41Z"
}
]

(Profile row trimmed for length — every field is listed in the table above.)

You are charged one row_result event per row actually written to the dataset — one per profile row and one per video row. Profiles that fail to load (blocked, not found, or unparsable) are logged and skipped, never pushed to the dataset, so they are never charged.


💡 How can I use the data extracted with TikTok User Profile and Video Insights Scraper?

  • 🎯 Creator research and influencer vetting: check follower_count, verified, tt_seller, and recent posting activity (postingCadenceDays) before a partnership decision.
  • 🤖 AI engineers and LLM developers: have an agent request a creator list, receive structured JSON with profile and video fields, and pass it straight to the model as grounded context for a brief or report.
  • 📊 Market researchers and competitive analysts: track avgViewsPerVideo, avgLikesPerVideo, and postingCadenceDays across a set of competitor accounts to compare content velocity and reach.
  • 💼 Sales and lead-gen teams: filter on tt_seller and biz_account_info fields plus bio_url to build outreach lists from a batch of handles.

📈 How do you monitor engagement and posting cadence over time?

Monitoring here means re-running the same creator list on a schedule and comparing the video-derived fields between runs, since a single run only shows a snapshot of the most recent videos. Because avgViewsPerVideo, avgLikesPerVideo, avgCommentsPerVideo and postingCadenceDays are recomputed fresh from whatever is currently the creator's most recent maxVideosPerProfile videos, a change between two runs reflects real movement — a viral video pulling the averages up, or a slower cadence stretching postingCadenceDays out.

The fields worth diffing run-to-run are follower_count, avgViewsPerVideo, avgLikesPerVideo, avgCommentsPerVideo, postingCadenceDays, and pinnedVideoCount (a change signals the creator swapped their pinned video). A practical workflow: schedule a run across your creator list, keep the previous run's dataset, join on unique_id or uid, and alert when avgViewsPerVideo or postingCadenceDays moves past whatever threshold matters for your use case.

Set this up with an Apify schedule against this Actor's saved input, and use a webhook on run completion to push the new dataset to wherever you compare it.


🔌 Integrate TikTok User Profile and Video Insights Scraper and automate your workflow

TikTok User Profile and Video Insights Scraper works with any language or tool that can send an HTTP request through the Apify API.

🐍 REST API with Python

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("your-username/tiktok-user-profile-and-video-insights-scraper").call(
run_input={
"usernames": ["nike", "nickiminaj"],
"includeRecentVideos": True,
"maxVideosPerProfile": 10,
}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
if item.get("type") == "profile":
print(item["unique_id"], item["follower_count"], item.get("avgViewsPerVideo"))

🗓️ Scheduled monitoring and delivery

Save your input once, then attach an Apify schedule to run it on a recurring interval. Add a webhook on the ACTOR.RUN.SUCCEEDED event to push the resulting dataset URL to your own pipeline as soon as each run finishes, instead of polling for new results.


Yes — scraping publicly accessible TikTok profile and video pages is generally legal; TikTok User Profile and Video Insights Scraper returns only what any logged-out visitor can already see on those pages. Because the output includes personal data (handles, display names, follower counts, bios tied to identifiable people), GDPR and CCPA can apply depending on who you are and how you use the data — particularly around storage, retention, and any onward use that identifies a person. Scraping for one-off research or monitoring carries a different risk profile than scraping for bulk storage or AI training on personal data. Consult your legal team for commercial use cases involving bulk data storage.


❓ Frequently asked questions

Can I mix handles, numeric IDs, and profile URLs in the same run?

Yes. usernames, userIds, and urls are all read together in one run — add creators to whichever field is convenient and mix freely. If the same creator ends up reachable two different ways, it's only saved once.

How many recent videos does it fetch per creator, and can I turn that off?

Up to maxVideosPerProfile (default 10, max 50) newest videos per creator. Set it to 0, or turn includeRecentVideos off, to collect only the profile row — the fastest option, with the analytics fields returned as null/0/false.

How does TikTok User Profile and Video Insights Scraper handle TikTok's anti-bot measures?

It retries failed requests up to maxRetries times, then falls back from a direct request to an Apify datacenter proxy, then to a residential proxy, if TikTok returns an error or a verification/challenge page. Once a residential proxy successfully loads a profile, the run switches to residential proxies for all remaining creators for the rest of that run (this only happens if Apify Proxy is enabled in proxyConfiguration; with it off, every request goes out direct with no fallback).

Does TikTok User Profile and Video Insights Scraper compute engagement analytics itself?

Yes — avgViewsPerVideo, avgLikesPerVideo, avgCommentsPerVideo, postingCadenceDays, hasPinnedVideo and pinnedVideoCount are computed on the fetched video batch and attached to the profile row in the same run. They are null/0/false when no videos were fetched (either includeRecentVideos is off, maxVideosPerProfile is 0, or the creator's sec_uid couldn't be resolved).

How many results does it return per query?

There's no schema limit on how many creators you can list across usernames, userIds, and urls — add as many as you need. Per creator, video rows are capped at maxVideosPerProfile (0–50); the fetch also stops after 12 internal pagination pages if it reaches that limit first, though at 15 videos per page that ceiling is well above the 50-video maximum.

How do I use this to monitor a creator's growth and posting activity over time?

Schedule a recurring run across the same creator list, keep each run's dataset, and diff follower_count, avgViewsPerVideo, avgLikesPerVideo, and postingCadenceDays against the previous run using an Apify schedule and a completion webhook.

Does TikTok User Profile and Video Insights Scraper work with Claude, ChatGPT, and AI agent frameworks?

It's callable as an HTTP endpoint through the Apify API from any agent framework that can make a request — an agent submits a creator list, receives structured JSON back, and grounds its answer in real profile and video fields instead of guessing.

Can I use it without managing proxies or a TikTok account?

Yes. No TikTok login or account is used anywhere in the run. Apify Proxy (datacenter and residential) is handled automatically when proxyConfiguration.useApifyProxy is on — you only need to supply the creators you want to look up.

What happens if a profile can't be loaded?

The run logs the reason (not found, blocked, a verification page, or unparsable data) and moves on to the next creator without pushing a row for it — so failed lookups are never charged and never appear as blank rows in your dataset.


💬 Your feedback

Found a bug, or need a field this scraper doesn't return yet? Let us know through the Issues tab on this Actor's Apify Store page, or via Scrapier's support contact on the listing — reports like this go straight into what gets fixed or added next.