Updated July 2026: added the 100 free requests starting option, reframed Sorsa pricing around the per-1,000-profiles rate, and refreshed the official X API costs to the current per-resource rate card.
Key takeaway: The Twitter/X followers API retrieves the accounts that follow a user and the accounts that user follows. The official X API exposes GET /2/users/:id/followers and GET /2/users/:id/following, returning paginated user objects with full profile metadata. Each endpoint bills per user object returned, so a follower list's cost scales with account size.
If you have ever tried to pull a follower list off X (formerly Twitter) at any meaningful scale, you have hit one of two walls. Either the web UI quietly stops loading after a few hundred profiles, or you sign up for the official X API and find that "fetch 100,000 followers" can mean a four-figure invoice. Neither is workable for the jobs people actually need follower data for: competitive intelligence, lead generation, influencer discovery, academic research, campaign verification.
This is the developer-oriented walkthrough: the endpoints, the authentication model, the production patterns. If you have not picked a tool yet and want to weigh API access against browser extensions, DIY scrapers, and X's native data export, our methods comparison for extracting Twitter followers covers those tradeoffs first. The rest of this guide assumes you have settled on the API route.
Sorsa API, an alternative Twitter/X API provider, handles the same data as the official endpoints with a different cost structure. Its /followers and /follows endpoints return up to 200 full user profiles per request behind a single ApiKey header, run at a flat 20 requests per second with no app review, and bill per request rather than per user object. That last difference is the whole story for follower data at scale, and the sections below work through why, with the official endpoints, the pricing math, and copy-paste Python and JavaScript.
What the Twitter Followers API Returns
The Twitter/X followers API returns a paginated list of user objects, one per follower, with each object carrying that follower's full profile rather than just a handle. A single follower request is, in practice, a bulk profile lookup with a relationship filter applied. For each follower you typically get the same fields you would get from a direct profile lookup.
- Stable numeric user ID and current handle
- Display name, bio, profile image URL, banner URL
- Follower count, following count, tweet count
- Account creation date
- Location string (freeform, not validated)
- Verified status (Blue, Gold, Gray)
- Protected/private flag
- URLs found in the bio
- Pinned tweet IDs
That richness matters more than it looks. With one follower-list request you are not just collecting handles; you are getting the data needed to qualify, segment, or filter the audience without a second round of profile lookups.
The official X API splits this across two endpoints:
| Endpoint | Returns |
|---|---|
GET /2/users/:id/followers | Users who follow the specified user |
GET /2/users/:id/following | Users that the specified user follows |
Sorsa exposes the same pair as GET /v3/followers and GET /v3/follows, plus a third utility endpoint, GET /v3/verified-followers, that returns only verified accounts (more on why that exists below).
How Much Does the Official X API Cost for Followers in 2026?
Under the X API pay-per-use model, follower and following reads are billed per user object returned, at $0.010 per resource for any account that is not your own. A follower list of 100,000 accounts is 100,000 billable resources, roughly $1,000, no matter how few requests you used to paginate through it. This is the detail most older guides miss, because they were written before the 2026 pricing changes.
The model arrived in two steps. X moved to pay-per-use as the default for new developers in February 2026: no free tier, no fixed Basic or Pro subscription, just credits bought in the Developer Console and charged per call. Then on April 20, 2026, X cut "Owned Reads" (requests for your own account's data) to $0.001 per resource, while reads of any other account stayed at the standard rate. Per X's developer community, you are charged per resource: a user account with 1,000 followers at $0.010 each comes to $10, billed per user object returned, not per request.
This is the catch with "Owned Reads." Fetching your own developer account's follower list is now cheap. Fetching the followers of a competitor, an influencer, or a lead source is the standard non-owned read, billed per user object. The 2-million-per-month cap X applies to post reads does not govern follower reads, which are billed purely per resource.
| Account size | Official X API (non-owned reads, $0.010/resource) | Sorsa API (Pro) |
|---|---|---|
| 1,000 followers | $10.00 | ~$0.01 |
| 10,000 followers | $100.00 | ~$0.10 |
| 100,000 followers | $1,000.00 | ~$1.00 |
| 1,000,000 followers | $10,000.00 | ~$10.00 |
Disclosure: Sorsa API is our product. The official-API figures use X's published pricing, where non-owned reads are charged per resource returned and owned reads are $0.001 per resource, at the $0.010 per-resource user-read rate current as of June 2026; your exact cost can vary with overage handling and any negotiated contract. We recommend testing any provider against your real workload before committing.
Per-Resource vs Per-Request Billing
The difference between per-resource and per-request billing is what decides the cost of follower data, not the headline rate. The official X API counts every user object in a response as a separate billable resource, so one request that returns 1,000 followers costs the same as 1,000 individual lookups. A flat-rate API like Sorsa counts the whole request as one unit against a monthly quota, no matter how many users come back in it.
For follower extraction this gap compounds fast, because follower endpoints return many objects per call. On the official API, a 100,000-follower list is 100,000 resources at $0.010 each. On Sorsa, the same list is roughly 500 requests (200 profiles per request) against a monthly quota, around $1.00 on the Pro plan. The data shape is the same; the unit you pay for is not.
This is the structural reason a third-party Twitter API market exists for follower data at all. The official API is well-priced when you only read your own account. For everything else, per-resource billing works against you, and a per-request model is the lever that brings the cost down. For the full cross-provider breakdown, see our Twitter API pricing guide.
The Sorsa Follower and Following Endpoints
The Sorsa follower endpoints are three GET requests authenticated with a single ApiKey header, with no OAuth flow, no app review, and no bearer-token rotation. The full followers and following documentation covers the response schema and pagination behavior in depth. The short version:
GET /v3/followersreturns accounts that follow the specified user.GET /v3/followsreturns accounts that the specified user is following.GET /v3/verified-followersreturns the same shape as/followers, but only Blue, Gold, and Gray verified accounts.
You pass one of three user identifiers as a query parameter, plus an optional pagination cursor:
| Parameter | Description |
|---|---|
username | Handle without @, for example stripe |
user_id | Numeric user ID, for example 44196397 |
user_link | Full profile URL, for example https://x.com/stripe |
next_cursor | Optional pagination cursor returned by a prior response |
Each page returns up to 200 user objects, among the highest per-request yields available. The official X API caps each call at 1,000 user objects but charges for every one of them; Sorsa returns 200 per request and counts the whole batch as a single request against your quota.
Fetching One Page of Followers
The smallest working call against the /followers endpoint is one HTTP GET with a username and your API key. One request, one response, no authentication dance.
cURL
curl "https://api.sorsa.io/v3/followers?username=stripe" \
-H "ApiKey: YOUR_API_KEY"
Python
import requests
resp = requests.get(
"https://api.sorsa.io/v3/followers",
headers={"ApiKey": "YOUR_API_KEY"},
params={"username": "stripe"},
)
for user in resp.json().get("users", []):
print(f"@{user['username']} - {user.get('description', '')[:80]}")
JavaScript (Node.js or browser)
const resp = await fetch(
"https://api.sorsa.io/v3/followers?username=stripe",
{ headers: { "ApiKey": "YOUR_API_KEY" } }
);
const { users } = await resp.json();
users.forEach((u) =>
console.log(`@${u.username} - ${u.description?.slice(0, 80) ?? ""}`)
);
To fetch the accounts a user is following instead, swap /followers for /follows. The parameter shape and response structure are identical. If you want to see the response before writing any code, the Recent Followers tool renders the last 20 followers of any public account in your browser, and the API Playground lets you call any endpoint without writing a line.
Paginating Through a Complete Follower List
To retrieve a follower list beyond the first page, you walk pages using the next_cursor value returned in each response, passing it back on the next request until it comes back null or absent. One request returns up to 200 users on Sorsa, so a complete list is a loop over those pages.
Here is a complete, production-shaped loop in Python. It handles pagination, rate limiting, and a hard page cap so a runaway extraction does not silently drain your quota:
import requests
import time
API_KEY = "YOUR_API_KEY"
def get_all_followers(username, max_pages=100):
"""Fetch the complete follower list of a public account."""
all_users = []
cursor = None
for page in range(max_pages):
params = {"username": username}
if cursor:
params["next_cursor"] = cursor
resp = requests.get(
"https://api.sorsa.io/v3/followers",
headers={"ApiKey": API_KEY},
params=params,
timeout=30,
)
resp.raise_for_status()
data = resp.json()
users = data.get("users", [])
all_users.extend(users)
print(f"Page {page + 1}: {len(users)} followers (total: {len(all_users)})")
cursor = data.get("next_cursor")
if not cursor:
print("Reached end of list.")
break
# Sorsa's rate limit is 20 req/s. 50ms between calls is safe.
time.sleep(0.05)
return all_users
followers = get_all_followers("stripe", max_pages=100)
print(f"\nTotal followers collected: {len(followers)}")
At the 20 requests per second rate limit, this works out to roughly 4,000 followers per second of wall-clock time. A 100,000-follower account takes about 25 seconds. A one-million-follower account takes about four minutes. The same cursor pattern applies to every other paginated endpoint on the API.
For a following list, swap /followers for /follows; everything else stays identical. A unified helper that handles both:
def get_user_graph(username, endpoint, max_pages=100):
"""endpoint should be 'followers' or 'follows'."""
all_users = []
cursor = None
for _ in range(max_pages):
params = {"username": username}
if cursor:
params["next_cursor"] = cursor
data = requests.get(
f"https://api.sorsa.io/v3/{endpoint}",
headers={"ApiKey": API_KEY},
params=params,
timeout=30,
).json()
all_users.extend(data.get("users", []))
cursor = data.get("next_cursor")
if not cursor:
break
time.sleep(0.05)
return all_users
Production Patterns That Matter at Scale
A tidy loop works in a notebook. Running follower extraction inside a real pipeline (cron jobs, multi-account sweeps, downstream enrichment) surfaces a different set of problems. These are the patterns we reach for once the basic loop works.
Handle the 429 response cleanly
Sorsa returns 429 Too Many Requests when you exceed the 20 req/s limit. The fix is short: wait a second, retry. There is no penalty for hitting the limit and no token bucket to walk down. A drop-in wrapper:
import time
import requests
def get_with_retry(url, params, headers, max_retries=5):
for attempt in range(max_retries):
resp = requests.get(url, params=params, headers=headers, timeout=30)
if resp.status_code == 429:
# Rate limited. Back off and retry.
time.sleep(1.0 + attempt * 0.5)
continue
if resp.status_code >= 500:
# Transient server error. Exponential backoff.
time.sleep(2 ** attempt)
continue
resp.raise_for_status()
return resp.json()
raise RuntimeError(f"Failed after {max_retries} retries")
If your loop already sleeps 50ms between calls, you will rarely see a 429. They show up mostly when you parallelize across accounts. The rate limits docs describe exactly what counts against the quota.
Use user_id instead of username for long-running jobs
Usernames change; the numeric user_id does not. If you schedule a job to re-extract followers of the same accounts every week, resolve each username to a user_id once and store it. Otherwise a target renaming itself silently breaks the pipeline, and your logs say "user not found" with no obvious cause.
def resolve_user_id(username):
resp = requests.get(
f"https://api.sorsa.io/v3/username-to-id/{username}",
headers={"ApiKey": API_KEY},
timeout=30,
)
resp.raise_for_status()
return resp.json()["id"]
The ID conversion endpoints cover the full set: username to ID, ID to current username, and profile URL to ID. Store the IDs; resolve back to usernames only when you need them for display.
Parallelize across accounts, not within one
The pagination cursor is sequential by design: you cannot fetch page 7 without first fetching pages 1 through 6, since each response hands you the cursor for the next. There is no speedup inside a single account's extraction.
Across accounts is different. To pull followers from 20 competitors, run those 20 extractions concurrently against the 20 req/s limit. With async Python:
import asyncio
import aiohttp
async def fetch_page(session, url, params):
async with session.get(url, params=params, headers={"ApiKey": API_KEY}) as r:
return await r.json()
async def extract_one(session, username):
users = []
cursor = None
while True:
params = {"username": username}
if cursor:
params["next_cursor"] = cursor
data = await fetch_page(session, "https://api.sorsa.io/v3/followers", params)
users.extend(data.get("users", []))
cursor = data.get("next_cursor")
if not cursor:
return username, users
await asyncio.sleep(0.05)
async def extract_many(usernames):
async with aiohttp.ClientSession() as session:
tasks = [extract_one(session, u) for u in usernames]
return dict(await asyncio.gather(*tasks))
results = asyncio.run(extract_many(["stripe", "vercel", "supabase", "render"]))
Cap concurrency at your rate limit divided by per-request latency. At 20 req/s and roughly 150ms per request, three to four concurrent extractions saturates the ceiling.
Working with the response data
Each user object carries the full profile, so most downstream processing needs no extra API calls. A few things worth knowing about the shape:
- The
idfield is a string, not an integer, even though it looks numeric. Twitter user IDs exceed the 64-bit signed integer range some languages handle natively, so the API serializes them as strings. Do not cast to int unless your tooling handles 64-bit values safely. - The
created_atfield is ISO 8601 (for example2009-06-02T20:12:29Z), so it parses directly:datetime.fromisoformat(created_at.replace("Z", "+00:00")). No custom format string is needed. - The
description(bio) can contain newlines, emoji, and unicode of every kind. Sanitize it before writing to CSV or any pipeline that does not handle UTF-8 cleanly. - The
locationfield is a freeform user-entered string, not a validated geo field. For reliable country data, the audience geography workflow uses the/aboutendpoint to pull the country tag X attaches to each account, and the analyze followers by country guide walks through the full breakdown.
For deeper analysis of the audience, our methods comparison for extracting Twitter followers walks through filtering by bio keyword for lead qualification and finding accounts that follow multiple competitors. To turn a raw list into a CRM-ready sheet, see exporting X data to Google Sheets; to score the same list for fake or inactive accounts, the fake-follower audit guide covers it. This article stays on the API mechanics.
Why /verified-followers Exists as a Separate Endpoint
Filtering followers by verification on the client side is trivial (u.get("verified") is True), so a dedicated /verified-followers endpoint earns its place for two practical reasons. First, on accounts with millions of followers where verified users are a small minority, walking the whole list to pull them out wastes requests and clock time; the endpoint returns only the verified subset, ordered the same way as /followers. Second, the "high-profile audience" filter is common enough in PR, journalism, investor research, and influencer marketing to be worth one call.
curl "https://api.sorsa.io/v3/verified-followers?username=stripe" \
-H "ApiKey: YOUR_API_KEY"
The response and pagination behavior are identical to /followers. See the verified followers API reference for the full schema.
Edge Cases That Will Trip You Up
Even on a clean API, follower data has a few quirks worth knowing before you ship a pipeline. The four below account for most of the surprises teams hit in production.
Protected accounts return an error. If the target has set its tweets to private (the protected flag is true), its follower and following lists are not accessible to anyone outside its approved followers, and the endpoint returns an error rather than a partial result. Check the profile's protected flag with the /info endpoint before extraction if you are scripting across many accounts.
The follower count and the extractable list will not match exactly. A profile's followers_count is a real-time counter X maintains. The list you walk through the API can come back slightly smaller because of suspended accounts, deactivated users, and accounts that recently unfollowed but have not yet flushed from the counter. Expect a few percent of drift on large accounts, and do not write strict equality checks against followers_count.
Profile data is current, not historical. Each user object reflects the profile as it exists now, not its state when the follow happened. If someone followed Stripe in 2019 and has since renamed themselves, the username in your extraction is the new handle. The numeric id is stable; the handle is not.
Ordering is roughly reverse-chronological. Both /followers and /follows return results in the order X provides them, generally newest follows first, so the first pages hold the most recently acquired followers. X has not officially committed to this ordering, so do not build logic that depends on it staying fixed forever, though it has held consistently in practice.
When the Official X API Still Makes Sense
The official X API is the right choice in two specific cases: reading your own account's data, and any workflow that has to write. Reading your own followers became cheap on April 20, 2026 at the $0.001 owned-read rate, so for personal dashboards and account-management tools the official GET /2/users/:id/followers with OAuth user-context auth is a reasonable fit. Write actions (posting, liking, following) are official-API-only and not something read-focused providers handle.
For any third-party account, which is the realistic case for almost every commercial application, the math changes. The per-resource cost rises roughly tenfold compared to owned reads, OAuth 2.0 adds friction to the auth flow, and rate limits are enforced in 15-minute windows that return a 429 when exceeded and that paying more does not lift. For teams moving off the official API after the pricing changes, Sorsa's migration documentation covers the endpoint-by-endpoint mapping.
The decision tree is short:
- Reading your own account's data only? The official X API is fine. Cheap, and the data is canonical.
- Reading any other account's data? An alternative Twitter/X API is the better fit. The cost gap is large enough that it does not need a closer look.
- Need to post, like, or follow? Official X API only. Write actions are out of scope for a read-only provider like Sorsa.
In Practice
We rebuilt a follower-extraction job for a quant fund tracking sentiment across fintech X accounts. They needed the follower lists of about 50 mid-tier competitor accounts, averaging 80,000 followers each, roughly four million user objects in total. On the official API's non-owned read rate, that one-time pull priced out near $40,000. The same job on a flat-rate third-party API came to about $40 of quota and ran in an afternoon, with an identical data shape. The driver is structural rather than a discount: the official API bills every user object it returns, while a per-request API bills the call and returns 200 profiles inside it. For audiences in the millions, sampling the first 10,000 to 20,000 followers (50 to 100 requests) is usually representative of the recent audience and avoids paying to walk the full tail.
FAQ
What is the Twitter followers API?
The Twitter followers API is the set of endpoints that programmatically retrieve the accounts following a Twitter/X user, and on the same endpoint family, the accounts that user follows. The official version is GET /2/users/:id/followers and GET /2/users/:id/following. Third-party providers like Sorsa expose the same data through a single API key and per-request billing instead of OAuth and per-resource billing.
How do you get a Twitter following list via API?
To get a following list (the accounts a user follows, not the accounts that follow them), call the "following" endpoint rather than the followers one. On the official API that is GET /2/users/:id/following; on Sorsa it is GET /v3/follows, with the same parameters and 200-per-page pagination as the followers endpoint. Following lists are usually smaller than follower lists and often more revealing, since they show whom an account chooses to track.
How much does the official X API cost for follower data in 2026?
After the April 20, 2026 update, X charges $0.001 per resource for "Owned Reads" (your own data) and the standard non-owned read rate, $0.010 per resource, for any other account's data. The bill is calculated per user object returned, not per request. A follower list of 100,000 accounts on a non-owned read is about $1,000.
What is the difference between per-resource and per-request billing?
Per-resource billing counts every user object in a response as a separate charge, so one official-API request returning 1,000 followers costs the same as 1,000 individual lookups. Per-request billing, which Sorsa uses, counts the whole request as one unit against your monthly quota regardless of how many users come back. For follower lists, where each call returns up to 200 users, that is the difference between paying for 200 things or for one.
Should you use user_id or username in API calls?
Use username for ad-hoc queries and exploration. Use user_id for any code that runs more than once. Usernames change when accounts rename themselves; the numeric ID is stable for the life of the account. For scheduled jobs, resolve the username to a user_id once with the username-to-id endpoint, store it, and pass user_id from then on.
How do you handle the 429 rate limit response?
Sleep one second and retry. Sorsa's 20 req/s limit has no penalty for hitting it: you get a 429, wait, and the next request works. There are no token buckets, no 15-minute windows, and no per-endpoint sub-limits. A light retry wrapper that catches 429 and 5xx responses with short backoff is enough for production.
Why doesn't the extracted count match the profile's followers_count?
The followers_count value is a real-time counter X maintains, so the extractable list can come back slightly smaller. Suspended accounts, deactivated users, and people who recently unfollowed but have not flushed from the counter all create drift. Expect a few percent of difference on large accounts. This is platform behavior, not a bug in your code, so avoid strict equality checks.
How fresh is the follower data?
User objects reflect the profile as it exists at the moment of the request, so counts, bios, profile images, and verification status are current. Follow relationships are typically reflected within seconds to minutes of happening on X. For something closer to streaming, the real-time monitoring patterns cover how to detect new followers and mentions on a tight interval.
Getting Started
To try this against your own account or any public account:
- Sign up for an API key on the overview dashboard. Every new key includes 100 free requests: one-time, no card required, never expiring, and valid on all 40 endpoints. On follower endpoints that is up to 20,000 profiles before you pay anything.
- Run the cURL or Python example above with your handle as the
usernameparameter. - For a no-code preview, open the API Playground and call
/followersdirectly in the browser. - Follower data on Sorsa runs from $0.01 per 1,000 profiles, since one request returns up to 200 full profiles at a flat per-request rate. Plan for volume on the pricing page: from $0.02 per 1,000 profiles on Starter and from $0.01 per 1,000 profiles on Pro and Enterprise, with every plan running at the flat 20 requests per second.
The full code, endpoint reference, and pagination patterns live in the followers and following documentation. For non-API extraction (browser extensions, DIY scrapers, manual X data exports), see the methods comparison linked at the top of this guide. For how the third-party Twitter data API market compares to the official X API overall in 2026, see our Twitter API alternatives breakdown.
Reviewed by Keksich, founder of Sorsa, marketer and X API researcher.
How this guide was put together: the endpoints, code, and patterns come from our own work building and operating Sorsa's Twitter/X API and running follower extraction against live public accounts. The official-API costs and model were verified against X's published developer pricing and the rate-limit behavior documented in X's developer resources. Last verified July 2026.