Get a Twitter (X) Account's Followers with Cursor Pagination
This technical document shows developers how to fetch a user's followers using the TwitterAPI.io followers endpoint. The first page always returns the newest followers. Use the cursor to paginate until you have fetched the entire followers list for accurate analytics and user growth tracking.
API Overview
Endpoint: https://api.twitterapi.io/twitter/user/followers
Required query params: userName. Optional: pageSize, cursor.
- Ordering: page 1 returns the latest followers first.
- Pagination: when
has_next_page
is true, continue withnext_cursor
to fetch the next page.
https://api.twitterapi.io/twitter/user/followings
.Cursor-based pagination
Each response includes pagination state: has_next_page
and, if more data exists, a next_cursor
. Use this cursor value in the next request. Iterate until has_next_page
is false or next_cursor
is empty. Cursor pagination is efficient and ideal for exporting large follower lists.
Example response fields: followers
array, has_next_page
boolean, next_cursor
string, plus metadata like name
, userName
, verified
, followers_count
, and created_at
.
Implementation examples
Copy a production-ready snippet for Node.js, Python, or Java. Replace YOUR_API_KEY
and adjust pageSize
as needed.
Node.js
const axios = require('axios');
const fs = require('fs');
/**
* Fetches all followers for a given Twitter username using TwitterAPI.io
*
* @param {string} username - Twitter username (without @)
* @param {string} apiKey - TwitterAPI.io API key
* @param {number} pageSize - Number of followers per page (max 200)
* @returns {Promise<Array>} List of all follower objects
*
* Notes:
* - Handles pagination automatically using cursor
* - Implements retry logic for failed requests
* - Includes rate limiting protection
* - Deduplicates followers based on user ID
*/
async function fetchAllFollowers(username, apiKey, pageSize = 200) {
const baseUrl = "https://api.twitterapi.io/twitter/user/followers";
const headers = { "x-api-key": apiKey };
const allFollowers = [];
const seenUserIds = new Set(); // Set to track unique user IDs and avoid duplicates
let cursor = null;
const maxRetries = 3;
console.log(\`Starting to fetch followers for @\${username}...\`);
while (true) {
// Prepare query parameters
const params = {
userName: username,
pageSize: pageSize
};
// Add cursor if available for pagination
if (cursor) {
params.cursor = cursor;
}
let retryCount = 0;
while (retryCount < maxRetries) {
try {
console.log(\`Fetching page with cursor: \${cursor ? cursor : 'first page'}\`);
// Make API request
const response = await axios.get(baseUrl, {
headers,
params,
timeout: 30000
});
const data = response.data;
// Check if API returned success
if (data.code !== 0 || data.status !== "success") {
throw new Error(\`API Error: \${data.msg || 'Unknown error'}\`);
}
// Extract followers and metadata
const followers = data.followers || [];
const hasNextPage = data.has_next_page || false;
cursor = data.next_cursor || null;
// Filter out duplicate followers based on user ID
const newFollowers = [];
for (const follower of followers) {
const userId = follower.id;
if (userId && !seenUserIds.has(userId)) {
seenUserIds.add(userId);
allFollowers.push(follower);
newFollowers.push(follower);
}
}
console.log(\`Fetched \${newFollowers.length} new followers (total: \${allFollowers.length})\`);
// If no more pages, we're done
if (!hasNextPage || !cursor) {
console.log("Reached end of followers list");
return allFollowers;
}
// Add small delay to be respectful to the API
await new Promise(resolve => setTimeout(resolve, 500));
break; // Exit retry loop on success
} catch (error) {
retryCount++;
if (retryCount === maxRetries) {
console.log(\`Failed to fetch followers after \${maxRetries} attempts: \${error.message}\`);
return allFollowers;
}
// Handle rate limiting (429 status code)
if (error.response && error.response.status === 429) {
console.log("Rate limit reached. Waiting for 1 second...");
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second
} else {
const waitTime = Math.pow(2, retryCount) * 1000; // Exponential backoff in milliseconds
console.log(\`Error occurred: \${error.message}. Retrying in \${waitTime/1000} seconds... (\${retryCount}/\${maxRetries})\`);
await new Promise(resolve => setTimeout(resolve, waitTime));
}
}
}
}
return allFollowers;
}
/**
* Save followers data to a file
*
* @param {Array} followers - List of follower objects
* @param {string} username - Twitter username for filename
* @param {string} format - Output format ("json" or "csv")
*/
function saveFollowersToFile(followers, username, format = "json") {
if (format === "json") {
const filename = \`\${username}_followers.json\`;
fs.writeFileSync(filename, JSON.stringify(followers, null, 2), 'utf8');
console.log(\`Followers saved to \${filename}\`);
}
else if (format === "csv") {
const filename = \`\${username}_followers.csv\`;
if (followers.length > 0) {
const fieldnames = Object.keys(followers[0]);
// Create CSV header
let csvContent = fieldnames.join(',') + '\\n';
// Add data rows
for (const follower of followers) {
const row = fieldnames.map(field => {
const value = follower[field];
// Handle null/undefined values and escape commas in strings
if (value === null || value === undefined) {
return '';
}
if (typeof value === 'string' && value.includes(',')) {
return \`"\${value.replace(/"/g, '""')}"\`;
}
return value;
}).join(',');
csvContent += row + '\\n';
}
fs.writeFileSync(filename, csvContent, 'utf8');
console.log(\`Followers saved to \${filename}\`);
}
}
}
// Example usage
async function main() {
// Configuration
const apiKey = "your_api_key"; // Replace with your actual API key
const username = "elonmusk"; // Username to fetch followers for (without @)
try {
// Fetch all followers
console.log(\`Fetching all followers for @\${username}...\`);
const followers = await fetchAllFollowers(username, apiKey);
if (followers.length > 0) {
console.log(\`\\nSuccessfully fetched \${followers.length.toLocaleString()} followers!\`);
// Save to files
saveFollowersToFile(followers, username, "json");
} else {
console.log("No followers were fetched.");
}
} catch (error) {
console.log(\`Error in main execution: \${error.message}\`);
}
}
// Run the example if this file is executed directly
if (require.main === module) {
main();
}
module.exports = { fetchAllFollowers, saveFollowersToFile };
Getting Started
1. Get API Key
2. Copy Code
3. Start Fetching
next_cursor
until all followers are retrieved.Ready to export followers at scale?
Start with the Followers API today. Reliable data, simple pagination, and flexible usage for analytics, CRM enrichment, or growth workflows.