Skip to content

FOLLOWERS

Twitter Followers API: Pull Any Account's List for $0.016/1K

Updated July 2026

How do you pull a Twitter (X) account's followers with an API?

This Twitter Followers API is a single REST call that hands back any public account's followers, following, and verified followers as paginated JSON, billed at $0.0008 per call (roughly $0.012 to $0.016 per 1,000 records). TwitterAPIs ships four follower endpoints behind one Bearer key, each cursor-paged, with no developer account to apply for and one flat ceiling of 600 requests a minute per key.

We bill each follower call at $0.0008 (source: our published pricing), which works out to roughly $0.012 to $0.016 per 1,000 records returned, depending on where in the crawl a page falls.

Each relationship, mapped to its own endpoint

A follower graph is not a single call. TwitterAPIs splits every relationship you might want into its own endpoint, all sharing one Bearer key and the same flat $0.0008 per call: the full follower list, the accounts a user follows, verified-only followers, mutual connections, or a one-off follow check.

What you pullEndpointPer pageDocs
Full follower listGET /twitter/user/followers~70 per pageView docs
Followers v2 (more fields)GET /twitter/user/followers_v2~70 per pageView docs
Just verified followersGET /twitter/user/verified_followers~70 per pageView docs
Accounts a user followsGET /twitter/user/following~70 per pageView docs
Shared follows (mutuals)POST /twitter/user/followers_you_knowPagedView docs
One-shot follow checkGET /twitter/user/check_follow_relationshipSingle resultView docs

Each endpoint carries the identical flat $0.0008 per call, so your bill tracks the volume you pull rather than which relationship you happen to query.

Pull a complete follower list page by page

You will find the followers endpoint at GET /twitter/user/followers. Hand it the userName you care about and pull the followers array off the response. For the entire list, skip cursor on the opening call, then echo the returned next_cursor on each following call and keep going while has_more stays true. Each call costs $0.0008 and ships about 70 followers on the first page, fewer on the pages after it. The count parameter is currently ignored, so page size is fixed regardless of what you request.

Fetch the opening page of followers

curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://api.twitterapis.com/twitter/user/followers?userName=elonmusk"

Every page returns structured JSON carrying next_cursor and has_more, which means no markup to scrape and no proxy pool to babysit. Read the followers endpoint docs.

Choosing between followers and followers_v2

VersionPage sizeFieldsBest for
followers (v1)~70 per pageStandard profile fields on each followerExisting integrations already built on the v1 response shape
followers_v2~70 per pageFuller profile object on every followerNew work. Same page size as v1, with more detail per record

Either version cursors through the identical full list. v1 packs more records into each call, so it covers a big list in fewer round trips; v2 gives up page size for a deeper payload on every follower. That same v1-versus-v2 tradeoff carries over to the following endpoint.

How TwitterAPIs stacks up against the X API and scraping

OptionPriceAuthLimitsFull export
TwitterAPIs~$0.012-0.016 / 1,000 followersOne Bearer token, 30-second signup600 req/min per keyWalk the entire list by cursor
Official X API followersGated, enterprise pricingApproved X developer app requiredLower tiers cannot read followers at allWindowed caps and hard tier ceilings
Browser scraping the followers tabFree, minus proxy and server costLogged-in session cookies or tokensIPs get banned fast under any real loadSnaps on UI changes, partial data only

Pricing stays simple and flat

$0.016

for every 1,000 followers you export

$0.50

in free credit at signup, no card

$0

monthly fee, you are billed per call

At $0.0008 a call returning about 70 followers on the first page and fewer after it, 1,000 followers takes roughly 15 to 20 calls and comes to about $0.012 to $0.016. Find the full breakdown on the Twitter API pricing page or estimate your monthly spend with the Twitter API cost calculator.

Every field the follower object returns

A follower record is a full user object, not a handle and an id. That matters because most of the work people do after an export, scoring accounts, filtering bots, segmenting by size or recency, needs profile fields that a thin response would force you to fetch separately at a second cost per row. The table below is the published schema, the same one the OpenAPI document describes, so you can size your database columns before writing a line of client code.

FieldTypeWhat it is good for
idstringStable primary key. A string on purpose: X ids exceed the safe integer range in JavaScript
usernamestringHandle without the leading @. Changeable, so never use it as a join key
namestringDisplay name, for anything a human reads
descriptionstringBio text. The single most useful field for keyword segmentation of an audience
locationstringSelf-reported and unvalidated. Useful in aggregate, unreliable per row
urlstringLinked website. A strong signal when profiling a follower base for company domains
followers_countintegerAudience size, for weighting or tiering followers by reach
following_countintegerPaired with followers_count, the ratio is the cheapest bot heuristic there is
tweet_countintegerTotal posts. A zero here beside a high follower count is worth flagging
favourites_countintegerLikes given. Distinguishes lurkers from active participants
media_countintegerMedia posted, for finding creators inside a follower base
listed_countintegerHow many public lists the account appears on, a decent proxy for topical authority
created_atstringAccount age. Beside followers_count it is the fastest plausibility check available
verifiedbooleanLegacy verification, distinct from the paid badge below
is_blue_verifiedbooleanThe current paid Verified badge
verified_typestringBusiness or Government where it applies, for separating brands from people
professional_typestringCreator or Business when the account declares one
affiliate_labelobjectThe parent-organization badge, which maps employees to their company
is_automatedbooleanX's own automated-account label, a declared bot signal rather than a guess
automated_bystringThe handle operating an automated account, when labelled
protectedbooleanThe account is locked, so its posts are not publicly readable by anyone
possibly_sensitivebooleanFlagged for sensitive media, useful for brand-safety filtering
default_profile_imagebooleanStill on the default avatar, a classic low-effort-account signal
pinned_tweet_idsarrayPinned post ids, the cheapest route to an account's own headline message
profile_image_urlstringAvatar URL, for rendering a list in an interface
cover_picturestringProfile banner URL, when the account has set one
can_dmbooleanWhether the account accepts a direct message from the calling session
unavailablebooleanTrue when X reports the account as suspended or otherwise gone. Read this before counting an unfollow
unavailable_reasonstringThe short reason code behind an unavailable account
withheld_in_countriesarrayISO codes where X withholds the account, which matters for regional analysis

Three of those repay a second look. is_automated and automated_by come from X's own automated-account label, so a bot filter can start from a declared signal rather than a heuristic. unavailable with unavailable_reason is how a suspended or deleted account arrives, which is a state you want to record rather than silently drop, since it is the difference between an unfollow and a suspension. And created_at beside followers_count is the cheapest two-field plausibility check there is: an account made last week with 40,000 followers is worth a closer look.

Error responses, and what to do about each

Every error comes back as the same envelope, a machine-readable error code and a human message, so a client can branch on the code and log the message rather than parse prose. The distinction that matters in a paging loop is which of these you retry and which you must not.

StatusCodeCauseWhat to do
400bad_requestA missing or malformed parameter, usually a username with a leading @ or a cursor copied with whitespaceDo not retry. Fix the request. A retry loop on a 400 burns wall clock and changes nothing
401unauthorizedThe key is missing, malformed or revokedDo not retry. Check the Authorization header carries Bearer and the key itself
402insufficient_creditsThe balance is exhaustedStop the job and top up. Worth alerting on separately from other failures, because it is the one error a long export hits halfway through
404not_foundThe account does not exist, was deleted, or is protectedDo not retry. Record the handle as unresolvable rather than dropping it, or the next run tries it again
429rate_limitedMore than 600 requests a minute on this keyRetry with exponential backoff and jitter. This is the one error a healthy client is expected to see
5xxserver_errorA failure on our sideRetry with backoff. Failed calls are not billed, so a retry costs nothing but time

The rule that keeps a long export honest: retry 429 and 5xx, never retry 400, 401 or 404. A client that retries everything turns a typo into a twenty-minute stall and still ends with the same error.

What a full follower export costs, by account size

A flat per-call rate makes this arithmetic rather than a quote. At roughly $0.012 to $0.016 per 1,000 follower records (the exact figure depends on where in the crawl a page falls, since the first page returns more records than later ones), the cost of an export is the follower count times that rate, and the wall clock is governed by the 600 requests a minute ceiling on a single key.

Account sizeCost of one full exportCost of a daily re-pull for a month
5,000 followersAbout $0.06-0.08About $1.80-2.40
50,000 followersAbout $0.60-0.80About $18-24
500,000 followersAbout $6-8About $180-240
2,000,000 followersAbout $24-32About $720-960

The third column is the one worth reading twice, because it is where most follower projects overspend. Re-pulling two million records every day is thirty times the cost of pulling them once, and for most questions it buys nothing: a follower list of that size does not change materially in 24 hours. Pull the full list on a weekly or monthly cadence, and track the daily delta through the account's followers_count, which is one cheap profile call rather than a full crawl. Only crawl in full when the count moved enough to be worth explaining.

Detecting new followers and unfollows with a set diff

X does not publish an unfollow event, and no third-party API can invent one. The only honest way to know who left is to hold two snapshots and subtract. That is straightforward, and it has exactly one trap worth naming: an account that was suspended, deactivated or went private looks identical to an unfollow in a naive diff, and telling them apart is why the unavailable field is in the response.

import requests

BASE = "https://api.twitterapis.com/twitter/user/followers_v2"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}

def snapshot(username):
    """Full follower list as {id: user}. One billed call per page."""
    out, cursor = {}, ""
    while True:
        body = requests.get(BASE, headers=HEADERS, timeout=30,
                            params={"username": username,
                                    "cursor": cursor}).json()
        for u in body.get("users", []):
            out[u["id"]] = u
        # Follower-graph endpoints keep returning a non-null cursor
        # past the end, so has_more is the reliable stop signal.
        if not body.get("has_more"):
            break
        cursor = body.get("next_cursor", "")
    return out

today = snapshot("someaccount")
yesterday = load_previous_snapshot()

gained = today.keys() - yesterday.keys()
lost = yesterday.keys() - today.keys()

# Split the losses. An account X reports as unavailable did not
# unfollow you, it stopped existing, and counting it as churn
# makes a suspension wave look like a content problem.
suspended = {i for i in lost if yesterday[i].get("unavailable")}
real_unfollows = lost - suspended

Two operational notes for a diff job. Take both snapshots at roughly the same time of day, because a list crawled over two hours is a moving target and a large account will gain followers mid-crawl, showing up as phantom churn. And store the snapshot rather than only the diff: the second time someone asks a question about last quarter, a stored snapshot answers it for free and a stored diff does not.

Five things people get wrong reading a follower list

The endpoint is simple. The conclusions drawn from it are where the errors live, and none of these surface as a failure: the pipeline stays green and the number is quietly wrong, which is why they survive so long.

  • Treating the follower count and the crawl total as the same number. They rarely match exactly. The count on a profile is X's own aggregate at that instant, while a crawl is a walk over pages taken across minutes, during which the list moves. A small gap is normal and is not evidence of missing data.
  • Reading follower order as recency. The order pages come back in is the platform's, and it is not a documented chronological sort. If you need to know who followed recently, the answer is a diff between two snapshots, not the top of page one.
  • Quoting an engagement rate off a raw follower total. A follower list contains inactive accounts, automated accounts and accounts X has since suspended. The response already carries the fields to filter them, the automated-account label, the default-avatar flag, the follower-to-following ratio, the tweet count and account age, so a filtered denominator is a filter over data you have rather than a second integration.
  • Comparing two accounts' lists without normalising for size. Overlap between a 2,000-follower account and a 2,000,000-follower account is dominated by the larger one. If the question is affinity rather than reach, use a proportion of the smaller audience, not a raw intersection count.
  • Assuming a handle is a stable identity. Handles change. An account that renamed itself reads as one departure plus one arrival in any diff keyed on the username, which manufactures churn that never happened. Key on the numeric id and treat the handle as a display field that happens to be searchable.

The habit that catches most of these is recording provenance beside every number: what was crawled, when it started, when it finished, and which filters were applied to the denominator. A figure without those four is not reproducible next quarter, which is usually when somebody asks.

Rate limits, concurrency, and how long a crawl takes

One key carries 600 requests a minute. That number is the whole capacity plan, and it is worth converting into wall clock before you schedule anything, because the answer decides whether a job is a cron entry or a queue with checkpoints.

600 requests a minute is 36,000 calls an hour on a single key. Converting that into followers depends on how many records a page returns, which X varies, so the honest way to plan is to divide your target by the page size you actually observe on your first run rather than by a number we quote. On the roughly $0.012 to $0.016 per 1,000 basis this page prices against, 36,000 calls an hour is roughly 1.8 to 2.6 million records, so a 50,000-follower account is a couple of minutes, half a million is a quarter of an hour or so, and two million is a little over an hour. That last one is the point where a crawl stops being instantaneous relative to the thing it measures: the list changes while you read it, so treat the result as a reading taken over a window rather than a state at an instant, and record the start and end times with the snapshot.

Two practical notes. Run fewer workers than the ceiling allows, not more: a client that sits at 600 spends its time being rate limited and backing off, and the effective throughput of a job that trips 429 constantly is lower than one pacing itself at 80 percent. And pagination is sequential by construction, because each page needs the cursor from the one before it, so concurrency comes from crawling several accounts at once rather than from parallelising a single list.

Checkpoint the cursor. If a two-million-record crawl dies forty minutes in, resuming from the last successful cursor costs a few calls, and restarting costs forty minutes and the credits already spent. Failed calls are not billed, but successful ones you throw away are.

Storing follower snapshots without the table exploding

The API side of follower work is a loop. The part that usually goes wrong is what happens after, because the obvious design, one row per follower per snapshot, turns a 500,000-follower account tracked daily into 15 million rows a month, almost all of them identical to the row before.

The shape that holds up is two tables. One holds the account itself, keyed on the numeric id as text or bigint, carrying the profile fields and a last_seen timestamp, updated on each crawl. The other holds membership as intervals rather than snapshots: one row per follow relationship with a first_seen and a nullable last_seen, closed off when the account stops appearing. That answers who followed us in March, who left in June, and who has been here the whole time, all without storing a row per day.

Three details that cause real bugs. Store ids as text or bigint and never as a float or a JavaScript number, because X ids exceed the safe integer range and rounding two accounts onto the same key is a silent corruption rather than an error. Never key on the handle, because handles change and the same person then reads as one departure plus one arrival. And record unavailable when it comes back true rather than deleting the row, or a suspension wave shows up in your dashboard as a churn spike caused by something you did.

On volume: profile fields change far more slowly than membership does. Re-writing a full profile row on every crawl is mostly write amplification. Compare a hash of the fields you care about and update only when it moves, and the storage cost of tracking a large account drops by an order of magnitude.

When followers are not enough

The follower graph is just one layer of an account. When you also need timelines, tweets, and profiles, the wider Twitter scraper reaches the rest of the surface on the same key. For querying tweets by keyword, turn to the Twitter search API, and to feed followers into an AI agent, plug in the MCP server. A raw follower list also says nothing about how many of those accounts are real, which matters before anyone quotes an engagement rate off the total: scoring an account for automation starts from the profile and follow-graph fields these endpoints already return, so a first pass over your own follower list is a filter over data you have rather than a new integration.

By the numbers

Follower data, in numbers.

Sourced figures behind follower-pull costs.

  • The official X API bills user and follower reads pay-per-use at $0.010 per resource under the pay-per-use model. (X Developer Platform, 2026)

  • Official X API follower and user endpoints run on 15-minute windows, and pay-per-use is hard-capped at 3 million reads per monthly billing cycle. (X API docs, 2026)

  • TwitterAPIs bills each follower call at $0.0008, roughly $0.012 to $0.016 per 1,000 records, under one flat ceiling of 600 requests a minute per key. (TwitterAPIs pricing, 2026)

  • TwitterAPIs ships 6 follower-graph endpoints, including verified followers and followers-you-know, behind one Bearer key. (TwitterAPIs docs, 2026)

  • A new TwitterAPIs account starts with $0.50 in free signup credit, enough for tens of thousands of follower records, and no credit card. (TwitterAPIs pricing, 2026)

Followers API, common questions

Hit GET /twitter/user/followers and pass the userName of the target account. The response carries a followers array plus a next_cursor and a has_more flag. For a complete dump, leave cursor empty on the first request, feed next_cursor back on every subsequent request, and stop once has_more turns false. Each request costs $0.0008 and returns about 70 followers on the first page and fewer after that, so a 1,000-follower export takes roughly 15 to 20 calls and runs about $0.012 to $0.016. Everything comes back as clean JSON, ready to drop into CSV or a table.

Every call is a flat $0.0008. Calls return about 70 followers on the first page and fewer after that, so pulling 1,000 followers takes roughly 15 to 20 calls and lands around $0.012 to $0.016. No plan, no monthly floor, no commitment. The official X API hides follower reads behind paid developer tiers and blocks them entirely on cheaper plans, which makes TwitterAPIs the lowest-cost pay-as-you-go way to export a follower list at scale.

Leave the cursor parameter off your first request to land on page one. Every response ships a next_cursor token alongside a has_more flag. Drop that next_cursor into the cursor parameter on the next request to grab the following page, and keep looping while has_more stays true. The whole list comes out this way, with no state pinned on the server. Following, verified followers, and mutuals all page with the exact same mechanic.

One key is capped at 600 requests a minute, which is 36,000 calls an hour. How many followers that lands depends on the page size X returns, which varies, so divide your target by the page size you observe on your first run rather than by a quoted figure. On the roughly $0.012 to $0.016 per 1,000 basis this page prices against, that is roughly 1.8 to 2.6 million records an hour, so a 50,000-follower account is a couple of minutes, half a million is a quarter of an hour or so, and two million is a little over an hour. At that scale the list genuinely changes while you are reading it, so store the crawl start and end times alongside the snapshot and treat the result as a reading over a window rather than a state at an instant. Pagination itself is sequential because each page needs the previous cursor, so extra throughput comes from crawling several accounts concurrently rather than splitting one list.

Usually not. A full re-pull of two million records daily costs about thirty times a single export and for most questions buys nothing, because a list that size does not change materially in 24 hours. The cheaper pattern is to watch the account's followers_count with one profile call, which costs $0.0008, and only run a full crawl when the number moved enough to be worth explaining. Weekly or monthly full crawls with a daily count check give you the same answers for a fraction of the spend.

Yes. GET /twitter/user/check_follow_relationship resolves the follow link between two accounts in one call, so you can verify whether user A follows user B without crawling a whole list. To find shared connections, POST /twitter/user/followers_you_know returns the followers the two accounts have in common, which is the mutuals view.

No X developer account and no official OAuth dance are involved. All you need is a TwitterAPIs key, a single Bearer token you grab after a 30-second signup, and it signs every followers and following request. Nothing waits on app review or approval, so your first follower pull can happen inside a minute. Signup also drops $0.50 of free credit into your account, with no card on file.

Both return about 70 followers on the first page and fewer on subsequent pages, so there is no page-size or cost difference between them. The difference is the response: followers_v2 attaches a fuller profile object to each record and has the more consistent cursor. Prefer v2 for new work. Use v1 only when you already have an integration built against its response shape. Note that the count parameter is currently ignored by both endpoints, so page size is fixed regardless of what you request.

Yes to both. GET /twitter/user/verified_followers narrows the result to an account's verified followers, while GET /twitter/user/following (or following_v2) returns the accounts that user follows. Each one authenticates with the same Bearer key, bills at the same flat $0.0008 per call, and pages with the identical cursor loop the followers endpoint uses.

Read the unavailable field. An account that X reports as unavailable, suspended or deactivated, did not unfollow you: it stopped existing. A naive set difference between two snapshots counts both the same way, which makes a platform-wide suspension wave look like a content problem on your side. Split the losses into suspended and genuine unfollows before anything reaches a dashboard, and keep the unavailable_reason string, because it is the only explanation you will get.

A full user object, not a handle and an id. That includes the bio, location, linked URL, follower and following counts, tweet and media counts, listed count, account creation date, both verification flags, the professional and affiliate labels, X's own automated-account label, and the profile and banner image URLs. Because the profile arrives with the follower, segmentation and scoring work on data you already paid for rather than needing a lookup per row at a second cost.

Pull a follower list without an X account

Roughly $0.012-0.016 per 1,000 followers, $0.50 in free credit. Cursor paging, no developer account, 600 req/min per key.