TikTok hashtag performance shifts daily as trends rise and fall. This tracker monitors hashtag video counts, engagement rates, and top creators over time. Run it daily to spot trending hashtags early and track campaign performance. Each hashtag check costs $0.005.
Prerequisites
- Python 3.8+
- requests library
- A Scavio API key from scavio.dev
- List of hashtags to monitor
Walkthrough
Step 1: Fetch hashtag video data
Pull recent videos for each target hashtag.
import os, requests, json
from datetime import datetime
from collections import Counter
API_KEY = os.environ['SCAVIO_API_KEY']
TH = {'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'}
HASHTAGS = ['serpapi', 'aiagents', 'devtools', 'nocode', 'buildinpublic']
def get_hashtag_videos(hashtag):
data = requests.post('https://api.scavio.dev/api/v1/tiktok/hashtag/videos',
headers=TH, json={'hashtag': hashtag}).json()
videos = data.get('videos', data.get('data', {}).get('videos', []))
return [{'id': v.get('id', ''), 'desc': v.get('desc', '')[:80],
'plays': v.get('stats', {}).get('playCount', 0),
'likes': v.get('stats', {}).get('diggCount', 0),
'comments': v.get('stats', {}).get('commentCount', 0),
'shares': v.get('stats', {}).get('shareCount', 0),
'author': v.get('author', {}).get('uniqueId', 'unknown')} for v in videos]
hashtag_data = {}
for tag in HASHTAGS:
videos = get_hashtag_videos(tag)
total_plays = sum(v['plays'] for v in videos)
total_likes = sum(v['likes'] for v in videos)
hashtag_data[tag] = {'videos': videos, 'total_plays': total_plays, 'total_likes': total_likes}
print(f' #{tag}: {len(videos)} videos | {total_plays:,} plays | {total_likes:,} likes')
print(f'\nCost: ${len(HASHTAGS) * 0.005:.3f}')Step 2: Calculate engagement metrics
Compute engagement rate, virality score, and top creators per hashtag.
def analyze_hashtag(tag, data):
videos = data['videos']
if not videos:
return {'tag': tag, 'engagement_rate': 0, 'virality': 0, 'top_creators': []}
total_plays = sum(v['plays'] for v in videos)
total_likes = sum(v['likes'] for v in videos)
total_comments = sum(v['comments'] for v in videos)
total_shares = sum(v['shares'] for v in videos)
engagement_rate = (total_likes + total_comments + total_shares) / total_plays if total_plays else 0
virality = total_shares / len(videos) if videos else 0
# Top creators
creators = Counter(v['author'] for v in videos)
top = creators.most_common(3)
return {
'tag': tag,
'video_count': len(videos),
'total_plays': total_plays,
'engagement_rate': engagement_rate,
'virality': virality,
'top_creators': [{'username': c[0], 'videos': c[1]} for c in top]
}
print(f'\n=== Hashtag Performance ===')
analyses = []
for tag, data in hashtag_data.items():
analysis = analyze_hashtag(tag, data)
analyses.append(analysis)
er_pct = analysis['engagement_rate'] * 100
print(f' #{tag:20} | ER: {er_pct:.1f}% | Virality: {analysis["virality"]:.0f} shares/video')
for c in analysis['top_creators'][:2]:
print(f' @{c["username"]}: {c["videos"]} videos')Step 3: Track changes over time
Store daily snapshots and detect trending or declining hashtags.
def track_hashtag_trends(analyses, history_file='hashtag_history.json'):
try:
with open(history_file) as f:
history = json.load(f)
except FileNotFoundError:
history = []
today = {
'date': datetime.now().strftime('%Y-%m-%d'),
'hashtags': {a['tag']: {
'videos': a['video_count'],
'plays': a['total_plays'],
'engagement': a['engagement_rate']
} for a in analyses}
}
history.append(today)
with open(history_file, 'w') as f:
json.dump(history, f, indent=2)
print(f'\n=== Hashtag Trends ===')
if len(history) >= 2:
prev = history[-2]
for tag, current in today['hashtags'].items():
prev_data = prev.get('hashtags', {}).get(tag, {})
if prev_data:
play_delta = current['plays'] - prev_data.get('plays', 0)
direction = 'RISING' if play_delta > 0 else 'FALLING' if play_delta < 0 else 'STABLE'
print(f' #{tag:20} | {direction:8} | plays: {play_delta:+,}')
else:
print(f' #{tag:20} | NEW')
else:
print(f' First scan. Run again tomorrow to see trends.')
# Rank by engagement rate
sorted_tags = sorted(analyses, key=lambda a: a['engagement_rate'], reverse=True)
print(f'\n Engagement Ranking:')
for i, a in enumerate(sorted_tags, 1):
er_pct = a['engagement_rate'] * 100
print(f' {i}. #{a["tag"]:20} | {er_pct:.1f}% ER | {a["total_plays"]:,} plays')
print(f'\n Daily cost: ${len(HASHTAGS) * 0.005:.3f}')
track_hashtag_trends(analyses)Python Example
import os, requests
TH = {'Authorization': f'Bearer {os.environ["SCAVIO_API_KEY"]}', 'Content-Type': 'application/json'}
def track_hashtag(tag):
data = requests.post('https://api.scavio.dev/api/v1/tiktok/hashtag/videos',
headers=TH, json={'hashtag': tag}).json()
videos = data.get('videos', data.get('data', {}).get('videos', []))
plays = sum(v.get('stats', {}).get('playCount', 0) for v in videos)
print(f'#{tag}: {len(videos)} videos, {plays:,} plays')
for tag in ['aiagents', 'devtools']:
track_hashtag(tag)
print('Cost: $0.010')JavaScript Example
const TH = { 'Authorization': `Bearer ${process.env.SCAVIO_API_KEY}`, 'Content-Type': 'application/json' };
for (const tag of ['aiagents', 'devtools']) {
const data = await fetch('https://api.scavio.dev/api/v1/tiktok/hashtag/videos', {
method: 'POST', headers: TH, body: JSON.stringify({ hashtag: tag })
}).then(r => r.json());
const videos = data.videos || data.data?.videos || [];
console.log(`#${tag}: ${videos.length} videos`);
}Expected Output
#serpapi: 8 videos | 45,000 plays | 3,200 likes
#aiagents: 15 videos | 320,000 plays | 28,000 likes
#devtools: 12 videos | 180,000 plays | 15,000 likes
#nocode: 20 videos | 550,000 plays | 45,000 likes
#buildinpublic: 18 videos | 210,000 plays | 19,000 likes
Cost: $0.025
=== Hashtag Performance ===
#aiagents | ER: 9.1% | Virality: 420 shares/video
#nocode | ER: 8.5% | Virality: 380 shares/video
Engagement Ranking:
1. #aiagents | 9.1% ER | 320,000 plays
2. #nocode | 8.5% ER | 550,000 plays
3. #buildinpublic | 9.3% ER | 210,000 plays
Daily cost: $0.025