Tutorial

How to Build TikTok Audience Quality Scorer

Score TikTok influencer audience quality before partnerships. Detect fake engagement, measure real reach, and rank creators.

Fake followers and inflated engagement cost brands millions in wasted influencer spend. This scorer analyzes a TikTok creator's video performance patterns to estimate audience quality. It checks engagement consistency, view-to-like ratios, and comment quality. Each creator analysis costs $0.005.

Prerequisites

  • Python 3.8+
  • requests library
  • A Scavio API key from scavio.dev
  • TikTok creator usernames to evaluate

Walkthrough

Step 1: Collect creator performance data

Pull multiple videos to analyze engagement patterns over time.

Python
import os, requests, json, statistics
from datetime import datetime

API_KEY = os.environ['SCAVIO_API_KEY']
TH = {'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}

def get_creator_stats(username):
    data = requests.post('https://api.scavio.dev/api/v1/tiktok/user/videos',
        headers=TH, json={'username': username}).json()
    videos = data.get('videos', data.get('data', {}).get('videos', []))
    stats = []
    for v in videos:
        s = v.get('stats', {})
        plays = s.get('playCount', 0)
        likes = s.get('diggCount', 0)
        comments = s.get('commentCount', 0)
        shares = s.get('shareCount', 0)
        if plays > 0:
            stats.append({
                'plays': plays,
                'likes': likes,
                'comments': comments,
                'shares': shares,
                'like_rate': likes / plays,
                'comment_rate': comments / plays,
                'share_rate': shares / plays,
                'engagement_rate': (likes + comments + shares) / plays,
            })
    return stats

CREATORS = ['charlidamelio', 'khaby.lame', 'addisonre']

creator_data = {}
for username in CREATORS:
    stats = get_creator_stats(username)
    creator_data[username] = stats
    if stats:
        avg_plays = statistics.mean(s['plays'] for s in stats)
        avg_er = statistics.mean(s['engagement_rate'] for s in stats)
        print(f'  @{username:20} | {len(stats)} videos | Avg plays: {avg_plays:,.0f} | Avg ER: {avg_er*100:.1f}%')
print(f'\nCost: ${len(CREATORS) * 0.005:.3f}')

Step 2: Calculate audience quality signals

Analyze engagement patterns to detect quality issues like fake followers.

Python
def score_audience_quality(username, stats):
    if not stats or len(stats) < 3:
        return {'username': username, 'score': 0, 'reason': 'Insufficient data'}
    signals = {}
    # 1. Engagement consistency (real audiences have some variance, bots are too consistent)
    er_values = [s['engagement_rate'] for s in stats]
    er_cv = statistics.stdev(er_values) / statistics.mean(er_values) if statistics.mean(er_values) > 0 else 0
    # Healthy CV is 0.3-0.8. Too low = bot-like, too high = bought views
    if 0.2 <= er_cv <= 1.0:
        signals['consistency'] = 25
    elif er_cv < 0.2:
        signals['consistency'] = 5  # Suspiciously consistent
    else:
        signals['consistency'] = 10  # Too erratic
    # 2. Like-to-view ratio (healthy: 3-15%)
    avg_like_rate = statistics.mean(s['like_rate'] for s in stats)
    if 0.03 <= avg_like_rate <= 0.15:
        signals['like_ratio'] = 25
    elif avg_like_rate < 0.01:
        signals['like_ratio'] = 5  # Views but no likes = bought views
    else:
        signals['like_ratio'] = 15
    # 3. Comment-to-like ratio (healthy: 1-5%)
    avg_comment_to_like = statistics.mean(s['comments'] / s['likes'] if s['likes'] > 0 else 0 for s in stats)
    if 0.01 <= avg_comment_to_like <= 0.05:
        signals['comment_quality'] = 25
    elif avg_comment_to_like < 0.005:
        signals['comment_quality'] = 5  # Likes but no comments = suspicious
    else:
        signals['comment_quality'] = 15
    # 4. Share rate (real engagement drives shares)
    avg_share_rate = statistics.mean(s['share_rate'] for s in stats)
    signals['share_quality'] = min(25, int(avg_share_rate * 2500))
    total = sum(signals.values())
    return {
        'username': username,
        'score': total,
        'signals': signals,
        'avg_er': statistics.mean(er_values),
        'er_cv': er_cv,
        'avg_like_rate': avg_like_rate,
    }

print(f'\n=== Audience Quality Scores ===')
scores = []
for username, stats in creator_data.items():
    result = score_audience_quality(username, stats)
    scores.append(result)
    grade = 'A' if result['score'] >= 80 else 'B' if result['score'] >= 60 else 'C' if result['score'] >= 40 else 'F'
    print(f'  @{username:20} | Score: {result["score"]:3}/100 | Grade: {grade}')
    if result.get('signals'):
        for signal, value in result['signals'].items():
            print(f'    {signal:20} {value:3}/25')

Step 3: Generate audience quality report

Compile scores into a comparison report for influencer selection.

Python
def audience_quality_report(scores):
    print(f'\n{"=" * 60}')
    print(f'  TIKTOK AUDIENCE QUALITY REPORT')
    print(f'  Date: {datetime.now().strftime("%Y-%m-%d")}')
    print(f'{"=" * 60}')
    scores.sort(key=lambda x: x['score'], reverse=True)
    for i, s in enumerate(scores, 1):
        grade = 'A' if s['score'] >= 80 else 'B' if s['score'] >= 60 else 'C' if s['score'] >= 40 else 'F'
        status = 'RECOMMENDED' if grade in ['A', 'B'] else 'CAUTION' if grade == 'C' else 'AVOID'
        print(f'\n  {i}. @{s["username"]} - Grade {grade} ({s["score"]}/100) - {status}')
        if s.get('avg_er'):
            print(f'     Engagement Rate: {s["avg_er"]*100:.1f}%')
            print(f'     Engagement Variance: {s.get("er_cv", 0):.2f} (0.3-0.8 is healthy)')
            print(f'     Like Rate: {s.get("avg_like_rate", 0)*100:.1f}% (3-15% is healthy)')
    # Summary
    recommended = sum(1 for s in scores if s['score'] >= 60)
    caution = sum(1 for s in scores if 40 <= s['score'] < 60)
    avoid = sum(1 for s in scores if s['score'] < 40)
    print(f'\n  Summary:')
    print(f'    Recommended: {recommended}')
    print(f'    Caution: {caution}')
    print(f'    Avoid: {avoid}')
    print(f'\n  Cost: ${len(scores) * 0.005:.3f}')
    print(f'  vs. HypeAuditor: $299/mo for audience quality reports')

audience_quality_report(scores)

Python Example

Python
import os, requests, statistics
TH = {'Authorization': f'Bearer {os.environ["SCAVIO_API_KEY"]}', 'Content-Type': 'application/json'}

def quality_score(username):
    data = requests.post('https://api.scavio.dev/api/v1/tiktok/user/videos',
        headers=TH, json={'username': username}).json()
    videos = data.get('videos', data.get('data', {}).get('videos', []))
    ers = [(v.get('stats', {}).get('diggCount', 0) / max(v.get('stats', {}).get('playCount', 1), 1)) for v in videos]
    avg = statistics.mean(ers) if ers else 0
    print(f'@{username}: Avg like rate {avg*100:.1f}%')

quality_score('charlidamelio')
print('Cost: $0.005')

JavaScript Example

JavaScript
const TH = { 'Authorization': `Bearer ${process.env.SCAVIO_API_KEY}`, 'Content-Type': 'application/json' };
const data = await fetch('https://api.scavio.dev/api/v1/tiktok/user/videos', {
  method: 'POST', headers: TH, body: JSON.stringify({ username: 'charlidamelio' })
}).then(r => r.json());
const videos = data.videos || data.data?.videos || [];
const avgER = videos.reduce((s, v) => s + (v.stats?.diggCount || 0) / Math.max(v.stats?.playCount || 1, 1), 0) / Math.max(videos.length, 1);
console.log(`Avg like rate: ${(avgER * 100).toFixed(1)}%`);

Expected Output

JSON
  @charlidamelio         | 15 videos | Avg plays: 3,000,000 | Avg ER: 8.5%
  @khaby.lame            | 12 videos | Avg plays: 10,000,000 | Avg ER: 6.2%
  @addisonre             | 10 videos | Avg plays: 2,500,000 | Avg ER: 7.8%

=== Audience Quality Scores ===
  @charlidamelio         | Score:  82/100 | Grade: A
    consistency           22/25
    like_ratio            25/25
    comment_quality       20/25
    share_quality         15/25

============================================================
  TIKTOK AUDIENCE QUALITY REPORT
  Date: 2026-05-21
============================================================

  1. @charlidamelio - Grade A (82/100) - RECOMMENDED
     Engagement Rate: 8.5%

  Cost: $0.015
  vs. HypeAuditor: $299/mo for audience quality reports

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8+. requests library. A Scavio API key from scavio.dev. TikTok creator usernames to evaluate. A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Score TikTok influencer audience quality before partnerships. Detect fake engagement, measure real reach, and rank creators.