AI-Generated Content Detection: Spot Fake Engagement & Bot Comments
You wake up to 200 new comments on your post. Excitement!
Then you read them. "Great post!" "Amazing content!" "Love this!" Generic. Repetitive. Worthless.
Bot comments.
Or worse: you partner with an influencer who has 500K followers. Their post gets 10,000 likes but zero sales. Why? Because 80% of their audience is fake.
I learned this the hard way. Paid $5,000 for an influencer collaboration. Got amazing engagement numbers. Zero actual customers. The influencer had bought followers and engagement bots were doing all the commenting.
Now I analyze every account before working with them. I detect fake followers in seconds. I filter bot comments automatically. I verify authenticity before spending a dollar.
Let me show you how to spot fake engagement and AI-generated content using data analysis.
Why Fake Engagement Matters
Fake engagement is not just annoying—it costs you money.
The Influencer Scam
You pay an influencer based on their follower count. But 60% of their followers are bots. You just paid 60% more than the actual value.
Real case: A brand spent $50,000 on micro-influencers. After analyzing, we discovered 70% of their combined audience was fake. They wasted $35,000.
The Algorithm Problem
Platforms are getting better at detecting fake engagement. When bots interact with your content, the algorithm sees low-quality engagement and reduces your reach to real people.
You think you are boosting your post. Actually you are killing it.
The Data Pollution
You make decisions based on analytics. But if 40% of your engagement is fake, your data is worthless. You optimize for the wrong things.
You think carousel posts perform best because they get the most engagement. Actually bots just prefer carousel posts. Real humans prefer videos.
Detect Fake Followers
First, analyze an account to check if their followers are real.
Red Flag 1: Engagement Rate
Real engagement rates by follower count:
- Under 10K followers: 5-8% engagement
- 10K-100K followers: 3-5% engagement
- 100K-1M followers: 1-3% engagement
- Over 1M followers: 0.5-2% engagement
If someone has 500K followers and 1% engagement, that is normal. If they have 500K followers and 0.1% engagement, most followers are fake.
const axios = require('axios');
async function analyzeAccount(handle, platform = 'instagram') {
try {
const response = await axios.get(
`https://api.sociavault.com/${platform}/profile`,
{
params: { handle: handle },
headers: {
'X-API-Key': process.env.SOCIAVAULT_API_KEY
}
}
);
const profile = response.data.profile;
// Get recent posts for engagement calculation
const postsResponse = await axios.get(
`https://api.sociavault.com/${platform}/posts`,
{
params: { handle: handle, amount: 12 },
headers: {
'X-API-Key': process.env.SOCIAVAULT_API_KEY
}
}
);
const posts = platform === 'instagram' ? postsResponse.data.posts : postsResponse.data.videos;
// Calculate average engagement
let totalEngagement = 0;
posts.forEach(post => {
if (platform === 'instagram') {
totalEngagement += post.likesCount + post.commentsCount;
} else {
totalEngagement += post.diggCount + post.commentCount;
}
});
const avgEngagement = totalEngagement / posts.length;
const followers = profile.followersCount;
const engagementRate = ((avgEngagement / followers) * 100).toFixed(2);
// Determine if engagement rate is suspicious
let expectedRange;
if (followers < 10000) expectedRange = '5-8%';
else if (followers < 100000) expectedRange = '3-5%';
else if (followers < 1000000) expectedRange = '1-3%';
else expectedRange = '0.5-2%';
const expectedMin = parseFloat(expectedRange.split('-')[0]);
const isSuspicious = parseFloat(engagementRate) < expectedMin / 2;
console.log(`\n=== ACCOUNT ANALYSIS: @${handle} ===`);
console.log(`Platform: ${platform}`);
console.log(`Followers: ${followers.toLocaleString()}`);
console.log(`Avg Engagement: ${avgEngagement.toFixed(0)}`);
console.log(`Engagement Rate: ${engagementRate}%`);
console.log(`Expected Range: ${expectedRange}`);
console.log(`Status: ${isSuspicious ? '⚠️ SUSPICIOUS - Possible fake followers' : '✅ Normal engagement rate'}`);
return {
handle,
followers,
avgEngagement,
engagementRate: parseFloat(engagementRate),
isSuspicious,
expectedRange
};
} catch (error) {
console.error('Failed to analyze account:', error.message);
return null;
}
}
// Analyze potential influencer
const analysis = await analyzeAccount('potential_influencer', 'instagram');
Red Flag 2: Follower Growth Pattern
Real accounts grow gradually. Fake accounts show sudden spikes when they buy followers.
async function analyzeGrowthPattern(handle, platform = 'instagram') {
// In practice, you'd track follower count over time
// For demo, we'll simulate the concept
const historicalData = [
{ date: '2024-01-01', followers: 5000 },
{ date: '2024-02-01', followers: 5200 },
{ date: '2024-03-01', followers: 5350 },
{ date: '2024-04-01', followers: 15000 }, // Suspicious spike!
{ date: '2024-05-01', followers: 15100 },
{ date: '2024-06-01', followers: 15050 }
];
console.log(`\n=== GROWTH PATTERN ANALYSIS ===\n`);
const spikes = [];
for (let i = 1; i < historicalData.length; i++) {
const prev = historicalData[i - 1].followers;
const current = historicalData[i].followers;
const growth = ((current - prev) / prev * 100).toFixed(1);
console.log(`${historicalData[i].date}: ${current.toLocaleString()} (+${growth}%)`);
// Flag suspicious growth (over 50% in one month)
if (parseFloat(growth) > 50) {
spikes.push({
date: historicalData[i].date,
growth: growth,
followers: current
});
}
}
if (spikes.length > 0) {
console.log('\n⚠️ SUSPICIOUS GROWTH SPIKES DETECTED:');
spikes.forEach(spike => {
console.log(`${spike.date}: +${spike.growth}% (likely purchased followers)`);
});
} else {
console.log('\n✅ Organic growth pattern');
}
return spikes;
}
const growthAnalysis = await analyzeGrowthPattern('influencer_account');
Red Flag 3: Follower Quality
Check if followers have profile pictures, posts, and real names—or if they are empty bot accounts.
async function analyzeFollowerQuality(handle, platform = 'instagram', sampleSize = 50) {
try {
// Get follower list (sample)
const response = await axios.get(
`https://api.sociavault.com/${platform}/followers`,
{
params: {
handle: handle,
amount: sampleSize
},
headers: {
'X-API-Key': process.env.SOCIAVAULT_API_KEY
}
}
);
const followers = response.data.followers;
let suspiciousCount = 0;
const redFlags = {
noProfilePic: 0,
noPosts: 0,
newAccount: 0,
suspiciousUsername: 0
};
followers.forEach(follower => {
let flags = 0;
// Check for default profile pic
if (!follower.profilePicUrl || follower.profilePicUrl.includes('default')) {
redFlags.noProfilePic++;
flags++;
}
// Check post count
if (follower.postsCount === 0) {
redFlags.noPosts++;
flags++;
}
// Check username pattern (bots often have random numbers)
const username = follower.username;
const numberRatio = (username.match(/\d/g) || []).length / username.length;
if (numberRatio > 0.4) {
redFlags.suspiciousUsername++;
flags++;
}
// Mark as suspicious if multiple red flags
if (flags >= 2) {
suspiciousCount++;
}
});
const suspiciousPercent = ((suspiciousCount / followers.length) * 100).toFixed(1);
console.log(`\n=== FOLLOWER QUALITY ANALYSIS ===`);
console.log(`Sample Size: ${followers.length} followers`);
console.log(`\nRed Flags:`);
console.log(`- No profile pic: ${redFlags.noProfilePic} (${(redFlags.noProfilePic/followers.length*100).toFixed(1)}%)`);
console.log(`- No posts: ${redFlags.noPosts} (${(redFlags.noPosts/followers.length*100).toFixed(1)}%)`);
console.log(`- Suspicious username: ${redFlags.suspiciousUsername} (${(redFlags.suspiciousUsername/followers.length*100).toFixed(1)}%)`);
console.log(`\nSuspicious Followers: ${suspiciousCount} (${suspiciousPercent}%)`);
let assessment;
if (parseFloat(suspiciousPercent) < 10) {
assessment = '✅ High quality follower base';
} else if (parseFloat(suspiciousPercent) < 30) {
assessment = '⚠️ Some fake followers present';
} else {
assessment = '🚫 Majority fake followers - DO NOT WORK WITH THIS ACCOUNT';
}
console.log(`\nAssessment: ${assessment}`);
return {
totalSampled: followers.length,
suspiciousCount,
suspiciousPercent: parseFloat(suspiciousPercent),
assessment
};
} catch (error) {
console.error('Failed to analyze followers:', error.message);
return null;
}
}
const followerQuality = await analyzeFollowerQuality('influencer_account', 'instagram', 100);
Detect Bot Comments
Now identify which comments are from bots versus real people.
Pattern 1: Generic Praise
Bots use generic compliments:
function detectGenericComment(text) {
const genericPhrases = [
'great post',
'nice post',
'love this',
'amazing content',
'awesome',
'cool',
'nice',
'great',
'love it',
'beautiful',
'wonderful',
'fantastic',
'incredible',
'inspiring'
];
const text_lower = text.toLowerCase().trim();
// Check if comment is just a generic phrase
const isGeneric = genericPhrases.some(phrase => {
return text_lower === phrase || text_lower === phrase + '!' || text_lower === phrase + ' 👍' || text_lower === phrase + ' ❤️';
});
// Check if comment is extremely short (under 10 chars)
const isTooShort = text.length < 10;
// Check if comment is only emojis
const emojiPattern = /^[\u{1F300}-\u{1F9FF}\s]+$/u;
const isOnlyEmojis = emojiPattern.test(text);
return isGeneric || (isTooShort && !text.includes('?')) || isOnlyEmojis;
}
// Test it
console.log(detectGenericComment("Great post!")); // true
console.log(detectGenericComment("Love this content about APIs")); // false
console.log(detectGenericComment("❤️❤️❤️")); // true
console.log(detectGenericComment("This tutorial helped me fix my auth bug!")); // false
Pattern 2: Repetitive Comments
Bots often post the same comment on multiple posts:
function findRepetitiveComments(comments) {
const commentTracker = new Map();
// Track comment text frequency
comments.forEach(comment => {
const text = comment.text.toLowerCase().trim();
const current = commentTracker.get(text) || { count: 0, users: new Set() };
current.count++;
current.users.add(comment.username);
commentTracker.set(text, current);
});
// Find suspicious repeats
const suspicious = [];
commentTracker.forEach((data, text) => {
// Same text from different users = bot network
if (data.users.size >= 3 && data.count >= 5) {
suspicious.push({
text,
count: data.count,
uniqueUsers: data.users.size,
pattern: 'bot-network'
});
}
});
console.log(`\n=== REPETITIVE COMMENT ANALYSIS ===`);
console.log(`Total comments: ${comments.length}`);
console.log(`Suspicious patterns: ${suspicious.length}\n`);
if (suspicious.length > 0) {
console.log('Likely bot networks:');
suspicious.forEach(item => {
console.log(`"${item.text}" - Posted ${item.count} times by ${item.uniqueUsers} users`);
});
}
return suspicious;
}
Pattern 3: Timing Patterns
Bots comment instantly (within seconds) or at exact intervals:
function analyzeCommentTiming(comments) {
// Sort by timestamp
const sorted = [...comments].sort((a, b) => a.timestamp - b.timestamp);
const intervals = [];
for (let i = 1; i < sorted.length; i++) {
const interval = sorted[i].timestamp - sorted[i - 1].timestamp;
intervals.push({
interval,
seconds: interval / 1000,
user1: sorted[i - 1].username,
user2: sorted[i].username
});
}
// Detect suspicious patterns
const instantComments = intervals.filter(i => i.seconds < 2).length;
const exactIntervals = intervals.filter((i, idx, arr) => {
if (idx === 0) return false;
const prevInterval = arr[idx - 1].seconds;
return Math.abs(i.seconds - prevInterval) < 0.5;
}).length;
console.log(`\n=== COMMENT TIMING ANALYSIS ===`);
console.log(`Total comments: ${comments.length}`);
console.log(`Instant comments (under 2s): ${instantComments} (${(instantComments/intervals.length*100).toFixed(1)}%)`);
console.log(`Exact interval patterns: ${exactIntervals}`);
if (instantComments > intervals.length * 0.3) {
console.log('⚠️ High rate of instant comments - possible bot activity');
}
return { instantComments, exactIntervals };
}
Comprehensive Bot Detection
Combine all patterns:
async function detectBotComments(postId, platform = 'instagram') {
try {
// Get comments
const response = await axios.get(
`https://api.sociavault.com/${platform}/comments`,
{
params: {
postId: postId,
amount: 200
},
headers: {
'X-API-Key': process.env.SOCIAVAULT_API_KEY
}
}
);
const comments = response.data.comments;
console.log(`\n=== BOT COMMENT DETECTION ===`);
console.log(`Analyzing ${comments.length} comments...\n`);
const results = {
total: comments.length,
likelyBots: 0,
possibleBots: 0,
likelyReal: 0,
botComments: [],
realComments: []
};
comments.forEach(comment => {
const text = comment.text || '';
let botScore = 0;
const reasons = [];
// Check generic content
if (detectGenericComment(text)) {
botScore += 2;
reasons.push('generic-phrase');
}
// Check length
if (text.length < 15) {
botScore += 1;
reasons.push('too-short');
}
// Check for username with lots of numbers
const username = comment.username || '';
const numberRatio = (username.match(/\d/g) || []).length / username.length;
if (numberRatio > 0.4) {
botScore += 2;
reasons.push('suspicious-username');
}
// Check if user has no profile picture
if (!comment.profilePicUrl || comment.profilePicUrl.includes('default')) {
botScore += 1;
reasons.push('no-profile-pic');
}
// Classify
if (botScore >= 4) {
results.likelyBots++;
results.botComments.push({ text, username, botScore, reasons });
} else if (botScore >= 2) {
results.possibleBots++;
} else {
results.likelyReal++;
results.realComments.push({ text, username });
}
});
const botPercent = ((results.likelyBots / results.total) * 100).toFixed(1);
console.log(`Likely bots: ${results.likelyBots} (${botPercent}%)`);
console.log(`Possible bots: ${results.possibleBots}`);
console.log(`Likely real: ${results.likelyReal}`);
console.log('\n--- Sample Bot Comments ---');
results.botComments.slice(0, 5).forEach(comment => {
console.log(`@${comment.username}: "${comment.text}"`);
console.log(` Bot score: ${comment.botScore} | Reasons: ${comment.reasons.join(', ')}`);
});
console.log('\n--- Sample Real Comments ---');
results.realComments.slice(0, 5).forEach(comment => {
console.log(`@${comment.username}: "${comment.text}"`);
});
return results;
} catch (error) {
console.error('Failed to detect bot comments:', error.message);
return null;
}
}
const botAnalysis = await detectBotComments('POST_ID', 'instagram');
Detect AI-Generated Captions
Identify if someone is using AI to write their captions:
function detectAICaption(text) {
const aiIndicators = {
genericOpeners: [
'in today\'s digital landscape',
'in the ever-evolving world of',
'as we navigate',
'it\'s important to remember',
'let\'s dive into',
'looking to',
'are you ready to'
],
formalLanguage: [
'utilize',
'leverage',
'implement',
'facilitate',
'furthermore',
'moreover',
'additionally',
'subsequently'
],
aiClosers: [
'what are your thoughts',
'let me know in the comments',
'drop a comment below',
'i\'d love to hear your thoughts',
'share your experience in the comments'
]
};
const text_lower = text.toLowerCase();
let aiScore = 0;
const flags = [];
// Check for generic openers
aiIndicators.genericOpeners.forEach(opener => {
if (text_lower.startsWith(opener)) {
aiScore += 2;
flags.push('generic-opener');
}
});
// Check for overly formal language
let formalCount = 0;
aiIndicators.formalLanguage.forEach(word => {
if (text_lower.includes(word)) {
formalCount++;
}
});
if (formalCount >= 2) {
aiScore += 2;
flags.push('formal-language');
}
// Check for AI-style closers
aiIndicators.aiClosers.forEach(closer => {
if (text_lower.includes(closer)) {
aiScore += 1;
flags.push('generic-closer');
}
});
// Check length and structure (AI tends to be longer and more structured)
const paragraphs = text.split('\n\n').length;
if (text.length > 500 && paragraphs >= 3) {
aiScore += 1;
flags.push('structured-format');
}
// Check for emoji usage (AI often uses 2-3 emojis consistently)
const emojiCount = (text.match(/[\u{1F300}-\u{1F9FF}]/gu) || []).length;
if (emojiCount === 2 || emojiCount === 3) {
aiScore += 1;
flags.push('consistent-emojis');
}
return {
isLikelyAI: aiScore >= 3,
aiScore,
flags,
confidence: aiScore >= 4 ? 'high' : aiScore >= 3 ? 'medium' : 'low'
};
}
// Test it
const caption1 = "In today's digital landscape, it's important to leverage social media to facilitate engagement. What are your thoughts? 💭";
console.log(detectAICaption(caption1));
// { isLikelyAI: true, aiScore: 5, confidence: 'high' }
const caption2 = "just tried this new coffee place and OMFG it's amazing!! the latte art is insane 😍 anyone been here??";
console.log(detectAICaption(caption2));
// { isLikelyAI: false, aiScore: 0, confidence: 'low' }
Python Bot Detection with ML
For advanced detection using machine learning patterns:
import requests
import pandas as pd
import matplotlib.pyplot as plt
from collections import Counter
import re
def get_comments(post_id, platform='instagram', api_key='YOUR_KEY'):
"""Fetch comments for analysis"""
url = f'https://api.sociavault.com/{platform}/comments'
response = requests.get(
url,
params={'postId': post_id, 'amount': 200},
headers={'X-API-Key': api_key}
)
return response.json()['comments']
def calculate_bot_score(comment):
"""Calculate likelihood that comment is from a bot"""
text = comment.get('text', '')
username = comment.get('username', '')
score = 0
reasons = []
# Generic phrases
generic_phrases = ['great post', 'nice', 'love this', 'amazing', 'cool', 'awesome']
if any(phrase in text.lower() for phrase in generic_phrases) and len(text) < 20:
score += 2
reasons.append('generic')
# Too short
if len(text) < 10:
score += 1
reasons.append('short')
# Only emojis
if len(re.findall(r'[a-zA-Z]', text)) == 0 and len(text) > 0:
score += 2
reasons.append('only-emojis')
# Username with many numbers
number_ratio = len(re.findall(r'\d', username)) / max(len(username), 1)
if number_ratio > 0.4:
score += 2
reasons.append('suspicious-username')
# No profile picture indicator (would check in full implementation)
if comment.get('hasProfilePic', True) == False:
score += 1
reasons.append('no-pic')
return score, reasons
def detect_bots(comments):
"""Detect bot comments in batch"""
results = []
for comment in comments:
score, reasons = calculate_bot_score(comment)
classification = 'real'
if score >= 4:
classification = 'likely-bot'
elif score >= 2:
classification = 'possible-bot'
results.append({
'text': comment.get('text', '')[:80],
'username': comment.get('username', ''),
'bot_score': score,
'classification': classification,
'reasons': ', '.join(reasons)
})
df = pd.DataFrame(results)
return df
def visualize_bot_detection(df):
"""Create bot detection visualizations"""
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# Classification distribution
class_counts = df['classification'].value_counts()
axes[0, 0].pie(class_counts.values, labels=class_counts.index, autopct='%1.1f%%')
axes[0, 0].set_title('Comment Classification')
# Bot score distribution
axes[0, 1].hist(df['bot_score'], bins=range(0, df['bot_score'].max()+2), edgecolor='black')
axes[0, 1].set_title('Bot Score Distribution')
axes[0, 1].set_xlabel('Bot Score')
axes[0, 1].set_ylabel('Frequency')
# Reasons breakdown
all_reasons = []
for reasons in df['reasons']:
if reasons:
all_reasons.extend(reasons.split(', '))
reason_counts = Counter(all_reasons)
axes[1, 0].bar(reason_counts.keys(), reason_counts.values())
axes[1, 0].set_title('Bot Detection Reasons')
axes[1, 0].set_xlabel('Reason')
axes[1, 0].set_ylabel('Frequency')
axes[1, 0].tick_params(axis='x', rotation=45)
# Text length by classification
df.boxplot(column='bot_score', by='classification', ax=axes[1, 1])
axes[1, 1].set_title('Bot Score by Classification')
axes[1, 1].set_xlabel('Classification')
axes[1, 1].set_ylabel('Bot Score')
plt.tight_layout()
plt.savefig('bot_detection_analysis.png', dpi=300)
print("\nVisualization saved as bot_detection_analysis.png")
def print_bot_report(df):
"""Print detailed bot detection report"""
total = len(df)
likely_bots = len(df[df['classification'] == 'likely-bot'])
possible_bots = len(df[df['classification'] == 'possible-bot'])
real = len(df[df['classification'] == 'real'])
print("\n" + "="*60)
print("BOT DETECTION REPORT")
print("="*60)
print(f"\nTotal Comments: {total}")
print(f"Likely Bots: {likely_bots} ({likely_bots/total*100:.1f}%)")
print(f"Possible Bots: {possible_bots} ({possible_bots/total*100:.1f}%)")
print(f"Real Comments: {real} ({real/total*100:.1f}%)")
print("\n" + "-"*60)
print("SAMPLE BOT COMMENTS:")
print("-"*60)
bot_samples = df[df['classification'] == 'likely-bot'].head(5)
for i, row in bot_samples.iterrows():
print(f"\n@{row['username']}: \"{row['text']}\"")
print(f"Bot Score: {row['bot_score']} | Reasons: {row['reasons']}")
print("\n" + "-"*60)
print("SAMPLE REAL COMMENTS:")
print("-"*60)
real_samples = df[df['classification'] == 'real'].head(5)
for i, row in real_samples.iterrows():
print(f"\n@{row['username']}: \"{row['text']}\"")
# Usage
api_key = 'YOUR_API_KEY'
comments = get_comments('POST_ID', 'instagram', api_key)
df = detect_bots(comments)
print_bot_report(df)
visualize_bot_detection(df)
Real Bot Detection Examples
Here is what bot detection revealed for real accounts.
Example 1: Fake Influencer
Account stats: 450K followers, 3% engagement rate After analysis:
- 68% of followers had suspicious characteristics
- 71% of comments were generic bot responses
- Follower growth showed 3 massive spikes (bought followers)
- Decision: Did NOT partner with this influencer
- Money saved: $8,000
Example 2: Growing Account
Account stats: 12K followers, 7% engagement rate After analysis:
- 5% suspicious followers (normal range)
- 12% bot comments (acceptable)
- Organic growth pattern
- Decision: Partnered with confidence
- Result: 34 sales directly attributed to collaboration
Example 3: Comment Section Cleanup
Brand's own account had 40% bot comments Actions taken:
- Filtered and deleted bot comments
- Blocked suspicious accounts
- Enabled stricter comment filtering
- Result: Algorithm recognized better engagement quality and increased reach by 23%
Your Bot Detection Action Plan
- Analyze influencers before partnerships using engagement rate and follower quality checks
- Monitor your own comments and remove bots regularly
- Track bot percentage trends - sudden increases indicate problems
- Build bot detection into your workflow - check every collaboration
- Use the data to negotiate better rates with influencers
Stop wasting money on fake engagement. Start verifying authenticity.
Get your SociaVault API key and analyze any account in minutes. Know if followers are real before you spend a dollar.
The bots are everywhere. Time to detect them.
Found this helpful?
Share it with others who might benefit
Ready to Try SociaVault?
Start extracting social media data with our powerful API