Finding fake followers (Bluesky edition)
A few techniques for detecting inauthentic follower growth on Bluesky
How can one identify large swarms of fake followers on Bluesky? Since the platform has some similarities to X/Twitter, techniques that were effective on that platform back in the days of the free Twitter API work on Bluesky as well, such as searching for large streaks of follows from accounts with similar creation dates or repeated profile content. Bluesky introduces a few twists to the mix, such as the firehose, which makes real-time detection of inauthentic follower growth more practical, and the starter pack feature, which can sometimes result in genuine growth that is easily mistaken for infusions of fake followers. (Inauthentic audience growth via starter packs does happen, but is a topic for another day.)
For example, a quick scroll through the followers of @johnnydeppofficiai.bsky.social (a fake Johnny Depp account), @brucespringsteen7.bsky.social (a fake Bruce Springsteen account), and @iammrneeson1.bsky.social (a fake Liam Neeson account), reveals a bunch of accounts with zero posts and weirdly similar generic biographies. These accounts share these characteristics with a previously identified network of over 15,000 follow/repost spam accounts that were banned by Bluesky at some point in late December 2024. The spam accounts following the three fake celebrities appear to be part of an attempt to recreate this network.
Once one has a set of example fake followers that fit a given set of criteria and appear to be part of the same network, it is generally possible to map out the network using a process similar to the following:
Download the set of accounts followed by each suspected spam account. These are the current test accounts.
Filter the test accounts to those followed by at least N spam accounts. (In this case, N=300 was used.)
Download all followers of the test accounts.
Filter to any followers that A) follow more than one of the test accounts and B) match the criteria for the fake follower network (in this case, zero posts and a biography matching the expected format).
Add these followers to the set of suspected spam accounts and repeat steps 1-5 until the total number of suspected spam accounts stops increasing significantly with each iteration.
Review the resulting set of suspected spam accounts and remove false positives.
When applied to the spam accounts following the three fake celebrity accounts, this process yielded a total of 7035 accounts created between November 25th, 2024, and January 15th, 2025 that belong to the current incarnation of this spam network.
The set of accounts followed by the fake follower network is a bit eclectic, including but not limited to startup founders, musicians, aspiring political commentators, and fake Johnny Depp accounts. As with its predecessors, the network also reposts content from some of the accounts it follows. Although it remains unclear who runs this network, it is reasonable to hypothesize that it is affiliated with one or more follower sales sites, and that at least some of the accounts followed by the network are its customers.
The infusions of inauthentic followers show up as obvious horizontal streaks in follow order by creation date plots of the followers of the accounts followed by the spam network. There are also some blurrier surges present, such as the looser gray blob in November 2024, which is composed mostly of real users who signed up in the aftermath of the U.S. presidential election.
The Python code below (adapted from an earlier version written for X/Twitter) can be used to generate follow order by creation date plots from follower lists downloaded via the Bluesky API. Due to the underlying architecture, the Bluesky version is less reliable in some cases; not all accounts have the creation date populated, and the federated nature of the AT protocol means that someone running an independent server could potentially provide inaccurate dates. There is also no guarantee that the API actually returns an account’s followers in the reverse of the order in which they followed, although thus far this seems to be the case the vast majority of the time.
import bokeh.plotting as bk
import pandas as pd
def valid_time (s):
try:
return pd.to_datetime (s).tz_localize (None)
except:
return pd.to_datetime ("2000-01-01")
def follower_scatter_plot_bsky (df, handle,
opacity_norm=5000, bubble_size=4,
color=(0,90,180), cat_column=None,
cat_colors=None, start=None, end=None,
min_date=None, max_date=None,
max_sample_size=120000, outFile=None):
df["createTime"] = df["created_at"].fillna ("").apply (valid_time)
df = df[df["createTime"] >= pd.to_datetime ("2022-01-01")]
df["order"] = df.index
df["order"] = df["order"].max () - df["order"]
zoomed = ""
if start is not None:
df = df[df["order"] >= start]
zoomed = " (zoomed)"
if end is not None:
df = df[df["order"] < end]
zoomed = " (zoomed)"
if min_date is not None:
min_date = pd.to_datetime (min_date)
df = df[df["createTime"] >= min_date]
zoomed = " (zoomed)"
if max_date is not None:
max_date = pd.to_datetime (max_date)
df = df[df["createTime"] < max_date]
zoomed = " (zoomed)"
if outFile is not None:
df.to_csv (outFile, index=False)
title = "@" + handle + \
" followers - follow order by creation date" + zoomed
p = bk.figure (
title=title, width=600, height=600,
x_axis_label="follow order",
y_axis_type="datetime", y_axis_label="creation date")
if cat_colors is None or cat_column is None:
if len (df.index) > max_sample_size:
df = df.sample (max_sample_size)
alpha = opacity_norm / len (df.index)
p.circle (df["order"], df["createTime"], size=bubble_size,
color=color, alpha=alpha)
else:
for label in cat_colors:
df0 = df[df[cat_column] == label]
df1 = df.sample (1)
p.circle (df1["order"], df1["createTime"], size=bubble_size,
color=cat_colors[label],
legend=label + " (" + str (len (df0.index)) \
+ " accounts)")
p.circle (df1["order"], df1["createTime"], size=bubble_size,
color=(255,255,255))
if len (df.index) > max_sample_size:
df = df.sample (max_sample_size)
alpha = opacity_norm / len (df.index)
df["color"] = df[cat_column].apply (lambda x: cat_colors[x])
p.circle (df["order"], df["createTime"], size=4,
color=df["color"], alpha=alpha)
p.legend.location = "bottom_center"
p.xaxis.axis_label_text_font_size = "15pt"
p.yaxis.axis_label_text_font_size = "15pt"
p.yaxis.major_label_text_font_size = "12pt"
p.xaxis.major_label_text_font_size = "12pt"
p.yaxis[0].formatter.hours = ["%H:%M"]
p.yaxis[0].formatter.days = ["%Y-%m-%d"]
p.title.text_font_size = "11pt"
p.title.align = "center"
p.xaxis[0].formatter.use_scientific = False
return p
The Bluesky firehose, a real-time stream of every public action on Bluesky, offers additional possibilities for detecting bulk follow activity by observing follow actions as they happen. As an initial experiment, the firehose monitoring process described in this previous article was modified to detect any instance of an account gaining 100 or more followers in the span of under 10 minutes. This technique yielded many false positives, mostly large accounts that appear in multiple starter packs or have recent viral posts, but did identify some cases of inauthentic follower growth as well.
The firehose-based bulk follow detection flagged 55 accounts with biographies with the format “<age>, new on/fresh to bluesky💙 …😅➡️ https://bit.ly/<link>”. All 55 accounts were created on January 15th, 2025, and each has a bitly link its profile that redirects to getallmylinks(dot)com. Almost all have the display name “Naomi” or “Nora”. Each account gained at least 100 followers during a 10 minute window at some point on January 15th or 16th.
Almost all of these 55 accounts’ followers are from a fake follower network consisting of (at least) 417 accounts created throughout December 2024. These accounts are all devoid of content, having zero posts or reposts, and follow hundreds or thousands of accounts while having few followers of their own. Most have empty biographies, but a few have biographies of the same format as the accounts which they followed en masse, including the links to getallmylinks(dot)com.
I get 5-10 new followers a day and barely post, the same 5 people like & repost my stuff there. Over 1200 followers. Total bot wasteland. You’re doing great work to expose this!!