Tutorial

How to Detect TikTok Fake Followers via API

Build a fake follower detection system for TikTok using API data. Analyze engagement ratios, follower patterns, and content signals to spot fraud.

Fake followers and engagement fraud waste influencer marketing budgets. Detecting fakes on TikTok requires analyzing multiple signals: engagement-to-follower ratios, comment quality patterns, follower growth spikes, and content consistency. This tutorial builds an automated fraud detection pipeline using the Scavio TikTok API. It fetches profile data and recent videos, runs statistical tests for anomalies, and outputs a fraud risk score. Total cost is 2-3 credits ($0.01-0.015) per creator analyzed.

Prerequisites

  • Python 3.9+ installed
  • requests library installed
  • A Scavio API key from scavio.dev
  • TikTok usernames to analyze

Walkthrough

Step 1: Fetch profile and engagement data

Get the creator profile stats and recent video performance data. Both are needed to detect inconsistencies that signal fake engagement.

Python
import requests, os

API_KEY = os.environ['SCAVIO_API_KEY']
TIKTOK_URL = 'https://api.scavio.dev/api/v1/tiktok'

def fetch_creator_data(username: str) -> dict:
    # Profile
    profile_resp = requests.post(f'{TIKTOK_URL}/user/info',
        headers={'Authorization': f'Bearer {API_KEY}',
                 'Content-Type': 'application/json'},
        json={'username': username})
    profile_data = profile_resp.json().get('data', {})
    # Recent videos
    videos_resp = requests.post(f'{TIKTOK_URL}/user/posts',
        headers={'Authorization': f'Bearer {API_KEY}',
                 'Content-Type': 'application/json'},
        json={'username': username, 'count': 30, 'cursor': 0})
    videos = videos_resp.json().get('data', {}).get('videos', [])
    stats = profile_data.get('stats', {})
    return {
        'username': username,
        'followers': stats.get('followerCount', 0),
        'following': stats.get('followingCount', 0),
        'total_likes': stats.get('heartCount', 0),
        'video_count': stats.get('videoCount', 0),
        'videos': videos
    }

Step 2: Check engagement ratio anomalies

Legitimate accounts have predictable engagement-to-follower ratios. Accounts with fake followers show abnormally low engagement relative to follower count.

Python
def check_engagement_ratio(data: dict) -> dict:
    followers = max(data['followers'], 1)
    videos = data['videos']
    if not videos:
        return {'flag': 'NO_VIDEOS', 'risk': 50}
    avg_likes = sum(v.get('stats', {}).get('diggCount', 0) for v in videos) / len(videos)
    avg_plays = sum(v.get('stats', {}).get('playCount', 0) for v in videos) / len(videos)
    likes_to_followers = (avg_likes / followers) * 100
    plays_to_followers = (avg_plays / followers) * 100
    # Normal ranges for TikTok:
    # Likes/followers: 1-15% is typical, <0.5% suspicious, >20% suspicious (bought likes)
    # Plays/followers: 10-200% is typical, <5% suspicious
    engagement_risk = 0
    flags = []
    if likes_to_followers < 0.5:
        engagement_risk += 30
        flags.append(f'Very low like ratio: {likes_to_followers:.2f}%')
    elif likes_to_followers > 25:
        engagement_risk += 20
        flags.append(f'Abnormally high like ratio: {likes_to_followers:.2f}%')
    if plays_to_followers < 5:
        engagement_risk += 25
        flags.append(f'Very low play ratio: {plays_to_followers:.2f}%')
    return {
        'likes_to_followers': round(likes_to_followers, 2),
        'plays_to_followers': round(plays_to_followers, 2),
        'risk_score': engagement_risk,
        'flags': flags
    }

Step 3: Analyze engagement consistency

Real accounts show natural variation in engagement. Fake engagement often looks too consistent (bot likes) or has extreme spikes (purchased engagement).

Python
import statistics

def check_engagement_consistency(data: dict) -> dict:
    videos = data['videos']
    if len(videos) < 5:
        return {'risk_score': 10, 'flags': ['Too few videos to analyze']}
    like_counts = [v.get('stats', {}).get('diggCount', 0) for v in videos]
    play_counts = [v.get('stats', {}).get('playCount', 0) for v in videos]
    flags = []
    risk = 0
    # Check if engagement is suspiciously uniform
    if like_counts and statistics.mean(like_counts) > 0:
        cv = statistics.stdev(like_counts) / statistics.mean(like_counts)  # coefficient of variation
        if cv < 0.1:  # Less than 10% variation = suspiciously uniform
            risk += 25
            flags.append(f'Suspiciously uniform likes (CV={cv:.3f})')
    # Check for sudden engagement spikes
    if play_counts:
        median_plays = statistics.median(play_counts)
        spikes = sum(1 for p in play_counts if p > median_plays * 10)
        spike_ratio = spikes / len(play_counts)
        if spike_ratio > 0.3:  # More than 30% of videos have 10x spikes
            risk += 20
            flags.append(f'{spikes}/{len(play_counts)} videos have 10x play spikes')
    # Check likes-to-comments ratio (bots rarely comment)
    for v in videos:
        s = v.get('stats', {})
        likes = s.get('diggCount', 0)
        comments = s.get('commentCount', 0)
        if likes > 1000 and comments < likes * 0.005:  # Less than 0.5% comment rate
            risk += 5
            flags.append(f'Very low comment ratio on video with {likes} likes')
            break  # Only flag once
    return {'risk_score': min(risk, 50), 'flags': flags}

Step 4: Check following/follower ratio

Accounts that follow massive numbers of accounts relative to their followers often participated in follow-for-follow schemes or used follow bots.

Python
def check_follow_ratio(data: dict) -> dict:
    followers = max(data['followers'], 1)
    following = data['following']
    ratio = following / followers
    flags = []
    risk = 0
    if followers > 10000 and ratio > 1.0:
        risk += 30
        flags.append(f'Following > followers ({following:,} / {followers:,})')
    elif followers > 10000 and ratio > 0.5:
        risk += 15
        flags.append(f'High follow ratio: {ratio:.2f}')
    # Check if total likes seem inflated relative to video count
    if data['video_count'] > 0:
        likes_per_video = data['total_likes'] / data['video_count']
        expected_likes = followers * 0.05  # 5% of followers per video is generous
        if likes_per_video > expected_likes * 5:
            risk += 15
            flags.append(f'Inflated total likes: {likes_per_video:,.0f}/video vs {expected_likes:,.0f} expected')
    return {'follow_ratio': round(ratio, 3), 'risk_score': risk, 'flags': flags}

Step 5: Generate the full fraud report

Combine all detection signals into a comprehensive fraud risk assessment with an overall risk score and detailed breakdown.

Python
def fraud_report(username: str) -> dict:
    data = fetch_creator_data(username)
    engagement = check_engagement_ratio(data)
    consistency = check_engagement_consistency(data)
    follow = check_follow_ratio(data)
    total_risk = engagement['risk_score'] + consistency['risk_score'] + follow['risk_score']
    all_flags = engagement.get('flags', []) + consistency.get('flags', []) + follow.get('flags', [])
    verdict = 'LOW RISK' if total_risk < 20 else 'MEDIUM RISK' if total_risk < 50 else 'HIGH RISK'
    report = {
        'username': username,
        'followers': data['followers'],
        'total_risk_score': min(total_risk, 100),
        'verdict': verdict,
        'engagement_check': engagement,
        'consistency_check': consistency,
        'follow_check': follow,
        'all_flags': all_flags,
        'credits_used': 2
    }
    print(f'@{username}: {verdict} ({total_risk}/100)')
    print(f'  Followers: {data["followers"]:,}')
    for flag in all_flags:
        print(f'  - {flag}')
    return report

# report = fraud_report('suspicious_creator')

Python Example

Python
import os, requests, statistics

API_KEY = os.environ['SCAVIO_API_KEY']
TT = 'https://api.scavio.dev/api/v1/tiktok'

def tt(endpoint, body):
    return requests.post(f'{TT}/{endpoint}',
        headers={'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'},
        json=body).json()

def detect_fake(username):
    profile = tt('user/info', {'username': username}).get('data', {})
    stats = profile.get('stats', {})
    followers = stats.get('followerCount', 1)
    posts = tt('user/posts', {'username': username, 'count': 20, 'cursor': 0})
    videos = posts.get('data', {}).get('videos', [])
    avg_likes = sum(v.get('stats', {}).get('diggCount', 0) for v in videos) / max(len(videos), 1)
    ratio = (avg_likes / followers) * 100
    risk = 'HIGH' if ratio < 0.5 else 'MEDIUM' if ratio < 1.0 else 'LOW'
    print(f'@{username}: {risk} RISK (like ratio: {ratio:.2f}%, {followers:,} followers)')

detect_fake('example_creator')

JavaScript Example

JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;
const TT = 'https://api.scavio.dev/api/v1/tiktok';

async function tt(endpoint, body) {
  const r = await fetch(`${TT}/${endpoint}`, {
    method: 'POST',
    headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
    body: JSON.stringify(body)
  });
  return r.json();
}

async function detectFake(username) {
  const profile = await tt('user/info', { username });
  const followers = profile.data?.stats?.followerCount || 1;
  const posts = await tt('user/posts', { username, count: 20, cursor: 0 });
  const videos = posts.data?.videos || [];
  const avgLikes = videos.reduce((s, v) => s + (v.stats?.diggCount || 0), 0) / Math.max(videos.length, 1);
  const ratio = (avgLikes / followers) * 100;
  console.log(`@${username}: ${ratio < 0.5 ? 'HIGH' : ratio < 1 ? 'MED' : 'LOW'} RISK (${ratio.toFixed(2)}%)`);
}

detectFake('example_creator').catch(console.error);

Expected Output

JSON
@suspicious_creator: HIGH RISK (72/100)
  Followers: 500,000
  - Very low like ratio: 0.31%
  - Suspiciously uniform likes (CV=0.082)
  - Following > followers (520,000 / 500,000)

@legitimate_creator: LOW RISK (8/100)
  Followers: 85,000
  (no flags)

Credits used: 2 per creator ($0.01)

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.9+ installed. requests library installed. A Scavio API key from scavio.dev. TikTok usernames to analyze. 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

Build a fake follower detection system for TikTok using API data. Analyze engagement ratios, follower patterns, and content signals to spot fraud.