Choisir le mauvais créateur TikTok pour un partenariat de marque gaspille le budget et nuit à la crédibilité. Les vanités comme le nombre d'abonnés masquent un engagement factice, des publications irrégulières et un contenu hors marque. Ce tutoriel construit un pipeline de vérification des créateurs en utilisant l'API Scavio TikTok pour vérifier les taux d'engagement réels, la cohérence du contenu, les signaux d'audience et la fréquence de publication. Chaque appel API coûte 0,005 $ et vous donne des données que les plateformes d'influenceurs facturent des centaines par mois pour y accéder.
Prérequis
- Python 3.9+ installé
- bibliothèque requests installée
- Une clé API Scavio depuis scavio.dev
- Une liste de noms d'utilisateur de créateurs TikTok à évaluer
Parcours
Étape 1: Récupérer le profil et les statistiques du créateur
Utilisez le point de terminaison du profil TikTok pour obtenir le nombre d'abonnés, le nombre d'abonnements, le total des likes et la biographie d'un créateur. Le ratio abonnés/abonnements est un signal rapide d'authenticité.
import os, requests, time
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
TT_URL = 'https://api.scavio.dev/api/v1/tiktok'
TT_H = {'Authorization': f'Bearer {SCAVIO_KEY}', 'Content-Type': 'application/json'}
def get_creator_profile(username: str) -> dict:
"""Get creator profile data."""
resp = requests.post(f'{TT_URL}/profile', headers=TT_H,
json={'username': username})
data = resp.json().get('data', {})
user = data.get('user', {})
stats = data.get('stats', {})
return {
'username': username,
'nickname': user.get('nickname', ''),
'bio': user.get('signature', ''),
'verified': user.get('verified', False),
'sec_user_id': user.get('secUid', ''),
'followers': stats.get('followerCount', 0),
'following': stats.get('followingCount', 0),
'total_likes': stats.get('heartCount', 0),
'total_videos': stats.get('videoCount', 0),
'follower_ratio': stats.get('followerCount', 0) / max(stats.get('followingCount', 1), 1),
}
profile = get_creator_profile('charlidamelio')
print(f"Creator: @{profile['username']} ({profile['nickname']})")
print(f"Followers: {profile['followers']:,}")
print(f"Total likes: {profile['total_likes']:,}")
print(f"Videos: {profile['total_videos']}")
print(f"Follower ratio: {profile['follower_ratio']:.0f}:1")
print(f"Verified: {profile['verified']}")Étape 2: Analyser le contenu récent et les taux d'engagement
Récupérez les publications récentes du créateur et calculez les taux d'engagement réels. Un taux d'engagement moyen inférieur à 2 % sur TikTok est un signal d'alarme pour les faux abonnés.
def analyze_content(username: str, sec_user_id: str) -> dict:
"""Analyze a creator's recent content for engagement quality."""
resp = requests.post(f'{TT_URL}/user/posts', headers=TT_H,
json={'sec_user_id': sec_user_id, 'count': 20})
posts = resp.json().get('data', {}).get('videos', [])
if not posts:
return {'error': 'No posts found'}
engagement_rates = []
view_counts = []
for post in posts:
stats = post.get('stats', {})
views = stats.get('playCount', 0)
likes = stats.get('diggCount', 0)
comments = stats.get('commentCount', 0)
shares = stats.get('shareCount', 0)
if views > 0:
eng_rate = (likes + comments + shares) / views
engagement_rates.append(eng_rate)
view_counts.append(views)
avg_engagement = sum(engagement_rates) / len(engagement_rates) if engagement_rates else 0
avg_views = sum(view_counts) / len(view_counts) if view_counts else 0
view_consistency = min(view_counts) / max(view_counts) if view_counts and max(view_counts) > 0 else 0
return {
'posts_analyzed': len(posts),
'avg_engagement_rate': avg_engagement,
'avg_views': avg_views,
'min_views': min(view_counts) if view_counts else 0,
'max_views': max(view_counts) if view_counts else 0,
'view_consistency': view_consistency, # Higher = more consistent
'engagement_quality': 'good' if avg_engagement > 0.05 else 'average' if avg_engagement > 0.02 else 'low',
}
# Need sec_user_id from profile step
if profile.get('sec_user_id'):
content = analyze_content(profile['username'], profile['sec_user_id'])
print(f"Content Analysis: @{profile['username']}")
print(f" Posts analyzed: {content['posts_analyzed']}")
print(f" Avg engagement: {content['avg_engagement_rate']:.1%}")
print(f" Avg views: {content['avg_views']:,.0f}")
print(f" View consistency: {content['view_consistency']:.0%}")
print(f" Quality: {content['engagement_quality']}")Étape 3: Vérifier la sécurité de la marque et la pertinence du contenu
Recherchez dans les descriptions vidéo du créateur un contenu sans risque pour la marque. Vérifiez si son contenu correspond à la niche de votre marque en analysant les sujets des vidéos.
def check_brand_fit(username: str, sec_user_id: str, brand_keywords: list) -> dict:
"""Check if a creator's content fits your brand."""
resp = requests.post(f'{TT_URL}/user/posts', headers=TT_H,
json={'sec_user_id': sec_user_id, 'count': 20})
posts = resp.json().get('data', {}).get('videos', [])
descriptions = [post.get('desc', '').lower() for post in posts]
all_text = ' '.join(descriptions)
# Check brand keyword relevance
keyword_matches = {kw: sum(1 for d in descriptions if kw.lower() in d)
for kw in brand_keywords}
relevance = sum(keyword_matches.values()) / (len(descriptions) * len(brand_keywords)) if descriptions and brand_keywords else 0
# Brand safety checks
unsafe_terms = ['controversial', 'scandal', 'banned', 'nsfw', 'drama']
safety_flags = [t for t in unsafe_terms if t in all_text]
# Check if creator does sponsored content
sponsored_count = sum(1 for d in descriptions if any(w in d for w in ['#ad', '#sponsored', '#partner', 'collab']))
return {
'keyword_relevance': keyword_matches,
'relevance_score': relevance,
'safety_flags': safety_flags,
'brand_safe': len(safety_flags) == 0,
'sponsored_posts': sponsored_count,
'sponsored_rate': sponsored_count / len(descriptions) if descriptions else 0,
}
if profile.get('sec_user_id'):
brand_fit = check_brand_fit(profile['username'], profile['sec_user_id'],
['dance', 'fashion', 'lifestyle', 'beauty'])
print(f"Brand Fit Analysis:")
print(f" Relevance: {brand_fit['relevance_score']:.0%}")
print(f" Brand safe: {brand_fit['brand_safe']}")
print(f" Sponsored posts: {brand_fit['sponsored_posts']} ({brand_fit['sponsored_rate']:.0%})")
print(f" Keywords: {brand_fit['keyword_relevance']}")Étape 4: Générer le rapport de vérification du créateur
Combinez tous les signaux en un score de vérification et une recommandation. Le rapport donne un feu vert/rouge clair pour chaque créateur.
def vet_creator(username: str, brand_keywords: list) -> dict:
"""Full creator vetting report."""
profile = get_creator_profile(username)
time.sleep(0.3)
if not profile.get('sec_user_id'):
return {'username': username, 'verdict': 'ERROR', 'reason': 'Profile not found'}
content = analyze_content(username, profile['sec_user_id'])
time.sleep(0.3)
brand_fit = check_brand_fit(username, profile['sec_user_id'], brand_keywords)
# Scoring (0-100)
scores = {
'engagement': min(content.get('avg_engagement_rate', 0) * 1000, 30), # Max 30
'consistency': content.get('view_consistency', 0) * 20, # Max 20
'relevance': brand_fit.get('relevance_score', 0) * 25, # Max 25
'safety': 15 if brand_fit.get('brand_safe') else 0, # Max 15
'authenticity': min(profile.get('follower_ratio', 0) / 10, 10), # Max 10
}
total = sum(scores.values())
verdict = 'APPROVE' if total >= 60 else 'REVIEW' if total >= 40 else 'REJECT'
report = {
'username': username,
'followers': profile['followers'],
'avg_engagement': content.get('avg_engagement_rate', 0),
'avg_views': content.get('avg_views', 0),
'brand_safe': brand_fit.get('brand_safe'),
'relevance': brand_fit.get('relevance_score', 0),
'scores': scores,
'total_score': total,
'verdict': verdict,
'credits_used': 3,
'cost': 0.015,
}
print(f"\nCreator Report: @{username}")
print(f"Verdict: {verdict} (Score: {total:.0f}/100)")
print(f" Followers: {profile['followers']:,}")
print(f" Engagement: {content.get('avg_engagement_rate', 0):.1%}")
print(f" Brand safe: {brand_fit.get('brand_safe')}")
print(f" Relevance: {brand_fit.get('relevance_score', 0):.0%}")
for k, v in scores.items():
print(f" {k:15s}: {v:.1f}")
return report
report = vet_creator('charlidamelio', ['dance', 'fashion', 'lifestyle'])Exemple Python
import os, requests, time
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
TT_H = {'Authorization': f'Bearer {SCAVIO_KEY}', 'Content-Type': 'application/json'}
def vet_creator(username):
# Get profile
resp = requests.post('https://api.scavio.dev/api/v1/tiktok/profile', headers=TT_H,
json={'username': username})
data = resp.json().get('data', {})
stats = data.get('stats', {})
uid = data.get('user', {}).get('secUid', '')
time.sleep(0.3)
# Get posts
resp2 = requests.post('https://api.scavio.dev/api/v1/tiktok/user/posts', headers=TT_H,
json={'sec_user_id': uid, 'count': 10})
posts = resp2.json().get('data', {}).get('videos', [])
eng_rates = []
for p in posts:
s = p.get('stats', {})
views = s.get('playCount', 1)
eng_rates.append((s.get('diggCount', 0) + s.get('commentCount', 0)) / views)
avg_eng = sum(eng_rates) / len(eng_rates) if eng_rates else 0
print(f'@{username}: {stats.get("followerCount",0):,} followers, {avg_eng:.1%} engagement')
vet_creator('charlidamelio')Exemple JavaScript
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
const TT_H = { Authorization: `Bearer ${SCAVIO_KEY}`, 'Content-Type': 'application/json' };
async function vetCreator(username) {
const profile = await fetch('https://api.scavio.dev/api/v1/tiktok/profile', {
method: 'POST', headers: TT_H, body: JSON.stringify({ username })
}).then(r => r.json());
const stats = profile.data?.stats || {};
const uid = profile.data?.user?.secUid || '';
const posts = await fetch('https://api.scavio.dev/api/v1/tiktok/user/posts', {
method: 'POST', headers: TT_H, body: JSON.stringify({ sec_user_id: uid, count: 10 })
}).then(r => r.json());
const videos = posts.data?.videos || [];
const engRates = videos.map(v => {
const s = v.stats || {};
return (s.diggCount + s.commentCount) / (s.playCount || 1);
});
const avgEng = engRates.length ? engRates.reduce((a,b) => a+b, 0) / engRates.length : 0;
console.log(`@${username}: ${(stats.followerCount || 0).toLocaleString()} followers, ${(avgEng * 100).toFixed(1)}% engagement`);
}
vetCreator('charlidamelio');Sortie attendue
Creator: @charlidamelio (Charli D'Amelio)
Followers: 155,200,000
Total likes: 11,800,000,000
Videos: 2,340
Follower ratio: 4250:1
Verified: True
Content Analysis: @charlidamelio
Posts analyzed: 20
Avg engagement: 5.2%
Avg views: 8,450,000
View consistency: 45%
Quality: good
Creator Report: @charlidamelio
Verdict: APPROVE (Score: 72/100)
engagement : 30.0
consistency : 9.0
relevance : 18.8
safety : 15.0
authenticity : 10.0