A 60,000-view video with a flat comment section is a reach win and an intent miss, and you can quantify that gap with the Scavio TikTok API instead of guessing. Views measure how many phones the algorithm pushed your clip to. They say nothing about whether anyone wanted what you sell. Intent lives in the comments: how many people bothered to type, how many asked where to buy or how it works, how many shared it. Those signals are in the API. This walkthrough pulls your video stats, downloads the comments, and computes three numbers that tell you whether your content created demand or just scrolled past. Each Scavio call costs 1 credit ($0.005). The honest part comes at the end: the API measures whether intent existed; it cannot tell you who signed up, and it cannot fix a broken conversion path.
Prerequisites
- A Scavio API key (sk_live_...). 50 free credits on signup, no card.
- The video_id of the post that went viral.
- Python 3 or Node installed.
Walkthrough
Step 1: Step 1: Get your profile and post stats
TikTok endpoints work in two hops. First call profile with your username to get a sec_user_id, then pass that to user/posts to list recent posts with statistics: play_count, digg_count (likes), comment_count, share_count. Find your viral video in the list and note its raw numbers. This is the denominator for every ratio below. Two calls, 2 credits.
import requests
KEY = "sk_live_..."
H = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
BASE = "https://api.scavio.dev/api/v1/tiktok"
prof = requests.post(f"{BASE}/profile", headers=H, json={"username": "yourhandle"}).json()
sec_user_id = prof["sec_user_id"]
posts = requests.post(f"{BASE}/user/posts", headers=H,
json={"sec_user_id": sec_user_id, "count": 20}).json()
for p in posts["posts"]:
s = p["statistics"]
print(p["video_id"], s["play_count"], s["comment_count"], s["share_count"])Step 2: Step 2: Pull the comments on the viral video
Now grab the actual comments. Pass the video_id and a count (100 is enough to read the room). Each comment carries text, digg_count (how many liked the comment), and reply_comment_total (how many replies it triggered). Comments that attract likes and replies are the conversations worth reading. 1 credit.
video_id = "7300000000000000000"
cm = requests.post(f"{BASE}/video/comments", headers=H,
json={"video_id": video_id, "count": 100}).json()
comments = cm["comments"]
print(len(comments), "comments pulled")
for c in comments[:5]:
print(c["digg_count"], c["reply_comment_total"], c["text"])Step 3: Step 3: Compute the three intent signals
Reach is plays. Intent is what people did beyond watching. Compute comment-to-view ratio (comments / plays) and share-to-view ratio (shares / plays), then question/intent density: the share of comments that contain a question mark or a buying word like how, where, link, price, or sign up. Use the comments themselves as a save/share proxy too: a clip people send to a friend earns replies tagging someone, and those show up as text. A strong reach-but-no-intent pattern looks like high views, a comment-to-view ratio well under 0.3%, and almost no comments asking about your product. That means the algorithm liked your hook but nobody wanted the thing. If the ratio is healthy but density is near zero, people engaged with the entertainment and ignored the offer. Here is the honest tradeoff. The API hands you comments, counts, and these proxies; it does not attribute signups, because there is no funnel tracking in it, and it cannot fix TikTok's rule that accounts under 1,000 followers get no clickable bio link, which is a conversion-path problem no data call can solve. So the API answers one question only: did your content create intent? Your bio and landing page are a separate fix. The decision rule: if intent density is high but signups are flat, your content works and your conversion path is broken, so fix the link and landing page first. If intent density is near zero, more reach will not save you, so change the content and the offer before you chase another viral hit.
INTENT_WORDS = ["how", "where", "link", "price", "cost", "buy", "sign up", "sign-up"]
def has_intent(text):
t = text.lower()
if "?" in t:
return True
return any(w in t for w in INTENT_WORDS)
plays = posts["posts"][0]["statistics"]["play_count"]
shares = posts["posts"][0]["statistics"]["share_count"]
n = len(comments)
intent_n = sum(1 for c in comments if has_intent(c["text"]))
print("comment-to-view: %.3f%%" % (100 * n / plays))
print("share-to-view: %.3f%%" % (100 * shares / plays))
print("intent density: %.1f%%" % (100 * intent_n / n))Python Example
import requests
KEY = "sk_live_..."
H = {"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"}
BASE = "https://api.scavio.dev/api/v1/tiktok"
VIDEO_ID = "7300000000000000000"
INTENT_WORDS = ["how", "where", "link", "price", "cost", "buy", "sign up", "sign-up"]
def has_intent(text):
t = text.lower()
return "?" in t or any(w in t for w in INTENT_WORDS)
prof = requests.post(f"{BASE}/profile", headers=H, json={"username": "yourhandle"}).json()
sec_user_id = prof["sec_user_id"]
posts = requests.post(f"{BASE}/user/posts", headers=H,
json={"sec_user_id": sec_user_id, "count": 20}).json()
vid = next(p for p in posts["posts"] if p["video_id"] == VIDEO_ID)
plays = vid["statistics"]["play_count"]
shares = vid["statistics"]["share_count"]
cm = requests.post(f"{BASE}/video/comments", headers=H,
json={"video_id": VIDEO_ID, "count": 100}).json()
comments = cm["comments"]
n = len(comments)
intent_n = sum(1 for c in comments if has_intent(c["text"]))
print("plays: %d" % plays)
print("comment-to-view: %.3f%%" % (100 * n / plays))
print("share-to-view: %.3f%%" % (100 * shares / plays))
print("intent density: %.1f%% (%d of %d)" % (100 * intent_n / n, intent_n, n))JavaScript Example
const KEY = "sk_live_...";
const H = { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json" };
const BASE = "https://api.scavio.dev/api/v1/tiktok";
const VIDEO_ID = "7300000000000000000";
const INTENT_WORDS = ["how", "where", "link", "price", "cost", "buy", "sign up", "sign-up"];
const hasIntent = (t) => {
const s = t.toLowerCase();
return s.includes("?") || INTENT_WORDS.some((w) => s.includes(w));
};
const post = (path, body) =>
fetch(`${BASE}/${path}`, { method: "POST", headers: H, body: JSON.stringify(body) }).then((r) => r.json());
const prof = await post("profile", { username: "yourhandle" });
const posts = await post("user/posts", { sec_user_id: prof.sec_user_id, count: 20 });
const vid = posts.posts.find((p) => p.video_id === VIDEO_ID);
const plays = vid.statistics.play_count;
const shares = vid.statistics.share_count;
const cm = await post("video/comments", { video_id: VIDEO_ID, count: 100 });
const comments = cm.comments;
const n = comments.length;
const intentN = comments.filter((c) => hasIntent(c.text)).length;
console.log(`plays: ${plays}`);
console.log(`comment-to-view: ${(100 * n / plays).toFixed(3)}%`);
console.log(`share-to-view: ${(100 * shares / plays).toFixed(3)}%`);
console.log(`intent density: ${(100 * intentN / n).toFixed(1)}% (${intentN} of ${n})`);Expected Output
plays: 60214
comment-to-view: 0.142%
share-to-view: 0.061%
intent density: 3.5% (3 of 86)