FetchLayer fetchlayer.dev Sign in

Tutorial

How to Find Influencers on Twitter/X in Your Niche

Discover relevant Twitter/X accounts in any niche using keyword search, follower analysis, and profile filtering. Find influencers, journalists, and potential partners.

Written by Alex P.

  • twitter influencers
  • X influencers
  • twitter outreach
  • influencer discovery
  • twitter search

You want to find the right people to follow, reach out to, or partner with on X/Twitter — but scrolling through search results and manually checking profiles doesn’t scale.

Here’s how to programmatically find relevant accounts in any niche, filter by engagement and follower count, and export a qualified list.


The Approach

Search (People product) → Enrich with profile details → Filter by criteria → Export

We’ll use three FetchLayer endpoints:

  • twitter/search with product: 'People' — find accounts by keyword
  • twitter/user-profile-details — get full profile data for filtering
  • twitter/user-tweets — check recent activity and engagement

Step 1: Search for Accounts

async function findAccounts(keyword, count = 50) {
  const res = await fetch('https://api.fetchlayer.dev/twitter/search', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FETCHLAYER_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ query: keyword, product: 'People', count }),
  });

  const data = await res.json();
  return data.results || [];
}

// Find startup founders
const accounts = await findAccounts('startup founder SaaS');

Step 2: Enrich with Profile Data

Get detailed profile info for each account so you can filter intelligently:

async function getProfile(handle) {
  const res = await fetch('https://api.fetchlayer.dev/twitter/user-profile-details', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FETCHLAYER_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ handle }),
  });

  if (!res.ok) return null;
  return res.json();
}

async function enrichAccounts(accounts) {
  const enriched = [];

  for (const account of accounts) {
    const handle = account.author?.handle || account.handle;
    if (!handle) continue;

    const profile = await getProfile(handle);
    if (!profile) continue;

    enriched.push({
      handle: profile.handle,
      displayName: profile.displayName,
      description: profile.description,
      followersCount: profile.followersCount,
      followingCount: profile.followingCount,
      tweetsCount: profile.tweetsCount,
      isVerified: profile.isVerified,
      joinedAt: profile.joinedAt,
      location: profile.location,
      website: profile.website,
    });
  }

  return enriched;
}

Step 3: Filter by Criteria

Define what “influencer” means for your use case:

function filterInfluencers(profiles, options = {}) {
  const {
    minFollowers = 1000,
    maxFollowers = 500000,
    mustBeVerified = false,
    minTweets = 10,
    maxFollowingRatio = 5, // following <= followers * 5
    excludeKeywords = [], // filter out bios containing these
    requireKeywords = [], // only keep bios containing these
  } = options;

  return profiles.filter(p => {
    if (p.followersCount < minFollowers) return false;
    if (p.followersCount > maxFollowers) return false;
    if (mustBeVerified && !p.isVerified) return false;
    if (p.tweetsCount < minTweets) return false;

    // Avoid spam/follow-back accounts
    if (p.followingCount > p.followersCount * maxFollowingRatio) return false;

    // Keyword filters on bio
    const bio = (p.description || '').toLowerCase();
    if (excludeKeywords.some(kw => bio.includes(kw.toLowerCase()))) return false;
    if (requireKeywords.length > 0 && !requireKeywords.some(kw => bio.includes(kw.toLowerCase()))) return false;

    return true;
  });
}

Step 4: Full Script

// find-influencers.mjs
const KEYWORD = process.argv[2] || 'SaaS founder';
const MIN_FOLLOWERS = parseInt(process.argv[3]) || 1000;

async function run() {
  console.log(`Searching for "${KEYWORD}" on X/Twitter...`);

  // Step 1: Find accounts
  const accounts = await findAccounts(KEYWORD, 50);
  console.log(`Found ${accounts.length} accounts`);

  // Step 2: Enrich with profiles
  const profiles = await enrichAccounts(accounts);
  console.log(`Enriched ${profiles.length} profiles`);

  // Step 3: Filter
  const influencers = filterInfluencers(profiles, {
    minFollowers: MIN_FOLLOWERS,
    excludeKeywords: ['crypto', 'NFT', 'onlyfans'],
  });

  // Sort by follower count
  influencers.sort((a, b) => b.followersCount - a.followersCount);

  // Step 4: Export
  console.log(`\nFound ${influencers.length} qualified accounts:\n`);
  for (const inf of influencers.slice(0, 20)) {
    console.log(`@${inf.handle} — ${inf.followersCount.toLocaleString()} followers${inf.isVerified ? ' ✓' : ''}`);
    console.log(`  ${inf.description?.slice(0, 120) || '(no bio)'}`);
    console.log(`  ${inf.location || 'No location'} · ${inf.website || 'No website'}`);
    console.log();
  }

  // Export to CSV
  const csv = ['handle,displayName,followersCount,isVerified,location,website,description']
    .concat(influencers.map(i =>
      `"${i.handle}","${i.displayName}","${i.followersCount}","${i.isVerified}","${i.location || ''}","${i.website || ''}","${(i.description || '').replace(/"/g, '""')}"`
    ))
    .join('\n');

  const fs = await import('fs');
  fs.writeFileSync(`${KEYWORD.replace(/\s+/g, '-').toLowerCase()}-influencers.csv`, csv);
  console.log(`Exported ${influencers.length} accounts to CSV`);
}

run().catch(console.error);
FETCHLAYER_API_KEY=sk-your-key node find-influencers.mjs "indie hacker" 500

Advanced: Score by Engagement

Get recent tweets to calculate engagement rate and rank by influence:

async function getEngagementRate(handle) {
  const res = await fetch('https://api.fetchlayer.dev/twitter/user-tweets', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FETCHLAYER_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ handle, count: 20 }),
  });

  const data = await res.json();
  const tweets = data.tweets || [];
  if (tweets.length === 0) return 0;

  const avgLikes = tweets.reduce((sum, t) => sum + (t.likeCount || 0), 0) / tweets.length;
  return avgLikes;
}

// Enrich with engagement and re-rank
for (const inf of influencers) {
  inf.avgLikes = await getEngagementRate(inf.handle);
}

influencers.sort((a, b) => b.avgLikes - a.avgLikes);

What’s Next