Tweepcred: How Twitter (X) Scores Account Reputation, Read From the Code

By TwitterAPI.io Team•14 min read
Diagram of the 2023 Tweepcred pipeline (user mass prior, PageRank, follower-ratio post-adjust, 0-100 score) above the 2026 user-cred-v2 pipeline (eligible users, teleport vector, PageRank, 0-100 score)
Tweepcred (2023) and user-cred-v2 (2026), with constants quoted from the two GitHub repositories.

This page explains the account-level score called Tweepcred and its 2026 successor. Our guide to Twitter search engine optimization covers how posts rank in X search and Google; Tweepcred sits one layer below that, as a reputation number attached to the author, not the post.

Most pages about Tweepcred repeat numbers with no source: a starting score of -128, a +100 boost for verified accounts, throttling below 17. We read every file in the tweepcred directory of the-algorithm, the repository Twitter published under its twitter organization on GitHub, followed the score into the search and follow-recommendation code that consumes it, then read user-cred-v2/ in github.com/xai-org/x-algorithm, the version X published in 2026. Every formula and constant below is quoted from those files.

The code cannot tell you your own score: PageRank needs the whole follow graph, and the device and restricted flags are private. What it can tell you is exactly how much the follower/following ratio matters. So the unique part of this page is an estimator of that published rule, run on 1,804 real high-reach accounts collected in 2026.

01 — Section

What Tweepcred is, and where the 2023 code uses it

The repository's own index lists Tweepcred as the "Page-Rank algorithm for calculating X User reputation". Its README describes it as a tool that "calculates the influence of Twitter users based on their interactions with other users" using PageRank, and the TweepcredBatchJob description calls the output a "Twitter credibility" score. The job writes a daily file of user IDs and scores under /user/cassowary/tweepcred/, in an unweighted and a weighted variant.

Which graph. The README says interactions such as mentions and retweets form the edges. The code is more specific: PreparePageRankData reads follow edges from Flock (X's social graph store, positive edges only, snapshot no older than 7 days). With --weighted it can take edge weights from the Real Graph interaction model, but the default is weighted=false and flock_edges_only=true. In the default configuration, Tweepcred is PageRank over who follows whom.

Which PageRank. WeightedPageRank.scala documents its update: each user passes its mass equally to everyone it follows; mass from users who follow nobody is spread evenly; and a random-jump share (jumpprob, default 0.1) is handed out in proportion to each user's prior, not uniformly. The job stops after 20 iterations or when the total change drops below 0.001, and each day starts from the previous day's result.

What makes it a reputation score rather than plain PageRank is the prior and the two adjustments covered in the next two sections. Without them, any account with many followers would score high regardless of how it got them.

Where the 2023 code uses it. Searching the repository for the score shows where it was wired in, which matters more than the formula when you ask what a low score did.

Consumer (file)What it does with Tweepcred
Search ingester (UserPropertiesManager.java)Reads each author's TWEEPCRED value and stores it with every indexed post
Search filter (BadUserRepFilter.java)Drops posts whose author is below a caller-supplied minTweepCred
Anti-gaming (AntiGamingFilter.java, ranking.thrift)Caps hits per author (default 3); authors above maxTweepcredForAntiGaming, default 65 in facet ranking, are exempt
Light ranker (Earlybird README)Lists tweepcred among the static features in the scoring function
Follow recommendations (LowTweepCredFollowStore.scala)Picks out recently followed accounts (up to 500) whose score is below 40

Two takeaways. First, the thresholds that actually appear in the code are 65 and 40, plus whatever minTweepCred a search caller passes; we did not find a hard-coded 17 in any file we read. Second, the 2023 home-timeline heavy ranker that most algorithm guides discuss scores posts by predicted engagement; in that release Tweepcred reaches the For You feed indirectly, through the Earlybird search index and its light ranker, not as a published multiplier on the final score.

02 — Section

Step 1: the user mass prior (account age, device, verification)

UserMass.getUserMass gives every account a starting mass before PageRank runs. Deactivated accounts are skipped. Suspended accounts get 0. Accounts with the internal verified safety flag get 100. Everyone else starts at 0.05 (half of the device weight times 0.1), plus 0.5 if the account has a registered messaging device, so a fully trusted account reaches 0.55 before scaling.

That base is multiplied by an age term: 1.0 for accounts older than 30 days, otherwise min(1, ln(1 + age_days / 15)). A one-day-old account keeps about 6% of its base; at 15 days it keeps 69%. The result is floored at 0.01, multiplied by 0.1 if the account is restricted, capped at 1 and multiplied by 100.

The first ratio rule lives here. If the account follows more than 500 others and (1 + following) / (1 + followers) is above 0.6, the mass is divided by e^(5 x (ratio - 0.6)), with no upper limit. A small account following 600 people with 100 followers has a ratio of 5.95 and its prior is divided by roughly 4 x 10^11, which in practice removes it from the random-jump share entirely.

What the +100 claim really is. The "+100 for verified" figure that circulates online most likely comes from this line, but it is the prior mass, not 100 Tweepcred points. All priors are normalized to sum to 1 before PageRank, and the prior only steers the 10% random-jump share. The flag is the legacy safety verified bit; Blue subscriptions do not appear anywhere in the 2023 tweepcred files.

03 — Section

Step 2: the post-PageRank penalty and the 0-100 scale

After PageRank converges, ExtractTweepcred (with post_adjust on by default) calls Reputation.adjustReputationsPostCalculation. For accounts following more than 2,500 others it computes a division factor e^(3 x (ratio - 0.6) x ln(ln(following))), clamps it between 1 and 50, and divides the PageRank by it. Below a ratio of 0.6 the factor is under 1 and the clamp turns it into 1, so nothing changes. The adjusted values are normalized again.

Reputation.scaledReputation then maps PageRank to the familiar number: 130 + 5.21 x ln(pagerank), rounded and clamped to 0 to 100, with anything below 1e-20 set to 0. The code comment says the two constants come from a linear fit that sends the maximum PageRank to 95 and the minimum to 15. Because the scale is logarithmic, dividing PageRank by a factor d removes exactly 5.21 x ln(d) points, so the post-adjust rule can cost at most 5.21 x ln(50) = 20.4 points.

FollowersFollowingRatioPrior divided byPoints removed
1006005.954.2e+110.0
1,0003,0003.01.6e+0520.4
2,0003,0001.589.920.4
5,0003,0000.61.00.0
5005,0009.982.4e+2020.4
10,0005,0010.51.00.0

Those rows are synthetic profiles run through the two functions, so you can see the gates: 600 following with 100 followers is punished hard in the prior but untouched by the post-adjust rule (it needs more than 2,500 following), and 5,000 followers against 3,000 following sits on the 0.6 line and loses effectively nothing (under 0.01 points). Numbers in scientific notation mean the prior is effectively zero.

python
import math

def tweepcred_ratio_adjustments(followers: int, following: int) -> dict:
    """The two follower/following rules in the 2023 Tweepcred code, nothing else."""
    ratio = (1.0 + following) / (1.0 + followers)

    # UserMass.scala: shrinks the PageRank prior (teleport mass)
    umass_div = 1.0
    if following > 500 and ratio > 0.6:
        umass_div = math.exp(5.0 * (ratio - 0.6))

    # Reputation.adjustReputationsPostCalculation: shrinks final PageRank
    rep_div = 1.0
    if following > 2500:
        d = math.exp(3.0 * (ratio - 0.6) * math.log(math.log(following)))
        rep_div = max(min(d, 50.0), 1.0)

    # scaledReputation = 130 + 5.21 * ln(pagerank), so dividing by d removes 5.21 * ln(d)
    return {
        "ratio": round(ratio, 4),
        "prior_divided_by": round(umass_div, 2),
        "pagerank_divided_by": round(rep_div, 2),
        "tweepcred_points_removed": round(5.21 * math.log(rep_div), 1),
    }

print(tweepcred_ratio_adjustments(followers=29_454, following=29_834))
# {'ratio': 1.0129, 'prior_divided_by': 7.88, 'pagerank_divided_by': 17.98, 'tweepcred_points_removed': 15.1}
04 — Section

Study: how many real accounts the ratio rule touches

We pulled current profiles for 1,804 accounts with at least 10,000 followers and ran each one through the two ratio rules exactly as coded. The median account has 94,361 followers and follows 644, a ratio of 0.005622. Ninety percent sit below 0.118.

Measure (2023 rules)All 1,804Named 149Followed set 1,655
Following more than 50056.2%34.2%58.1%
Following more than 2,500 (post-adjust gate)19.0%9.4%19.9%
Ratio above 0.60.7%0.0%0.8%
Prior shrunk (UserMass rule)13 (0.7%)013
Score cut (post-adjust rule)13 (0.7%)013
Median points removed, among those cut6.62none6.62

The headline. Almost a fifth of these accounts follow more than 2,500 others, so they pass the first gate, but only 13 also follow more than 0.6 accounts per follower. Those 13 lose between 0.72 and 17.48 points; none reaches the 50x cap. The rule was written for follow-for-follow accounts, and established accounts almost never look like that.

Account age is a non-factor here. Every account in the sample is older than 30 days (median 16.5 years), so the age term is at its maximum of 1.0 for all of them. It only matters in an account's first month.

Bar chart of following-to-followers ratio for 1,804 X accounts with 10,000+ followers: 564 below 0.001, 483 from 0.001 to 0.01, 539 from 0.01 to 0.1, 205 from 0.1 to 0.6, 11 from 0.6 to 1, 2 from 1 to 10; only accounts right of 0.6 are penalized
Following/followers ratio for 1,804 accounts with 10,000+ followers, collected in 2026. Only 13 cross the 0.6 gate.
05 — Section

The 13 accounts the rule touched (not named)

The accounts that trip the rule all come from the followed set, which can include individual people, so we show their numbers without names. The pattern is the same in every row: tens of thousands of followers, and nearly as many accounts followed. The eight largest losses are shown.

FollowersFollowingRatioPoints removed
59,11162,9851.0717.5
29,45429,8341.0115.1
11,66511,4110.9813.2
19,59118,6370.9512.6
13,21011,5540.879.6
49,31142,3160.869.6
10,7018,4780.796.6
10,6308,3700.796.5

Read the chart below as the full rule: each blue line is the formula at a fixed following count, and the orange dots are the real accounts. The loss rises roughly linearly with the ratio above 0.6, slightly faster for accounts that follow more people (the ln(ln(following)) term), and flattens at 20.4 points.

If you want to move out of this zone under the 2023 rules, only two numbers matter: following below 2,500, or a ratio below 0.6. Unfollowing inactive accounts lowers both. Nothing else in the tweepcred code reads your follower count.

Line chart of Tweepcred points removed against following/followers ratio for following counts of 3,000, 10,000 and 100,000, zero below a ratio of 0.6 and capped at 20.4 points, with 13 sample accounts plotted between 0.7 and 17.5 points
Points removed by the 2023 post-adjust rule, formula lines plus the 13 sample accounts it touched (collected in 2026).
06 — Section

What changed in 2026: user-cred-v2

In August 2026 X added user-cred-v2/ to github.com/xai-org/x-algorithm, the repository for the current For You feed (Apache-2.0, first published January 2026). The README describes it as a job that "runs PageRank over the follow graph and engagement edges, and turns the resulting mass into a per-account score". It lives in a platform_manipulation package and sits in the labeling path that feeds visibility filtering, not in the post ranker.

SettingTweepcred (2023)user-cred-v2 (2026)
GraphFollow edges (Flock)Follow edges, minus pairs flagged as linked accounts
Who is excludedDeactivated; suspended get 0Restricted, suspended, erased, deactivated; near-zero users pass no mass
Random-jump seedUser mass prior (age, device, legacy verified)50% uniform over Blue, gray, gold, verified orgs and affiliates; 50% from 7 days of likes and reposts weighted by the engager's mass
Jump probability, iterations0.1, up to 200.2, up to 50
Score formula130 + 5.21 ln(pagerank), 0-100165.2 + 7.07 ln(mass), 0-100
Follower-ratio ruleYes, two of themNone in this job

Premium status now shapes the seed. In v2, only accounts with a Premium or organization verification flag (and not in the near-zero state) receive the uniform half of the random jump; everyone else can enter the seed only through likes and reposts they received from accounts that already have mass. That is a structural advantage, not a fixed point bonus. In our sample, 61.7% of accounts are isBlueVerified and 70.3% carry Blue or an organization type (Business 475, Government 95); among the 149 named organizations and public figures it is 99.3%.

Where the v2 score is read. In the published code it appears as user_cred_score on a high-PageRank-user record in abuse-enforcement-service, as a downstream call in the scarecrow rule engine, as a normalized feature in the bdsm inauthentic-behavior model, and as a user_credibility field on post embeddings in Phoenix serving. The README is explicit that ranking order comes from Phoenix's predicted actions; credibility is one input to labeling and filtering. Whether X still runs the 2023 Tweepcred job alongside v2 is not stated in either repository.

07 — Section

Myths about Tweepcred, checked against the code

Claim seen onlineWhat the code says
New accounts start at -128Both versions clamp the score to 0 to 100; a negative value cannot be produced
Verified accounts get +100 Tweepcred2023: verified sets the prior mass to 100 before normalization, not the score
You need 17 to be distributedNot found in the files we read; code thresholds are 65, 40 and a caller-set minimum
A bad follower ratio kills reachOnly above 500 or 2,500 following and a 0.6 ratio; 0.7% of our sample
Grok, dwell time or bio quality feed TweepcredNeither version reads text, dwell time or bio fields

Tweepcred calculators. Any tool that prints a single Tweepcred number for your handle is guessing: the PageRank term needs the full follow graph, and the device, restricted and near-zero states are not public. What a tool can compute honestly is the ratio rule, the age term and your verification flags, which is what the code above and our study do.

Older research named TweetCred. A 2014 academic system called TweetCred scored the credibility of individual tweets during crises. It is unrelated to X's internal Tweepcred despite the similar name.

08 — Section

Check the public inputs for any account with the API

Every input the ratio rules need is public: followers, following, createdAt, isBlueVerified and verifiedType come back from /twitter/user/info (one handle) or /twitter/user/batch_info_by_ids (up to 100 IDs per call, as we used in this study). /twitter/user/followings returns about 200 accounts per page with followers_count and following_count already attached, so you can screen everyone you follow in a few calls. Reads need only an API key; no X account is involved.

Cost, against the official rate card. Profiles cost 18 credits each on TwitterAPI.io, $0.18 per 1,000; following lists cost 1 to 3 credits per account returned. The official X API pay-per-usage rate card at docs.x.com/x-api/getting-started/pricing lists User: Read at $0.010 per resource, $10 per 1,000, about 55 times more for the same profile fields; for posts it is $0.005 per post read against our $0.15 per 1,000 tweets, about 33 times. This whole study, 36 requests and 1,804 profiles, cost at most $0.42 at our rates (1,804 profiles at 18 credits plus 3,165 following-list rows at up to 3 credits).

New accounts that pass the automatic bot check get up to $1 of free credits (at most 100,000 credits, no card, one per person or network, expiring after 31 days), enough for roughly 5,500 profile lookups. Rate limits start at 0.2 requests per second before the first payment and rise to 20 once paid. Purchased credits never expire; plans and volume tiers are on the pricing page.

bash
curl -s "https://api.twitterapi.io/twitter/user/info?userName=XDevelopers" \
  -H "X-API-Key: $TWITTERAPI_KEY" | jq '.data | {userName, followers, following, createdAt, isBlueVerified}'
09 — Section

How we collected this

Question. How many real high-reach X accounts would the follower/following rules in the 2023 Tweepcred code touch, and by how much?

Accounts. Two sets. The named set is 149 organizations and public figures from a public-source list (the most-followed accounts plus major AI, tech, developer and news brands), read with /twitter/user/batch_info_by_ids. The followed set is every account followed by 10 organization accounts (NASA, Google, Microsoft, BBCWorld, Reuters, espn, NBA, nytimes, awscloud, github), read with /twitter/user/followings (up to 2 pages each), de-duplicated, kept if public with at least 10,000 followers and not already in the named set: 1,655 accounts, re-read with batch_info_by_ids for verification flags.

Window and size. One profile snapshot per account, collected in 2026: 1,804 accounts from 36 read-only requests.

Method. The ratio, the UserMass division factor, the post-adjust division factor and the points removed are computed with the constants in UserMass.scala and Reputation.scala, unchanged. The analysis script, results and de-identified rows are in the study folder data/studies/tweepcred/ of this site's repository.

What the sample cannot show. Nobody's actual Tweepcred or user-cred-v2 score: PageRank needs the full graph, and the device, restricted and near-zero flags are private. Accounts under 10,000 followers, where the ratio rule bites far more often, are not in the sample by design. X may have changed thresholds in production since the code was published.

Privacy. Aggregates only. The followed set can include individual people, so none of them is named, and the study keeps only numeric rows without IDs or handles.

python
import math
import requests

API_KEY = "YOUR_API_KEY"
BASE = "https://api.twitterapi.io"
HEADERS = {"X-API-Key": API_KEY}


def ratio_penalty(followers: int, following: int) -> dict:
    """Apply the follower/following rules from the 2023 open-sourced Tweepcred code."""
    ratio = (1.0 + following) / (1.0 + followers)
    prior_div = math.exp(5.0 * (ratio - 0.6)) if (following > 500 and ratio > 0.6) else 1.0
    post_div = 1.0
    if following > 2500:
        d = math.exp(3.0 * (ratio - 0.6) * math.log(math.log(following)))
        post_div = max(min(d, 50.0), 1.0)
    return {
        "ratio": round(ratio, 4),
        "prior_divided_by": round(prior_div, 2),
        "points_removed": round(5.21 * math.log(post_div), 1),
    }


def followings(user_name: str, max_pages: int = 2) -> list:
    """Accounts a user follows (about 200 per page), following next_cursor."""
    out, cursor = [], ""
    for _ in range(max_pages):
        r = requests.get(
            f"{BASE}/twitter/user/followings",
            headers=HEADERS,
            params={"userName": user_name, "pageSize": 200, "cursor": cursor},
            timeout=30,
        )
        r.raise_for_status()
        body = r.json()
        out.extend(body.get("followings") or [])
        if not body.get("has_next_page"):
            break
        cursor = body.get("next_cursor") or ""
    return out


def profiles_by_ids(ids: list) -> list:
    """Current profiles for up to 100 user IDs per call."""
    users = []
    for i in range(0, len(ids), 100):
        r = requests.get(
            f"{BASE}/twitter/user/batch_info_by_ids",
            headers=HEADERS,
            params={"userIds": ",".join(ids[i:i + 100])},
            timeout=30,
        )
        r.raise_for_status()
        users.extend(r.json().get("users") or [])
    return users


def one_profile(user_name: str) -> dict:
    r = requests.get(f"{BASE}/twitter/user/info", headers=HEADERS,
                     params={"userName": user_name}, timeout=30)
    body = r.json()
    if body.get("status") != "success" or not body.get("data"):
        raise SystemExit(f"lookup failed: {body.get('msg')}")
    return body["data"]


if __name__ == "__main__":
    me = one_profile("XDevelopers")
    print(me["userName"], me["followers"], me["following"],
          ratio_penalty(me["followers"], me["following"]))

    ids = [str(u["id"]) for u in followings("XDevelopers")]
    for u in profiles_by_ids(ids):
        p = ratio_penalty(u["followers"], u["following"])
        if p["points_removed"] > 0 or p["prior_divided_by"] > 1:
            print(u["userName"], u["followers"], u["following"], p,
                  "Blue" if u.get("isBlueVerified") else "", u.get("verifiedType") or "")
10 — Questions

Questions readers ask

What is Tweepcred?

Tweepcred is the account reputation score in the code Twitter open-sourced in 2023. It is PageRank over the follow graph, seeded by a prior built from account age, a device flag and verification, reduced for accounts that follow far more people than follow them back, and mapped to a whole number from 0 to 100.

How do I check my Tweepcred score?

You cannot. X does not expose the score in the app or in any API, and the PageRank part needs the entire follow graph. You can check the public inputs the code reads, followers, following, account age and verification flags, and compute the follower-ratio adjustment yourself with the formula on this page.

What is a good Tweepcred score?

The code comment says the scale was fit so the highest PageRank maps to 95 and the lowest to 15. In 2023 search code, authors above 65 were exempt from the per-author anti-gaming cap by default, and follow recommendations singled out recently followed accounts below 40. Those are the only reference points in the code.

Does a bad follower/following ratio hurt Tweepcred?

Only past two gates. The prior shrinks when you follow more than 500 accounts and follow more than 0.6 accounts per follower; the final score shrinks only above 2,500 following, by at most 20.4 points. In our sample of 1,804 accounts with 10,000+ followers, 0.7% were affected.

Does X Premium (Blue) raise Tweepcred?

Not in the 2023 code, which only reads the legacy verified flag. In user-cred-v2, published in 2026, Premium and organization verification put an account into the uniform half of the PageRank random-jump seed, which gives it more starting mass than unverified accounts. It is not a fixed point bonus.

Is Tweepcred still used in 2026?

X's 2026 open-source release (xai-org/x-algorithm) contains user-cred-v2, a PageRank credibility score used in labeling, abuse enforcement and as a feature, rather than the old tweepcred job. Neither repository says whether the 2023 job still runs.

Is the -128 starting score real?

Not in the published code. Both versions clamp the score to the range 0 to 100, so a negative value cannot be produced. The number has no source in the open-sourced repositories.

Is Tweepcred the same as TweetCred?

No. TweetCred is a 2014 academic system that rated the credibility of individual tweets during crisis events. Tweepcred is X's internal account-level reputation score.

11 — Further reading

Continue

Sources & further reading
More from this series
Build it

Stop reading. Start building.

Starter credits cover real testing on real data. Google sign-in, no card, no application queue.

Get an API key

Already building with TwitterAPI.io? Publish an honest tutorial or build log about it and earn up to $200 a month in API credits.