X's Algorithm Decoded: What Actually Gets Reach in 2026
We went through X's open-source algorithm code line by line. Here's what we found about TweepCred, spam filters, and the hidden scoring system that determines if your tweets get seen or buried.
In March 2023, X (formerly Twitter) open-sourced their recommendation algorithm on GitHub. Most people glanced at the headlines and moved on. We spent weeks reading the actual code.
What we found changes everything you think you know about growing on X.
Section 1: TweepCred - Your Hidden Reputation Score
Every account on X has a hidden reputation score called TweepCred. It ranges from 0 to 100, and it determines how much the algorithm trusts your content.
The code lives in Reputation.scala:
def scaledReputation(raw: Double): Byte = {
// convert log(pagerank) to a number between 0 and 100
val e: Double = 130d + 5.21 * scala.math.log(raw)
val pos = scala.math.rint(e)
val v = if (pos > 100) 100.0 else if (pos < 0) 0.0 else pos
v.toByte
}Your TweepCred is calculated using a PageRank-style algorithm. It factors in:
Here's the brutal part: if your TweepCred drops below 40, you're essentially invisible in Top Tweets.
Section 2: The Following Ratio Penalty
This is where most people unknowingly destroy their reach.
The algorithm has specific thresholds hardcoded in Reputation.scala:
private val threshAbsNumFriendsReps = 2500
private val threshFriendsToFollowersRatioUMass = 0.6
private val maxDivFactorReps = 50Translation:
Your TweepCred gets divided by up to 50x.
Let's say you have a TweepCred of 70. You go on a following spree and end up following 3,000 accounts with a 0.8 ratio. Your effective score could drop to 1.4.
The function that does this:
def adjustReputationsPostCalculation(mass: Double, numFollowers: Int, numFollowings: Int) = {
if (numFollowings > threshAbsNumFriendsReps) {
val friendsToFollowersRatio = (1.0 + numFollowings) / (1.0 + numFollowers)
val divFactor = scala.math.exp(
constantDivisionFactorGt_threshFriendsToFollowersRatioReps *
(friendsToFollowersRatio - threshFriendsToFollowersRatioUMass) *
scala.math.log(scala.math.log(numFollowings))
)
mass / ((divFactor min maxDivFactorReps) max 1.0)
} else {
mass
}
}This is why "follow for follow" strategies backfire. The algorithm literally penalizes accounts that look like they're gaming the system.
Section 3: The Spam Filter That Kills Your Replies
The SpamVectorScoringFunction.java file reveals how X filters spam:
private static final int MIN_TWEEPCRED_WITH_LINK =
EarlybirdConfig.getInt("min_tweepcred_with_non_whitelisted_link", 25);If your TweepCred is below 25 and you post a link (that isn't an image, video, or news), you get flagged as spam.
The scoring logic:
if (documentFeatures.isFlagSet(EarlybirdFieldConstant.HAS_LINK_FLAG)
&& !documentFeatures.isFlagSet(EarlybirdFieldConstant.HAS_IMAGE_URL_FLAG)
&& !documentFeatures.isFlagSet(EarlybirdFieldConstant.HAS_VIDEO_URL_FLAG)
&& !documentFeatures.isFlagSet(EarlybirdFieldConstant.HAS_NEWS_URL_FLAG)) {
// Contains a non-media non-news link, definite spam vector.
tweepCredThreshold = MIN_TWEEPCRED_WITH_LINK;
}This means:
Always pair links with media. The algorithm treats naked links as a red flag.
Section 4: The Reply-Back Signal (This One Is Huge)
Deep in RecapFeatures.scala, there's a feature that most people don't know about:
val IS_REPLIED_REPLY_ENGAGED_BY_AUTHOR = new Binary(
name("recap.engagement.is_replied_reply_engaged_by_author"),
Set(EngagementsPrivate, EngagementsPublic).asJava)This tracks whether the original author engaged with your reply. If they:
Your content gets a significant boost. The algorithm is literally looking for this signal.
The related features in the code:
val IS_REPLIED_REPLY_FAVORITED_BY_AUTHOR = new Binary(...)
val IS_REPLIED_REPLY_QUOTED_BY_AUTHOR = new Binary(...)
val IS_REPLIED_REPLY_REPLIED_BY_AUTHOR = new Binary(...)
val IS_REPLIED_REPLY_RETWEETED_BY_AUTHOR = new Binary(...)This is why generic replies like "Great post!" never perform. They don't trigger a response from the author. Write replies that start conversations.
Section 5: Real Graph - Your Relationship Score
The algorithm doesn't treat all engagement equally. It uses something called "Real Graph" to weight interactions based on relationship strength.
From RecapFeatures.scala:
val REAL_GRAPH_WEIGHT =
new Continuous("recap.tweetfeature.real_graph_weight", Set(UsersRealGraphScore).asJava)This means:
The algorithm tracks:
This is why engagement pods eventually stop working. The algorithm detects when engagement comes from outside your natural graph.
Section 6: The Heavy Ranker Model Weights
X uses a machine learning model called the "Heavy Ranker" to score every tweet. The model predicts multiple engagement types and weights them.
From HomeGlobalParams.scala:
object ModelWeights {
object FavParam extends FSBoundedParam[Double](
name = "home_mixer_model_weight_fav", ...)
object RetweetParam extends FSBoundedParam[Double](
name = "home_mixer_model_weight_retweet", ...)
object ReplyParam extends FSBoundedParam[Double](
name = "home_mixer_model_weight_reply", ...)
object ReplyEngagedByAuthorParam extends FSBoundedParam[Double](
name = "home_mixer_model_weight_reply_engaged_by_author", ...)
object BookmarkParam extends FSBoundedParam[Double](
name = "home_mixer_model_weight_bookmark", ...)
object ShareParam extends FSBoundedParam[Double](
name = "home_mixer_model_weight_share", ...)
}The algorithm predicts the probability of:
Each prediction is multiplied by its weight, and the sum becomes your tweet's score.
Negative signals also have weights:
object NegativeFeedbackV2Param extends FSBoundedParam[Double](
name = "home_mixer_model_weight_negative_feedback_v2", ...)
object ReportParam extends FSBoundedParam[Double](
name = "home_mixer_model_weight_report",
min = -20000.0, max = 0.0)Reports carry massive negative weight (up to -20,000). A few reports can tank your visibility.
Section 7: Dwell Time - The Silent Ranking Factor
The algorithm tracks how long people look at your content:
val IS_DWELLED_1S = new Binary(name("recap.engagement.is_dwelled_1s"), ...)
val IS_DWELLED_2S = new Binary(name("recap.engagement.is_dwelled_2s"), ...)
// ... up to 10 seconds
val IS_TWEET_DETAIL_DWELLED_8_SEC = new Binary(...)
val IS_TWEET_DETAIL_DWELLED_15_SEC = new Binary(...)
val IS_TWEET_DETAIL_DWELLED_25_SEC = new Binary(...)
val IS_TWEET_DETAIL_DWELLED_30_SEC = new Binary(...)If people scroll past your tweet in under 1 second, that's a negative signal. If they stop and read for 8+ seconds, that's a strong positive signal.
This is why:
Section 8: What This Means For Your Strategy
Based on the actual code, here's what works:
The algorithm isn't random. It's a machine learning model with specific features and weights. Now you know what those features are.
How Quickly Uses This
We built Quickly to analyze your replies against these exact signals before you post. Our A-F grading system checks:
Instead of guessing, you'll know if your reply will get seen or buried.
The algorithm is public. The playbook is in the code. Now it's just about execution.