Your client sells vegan protein powder. They need 50 micro-influencers in the fitness + vegan niche. Budget: $10K.
You open Instagram. Search "vegan fitness." Scroll through profiles one by one. Copy-paste usernames into a spreadsheet. Check engagement manually. Repeat 200 times.
That's 8 hours of your life you're not getting back.
I built a tool that finds, filters, and ranks creators by niche in minutes. It searches across platforms, scores relevance, and spits out a ranked list. Here's the entire thing.
The Stack
- Node.js – runtime
- SociaVault API – search creators, fetch profiles, get post data
- Natural language matching – keyword relevance scoring
The Architecture
Search Query ("vegan fitness micro-influencer")
↓
Platform Search (TikTok, Instagram, YouTube)
↓
Fetch Full Profiles
↓
Filter (followers, engagement, niche)
↓
Rank by Relevance Score
↓
Output: Ranked Creator List
Step 1: Set Up the API Client
const axios = require('axios');
const API_BASE = 'https://api.sociavault.com/v1';
const API_KEY = process.env.SOCIAVAULT_API_KEY;
const api = axios.create({
baseURL: API_BASE,
headers: { 'x-api-key': API_KEY },
});
async function searchUsers(platform, keyword, limit = 50) {
const { data } = await api.get(`/${platform}/search/users`, {
params: { keyword, limit },
});
return data.users;
}
async function getProfile(platform, username) {
const { data } = await api.get(`/${platform}/profile/${username}`);
return data;
}
async function getRecentPosts(platform, username, limit = 20) {
const { data } = await api.get(`/${platform}/posts/${username}`, {
params: { limit },
});
return data.posts;
}
Step 2: Multi-Platform Search
Don't limit yourself to one platform. A creator might be huge on TikTok but undiscovered on Instagram.
async function multiPlatformSearch(keywords, platforms = ['tiktok', 'instagram', 'youtube']) {
const allResults = [];
for (const platform of platforms) {
for (const keyword of keywords) {
try {
const users = await searchUsers(platform, keyword, 30);
allResults.push(
...users.map(user => ({
...user,
platform,
searchKeyword: keyword,
}))
);
} catch (err) {
console.error(`Search failed for ${keyword} on ${platform}:`, err.message);
}
}
}
// Deduplicate by username + platform
const seen = new Set();
return allResults.filter(user => {
const key = `${user.platform}:${user.username}`;
if (seen.has(key)) return false;
seen.add(key);
return true;
});
}
Usage:
const candidates = await multiPlatformSearch(
['vegan fitness', 'plant based athlete', 'vegan gym', 'vegan protein'],
['tiktok', 'instagram']
);
console.log(`Found ${candidates.length} candidates`);
// Found 187 candidates
Step 3: Filter by Criteria
Most creators won't match your requirements. Filter aggressively.
function filterCandidates(candidates, criteria) {
return candidates.filter(user => {
// Follower range (micro-influencer: 10K-100K)
if (user.followerCount < criteria.minFollowers) return false;
if (user.followerCount > criteria.maxFollowers) return false;
// Must have posted recently (active creator)
if (user.lastPostDate) {
const daysSincePost = (Date.now() - new Date(user.lastPostDate)) / (1000 * 60 * 60 * 24);
if (daysSincePost > criteria.maxDaysSincePost) return false;
}
// Minimum post count (established creator)
if (user.postCount < criteria.minPosts) return false;
return true;
});
}
// Filter to micro-influencers who posted within 14 days
const filtered = filterCandidates(candidates, {
minFollowers: 10000,
maxFollowers: 100000,
maxDaysSincePost: 14,
minPosts: 50,
});
console.log(`${filtered.length} candidates after filtering`);
// 63 candidates after filtering
Step 4: Enrich with Full Profile Data
The search results give you basics. Now pull detailed profiles.
async function enrichCandidates(candidates) {
const enriched = [];
for (const candidate of candidates) {
try {
const profile = await getProfile(candidate.platform, candidate.username);
const posts = await getRecentPosts(candidate.platform, candidate.username, 20);
// Calculate engagement rate from actual posts
const avgEngagement = posts.reduce((sum, post) => {
return sum + ((post.likeCount + post.commentCount) / profile.followerCount) * 100;
}, 0) / posts.length;
enriched.push({
username: candidate.username,
platform: candidate.platform,
followers: profile.followerCount,
following: profile.followingCount,
posts: profile.postCount,
bio: profile.biography,
avgEngagement: parseFloat(avgEngagement.toFixed(2)),
avgLikes: Math.round(posts.reduce((s, p) => s + p.likeCount, 0) / posts.length),
avgComments: Math.round(posts.reduce((s, p) => s + p.commentCount, 0) / posts.length),
recentPostDates: posts.slice(0, 5).map(p => p.createdAt),
topHashtags: extractTopHashtags(posts),
});
} catch (err) {
console.error(`Failed to enrich ${candidate.username}:`, err.message);
}
}
return enriched;
}
function extractTopHashtags(posts) {
const hashtagCount = {};
for (const post of posts) {
const tags = post.caption?.match(/#\w+/g) || [];
for (const tag of tags) {
hashtagCount[tag.toLowerCase()] = (hashtagCount[tag.toLowerCase()] || 0) + 1;
}
}
return Object.entries(hashtagCount)
.sort((a, b) => b[1] - a[1])
.slice(0, 10)
.map(([tag]) => tag);
}
Step 5: Score Niche Relevance
This is where the magic happens. How relevant is each creator to your specific niche?
function scoreNicheRelevance(creator, nicheKeywords) {
let score = 0;
// Check bio for keywords (high signal)
const bioLower = (creator.bio || '').toLowerCase();
for (const keyword of nicheKeywords) {
if (bioLower.includes(keyword.toLowerCase())) {
score += 20;
}
}
// Check hashtags for niche relevance
for (const tag of creator.topHashtags) {
for (const keyword of nicheKeywords) {
if (tag.includes(keyword.toLowerCase())) {
score += 10;
}
}
}
// Engagement rate bonus (higher engagement = more relevant audience)
if (creator.avgEngagement > 5) score += 15;
else if (creator.avgEngagement > 3) score += 10;
else if (creator.avgEngagement > 1.5) score += 5;
// Follower sweet spot bonus (25K-75K is the micro-influencer sweet spot)
if (creator.followers >= 25000 && creator.followers <= 75000) {
score += 10;
}
return Math.min(100, score);
}
// Score all candidates
const nicheKeywords = ['vegan', 'plant based', 'fitness', 'gym', 'protein', 'workout', 'health'];
const scored = enrichedCandidates.map(creator => ({
...creator,
relevanceScore: scoreNicheRelevance(creator, nicheKeywords),
}));
Step 6: Rank and Output
function generateReport(creators) {
// Sort by relevance score descending
const ranked = creators.sort((a, b) => b.relevanceScore - a.relevanceScore);
console.log('\n=== CREATOR DISCOVERY REPORT ===\n');
console.log(`Total candidates analyzed: ${creators.length}`);
console.log(`Top matches:\n`);
ranked.slice(0, 20).forEach((creator, i) => {
console.log(`${i + 1}. @${creator.username} (${creator.platform})`);
console.log(` Followers: ${creator.followers.toLocaleString()}`);
console.log(` Avg Engagement: ${creator.avgEngagement}%`);
console.log(` Relevance Score: ${creator.relevanceScore}/100`);
console.log(` Top Hashtags: ${creator.topHashtags.slice(0, 5).join(', ')}`);
console.log('');
});
return ranked;
}
Putting It All Together
async function discoverCreators(config) {
console.log('🔍 Searching across platforms...');
const candidates = await multiPlatformSearch(config.searchKeywords, config.platforms);
console.log(`Found ${candidates.length} raw candidates`);
console.log('📋 Filtering by criteria...');
const filtered = filterCandidates(candidates, config.filters);
console.log(`${filtered.length} candidates match criteria`);
console.log('📊 Enriching profiles...');
const enriched = await enrichCandidates(filtered);
console.log('🎯 Scoring relevance...');
const scored = enriched.map(creator => ({
...creator,
relevanceScore: scoreNicheRelevance(creator, config.nicheKeywords),
}));
return generateReport(scored);
}
// Run it
discoverCreators({
searchKeywords: ['vegan fitness', 'plant based athlete', 'vegan protein', 'vegan gym'],
platforms: ['tiktok', 'instagram'],
nicheKeywords: ['vegan', 'plant based', 'fitness', 'gym', 'protein', 'workout'],
filters: {
minFollowers: 10000,
maxFollowers: 100000,
maxDaysSincePost: 14,
minPosts: 50,
},
});
Sample Output
=== CREATOR DISCOVERY REPORT ===
Total candidates analyzed: 63
Top matches:
1. @plantpoweredpaul (tiktok)
Followers: 47,200
Avg Engagement: 6.3%
Relevance Score: 85/100
Top Hashtags: #vegan, #veganfitness, #plantbased, #gymtok, #protein
2. @veganlifts_maria (instagram)
Followers: 31,800
Avg Engagement: 4.1%
Relevance Score: 75/100
Top Hashtags: #veganathlete, #plantbasedprotein, #fitnessmotivation
3. @greengains (tiktok)
Followers: 68,400
Avg Engagement: 5.7%
Relevance Score: 70/100
Top Hashtags: #veganfitness, #gymtok, #plantbasedmuscle
8 hours of manual work → 3 minutes.
Read the Full Guide
This is a condensed version. The full guide covers:
- Adding estimated cost-per-post calculations
- Exporting to CSV/Google Sheets
- Scheduling recurring discovery searches
- Adding authenticity scoring with the SV-Score
Read the complete guide on SociaVault →
Building influencer marketing tools? SociaVault provides social media data APIs for TikTok, Instagram, YouTube, and 10+ platforms. Search users, fetch profiles, get posts and comments — all through one unified API.
Discussion
How do you find influencers for campaigns right now? Manual search? Platforms? Let me know what works (and what doesn't) 👇
Top comments (0)