FetchLayer fetchlayer.dev Sign in

Tutorial

How to Export Twitter/X Followers to CSV

Export any public Twitter/X account's followers (including verified followers) to CSV. Step-by-step code for Node.js with the FetchLayer API.

Written by Alex P.

  • twitter followers
  • X followers
  • CSV export
  • twitter data
  • follower analysis

You need a list of followers for an account — for outreach, audience analysis, or research. X’s official API doesn’t make this easy (follower endpoints are Pro/Enterprise tier, $5K+/month).

Here’s how to export any public account’s followers to CSV with one API call.


Setup

const API_KEY = process.env.FETCHLAYER_API_KEY;

async function twitter(endpoint, body) {
  const res = await fetch(`https://api.fetchlayer.dev/twitter/${endpoint}`, {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(body),
  });
  if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
  return res.json();
}

Export All Followers

The followers endpoint returns accounts with handle, display name, follower count, and verification status:

import { writeFileSync } from 'fs';

async function exportFollowers(handle, maxPages = 5) {
  const rows = [];
  let cursor = null;
  let page = 0;

  do {
    const data = await twitter('followers', {
      handle,
      count: 100,
      ...(cursor && { cursor }),
    });

    for (const account of data.accounts || []) {
      rows.push({
        handle: account.handle,
        displayName: account.displayName,
        followersCount: account.followersCount,
        isVerified: account.isVerified,
        description: account.description || '',
      });
    }

    cursor = data.cursor;
    page++;
    console.log(`Page ${page}: ${rows.length} followers so far`);
  } while (cursor && page < maxPages);

  return rows;
}

Convert to CSV

function toCSV(rows) {
  const headers = ['handle', 'displayName', 'followersCount', 'isVerified', 'description'];
  const csvRows = [headers.join(',')];

  for (const row of rows) {
    csvRows.push(headers.map(h => {
      const val = String(row[h] || '');
      // Escape commas and quotes
      return val.includes(',') || val.includes('"') ? `"${val.replace(/"/g, '""')}"` : val;
    }).join(','));
  }

  return csvRows.join('\n');
}

Full Export Script

// export-followers.mjs
const handle = process.argv[2] || 'openai';

console.log(`Exporting followers for @${handle}...`);

const rows = await exportFollowers(handle, 10); // Up to 1000 followers
const csv = toCSV(rows);

const filename = `${handle}-followers.csv`;
writeFileSync(filename, csv);

console.log(`Done! ${rows.length} followers exported to ${filename}`);

// Summary
const verified = rows.filter(r => r.isVerified).length;
const avgFollowers = Math.round(rows.reduce((s, r) => s + r.followersCount, 0) / rows.length);
console.log(`Verified: ${verified} (${((verified / rows.length) * 100).toFixed(1)}%)`);
console.log(`Avg followers per account: ${avgFollowers.toLocaleString()}`);
FETCHLAYER_API_KEY=sk-your-key node export-followers.mjs openai

Export Verified Followers Only

Target high-value accounts — verified followers are typically journalists, founders, investors, and influencers:

async function exportVerifiedFollowers(handle, maxPages = 5) {
  const rows = [];
  let cursor = null;
  let page = 0;

  do {
    const data = await twitter('verified-followers', {
      handle,
      count: 100,
      ...(cursor && { cursor }),
    });

    for (const account of data.accounts || []) {
      rows.push({
        handle: account.handle,
        displayName: account.displayName,
        followersCount: account.followersCount,
        description: account.description || '',
      });
    }

    cursor = data.cursor;
    page++;
  } while (cursor && page < maxPages);

  return rows;
}

const verifiedRows = await exportVerifiedFollowers('openai', 5);
writeFileSync('openai-verified-followers.csv', toCSV(verifiedRows));
console.log(`${verifiedRows.length} verified followers exported`);

Analyze the Follower List

// Quick audience analysis
function analyze(rows) {
  const byFollowerCount = [...rows].sort((a, b) => b.followersCount - a.followersCount);
  const top10 = byFollowerCount.slice(0, 10);
  const verifiedCount = rows.filter(r => r.isVerified).length;

  console.log('\nAudience Analysis:');
  console.log(`Total followers: ${rows.length}`);
  console.log(`Verified: ${verifiedCount} (${((verifiedCount / rows.length) * 100).toFixed(1)}%)`);
  console.log(`Avg followers: ${Math.round(rows.reduce((s, r) => s + r.followersCount, 0) / rows.length).toLocaleString()}`);
  console.log(`\nTop 10 by follower count:`);
  top10.forEach((r, i) => {
    console.log(`  ${i + 1}. @${r.handle} — ${r.followersCount.toLocaleString()} followers${r.isVerified ? ' ✓' : ''}`);
  });
}

Alternative: Following List

Export who an account follows instead of who follows them:

const followingRows = [];
let cursor = null;

do {
  const data = await twitter('following', { handle: 'openai', count: 100, ...(cursor && { cursor }) });
  for (const account of data.accounts || []) {
    followingRows.push({
      handle: account.handle,
      displayName: account.displayName,
      followersCount: account.followersCount,
      isVerified: account.isVerified,
      description: account.description || '',
    });
  }
  cursor = data.cursor;
} while (cursor);

writeFileSync('openai-following.csv', toCSV(followingRows));
console.log(`${followingRows.length} accounts exported`);

What’s Next