tiktokbrand-safetyvetting

TikTok Brand Safety: Creator Vetting API

Vet TikTok creators before paying them. API checks: follower authenticity, content history, engagement patterns, audience demographics. Automated pipeline.

8 min

Before spending $5K or more on a TikTok creator partnership, vet their content and audience programmatically. A creator vetting pipeline checks comment sentiment, follower authenticity via follower-to-following ratio, content history for brand safety red flags, and existing brand mention context. Total API cost per creator: roughly $0.04.

What the Vetting Pipeline Checks

  • Profile metrics: follower count, video count, total likes, engagement rate
  • Follower authenticity: follower/following ratio. Ratios below 2:1 for accounts with 100K+ followers are suspect.
  • Content history: scan recent posts for controversial topics, competitor mentions, brand safety issues
  • Comment sentiment: are real people engaging, or is it bot comments and spam?
  • Brand mention context: if they have mentioned your brand or competitors, what was the tone?

Step 1: Profile Analysis

Python
import requests, os

API_KEY = os.environ["SCAVIO_API_KEY"]
BASE = "https://api.scavio.dev/api/v1/tiktok"
HEADERS = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}

def get_creator_profile(username: str) -> dict:
    resp = requests.post(f"{BASE}/profile",
        headers=HEADERS,
        json={"username": username}, timeout=15)
    user = resp.json()["data"]["user"]
    stats = resp.json()["data"]["stats"]
    follower_ratio = round(stats["followerCount"] / max(stats["followingCount"], 1), 1)
    engagement_rate = round(stats["heartCount"] / max(stats["followerCount"], 1) * 100 / max(stats["videoCount"], 1), 2)
    return {
        "username": user["uniqueId"],
        "followers": stats["followerCount"],
        "following": stats["followingCount"],
        "videos": stats["videoCount"],
        "total_likes": stats["heartCount"],
        "follower_ratio": follower_ratio,
        "engagement_rate": engagement_rate,
        "verified": user.get("verified", False),
        "flags": get_profile_flags(stats, follower_ratio),
    }

def get_profile_flags(stats: dict, ratio: float) -> list:
    flags = []
    if stats["followerCount"] > 100000 and ratio < 2:
        flags.append("Low follower/following ratio - possible purchased followers")
    if stats["videoCount"] < 10:
        flags.append("Very few videos for claimed audience size")
    if stats["heartCount"] / max(stats["videoCount"], 1) < 100:
        flags.append("Low average likes per video")
    return flags

Step 2: Content History Scan

Python
BRAND_SAFETY_KEYWORDS = {
    "politics", "conspiracy", "scam", "fake", "lawsuit",
    "controversy", "arrested", "banned", "exposed",
}

def scan_content_history(username: str, count: int = 20) -> dict:
    resp = requests.post(f"{BASE}/user/posts",
        headers=HEADERS,
        json={"username": username, "count": count}, timeout=15)
    videos = resp.json().get("data", {}).get("aweme_list", [])
    flagged = []
    topics = []
    for v in videos:
        desc = v.get("desc", "").lower()
        words = set(desc.split())
        matches = words & BRAND_SAFETY_KEYWORDS
        if matches:
            flagged.append({"desc": v["desc"][:100], "flags": list(matches),
                            "views": v["statistics"]["play_count"]})
        topics.append(desc[:80])
    return {
        "total_scanned": len(videos),
        "flagged_count": len(flagged),
        "flagged_posts": flagged,
        "recent_topics": topics[:10],
    }

Step 3: Comment Sentiment Analysis

Python
def analyze_comments(username: str, video_count: int = 5) -> dict:
    resp = requests.post(f"{BASE}/user/posts",
        headers=HEADERS,
        json={"username": username, "count": video_count}, timeout=15)
    videos = resp.json().get("data", {}).get("aweme_list", [])
    all_comments = []
    bot_signals = 0
    for v in videos[:video_count]:
        video_id = v["aweme_id"]
        c_resp = requests.post(f"{BASE}/video/comments",
            headers=HEADERS,
            json={"video_id": video_id, "count": 20}, timeout=15)
        comments = c_resp.json().get("data", {}).get("comments", [])
        for c in comments:
            text = c.get("text", "")
            all_comments.append(text)
            # Bot signals: very short, generic praise, emoji-only
            if len(text) < 5 or text in ("nice", "wow", "amazing", "love it"):
                bot_signals += 1
    total = max(len(all_comments), 1)
    return {
        "total_comments_analyzed": len(all_comments),
        "bot_signal_pct": round(bot_signals / total * 100, 1),
        "sample_comments": all_comments[:10],
        "flags": ["High bot comment percentage"] if bot_signals / total > 0.4 else [],
    }

Step 4: Full Vetting Report

Python
def vet_creator(username: str) -> dict:
    profile = get_creator_profile(username)  # 1 credit
    content = scan_content_history(username, count=20)  # 1 credit
    comments = analyze_comments(username, video_count=5)  # 6 credits (1 posts + 5 comments)
    all_flags = profile["flags"] + content.get("flagged_posts", []) + comments["flags"]
    risk_score = min(len(all_flags) * 20, 100)
    report = {
        "username": username,
        "profile": profile,
        "content_scan": content,
        "comment_analysis": comments,
        "risk_score": risk_score,
        "risk_level": "low" if risk_score < 30 else "medium" if risk_score < 60 else "high",
        "total_flags": len(all_flags),
        "recommendation": "proceed" if risk_score < 30 else "review flags" if risk_score < 60 else "do not proceed",
        "api_credits_used": 8,
        "api_cost": "$0.04",
    }
    return report

report = vet_creator("example_creator")
print(f"Risk: {report['risk_level']} (score: {report['risk_score']})")
for f in report["profile"]["flags"]:
    print(f"  Profile: {f}")
if report["content_scan"]["flagged_count"] > 0:
    print(f"  Content: {report['content_scan']['flagged_count']} flagged posts")

Cost Breakdown

  • Profile lookup: 1 credit
  • Post history (20 posts): 1 credit
  • Comments on 5 videos: 5 credits
  • Brand mention search (optional): 1 credit
  • Total per creator: ~8 credits = $0.04
  • Vetting 50 creators for a campaign: 400 credits = $2.00
  • Compare: manual vetting takes 15-30 min per creator. At $50/hr, 50 creators = $625-$1,250 in labor.

Limitations

Keyword-based brand safety scanning catches obvious issues but misses context. A creator discussing a brand "controversy" might be defending the brand. Bot detection via short comments is a rough heuristic -- real humans also write "nice" and "wow." Follower/following ratio is a signal, not proof. Use the automated pipeline as a first pass to filter out obvious risks, then have a human review the shortlisted creators before signing contracts.