How do we count the userbase of the Atmosphere?

This came up when @erlend.sh asked about the “60M+ identities” number on the sifa.id homepage. Turns out that number was wrong and I like to have a more accurate number, but depending on what you count, that 60M might be too high or too low….

I went down the rabbit hole, crawled the entire PLC directory, and figured I’d share what I found.

What’s out there

1. Jaz’s Bluesky Stats / theo.io counter

bsky.jazco.dev/stats (by @jaz.bsky.social) indexes the Bluesky firehose and queries the Bluesky API for registered accounts, updated every ~5 minutes. bsky-users.theo.io wraps this with interpolation for a smooth real-time ticker.

Counts: registered Bluesky accounts (DIDs known to Bluesky’s AppView). Currently ~43.3M.

Good: real-time, reliable, easy to consume via JSON API.

But: only Bluesky. If you’re on a non-Bluesky PDS that their AppView doesn’t index, you don’t exist in this number. And “registered” includes every abandoned signup. Bluesky’s own 2025 transparency report says ~41.4M registered at end of 2025.

2. PLC directory crawl (what I did)

The PLC directory at plc.directory is the canonical registry for all did:plc identities, and nearly every ATProto account uses did:plc (hello did:web :waving_hand:) I crawled the entire /export API: 85.7M operations, ~80K pages, counted genesis operations (prev: null), grouped by PDS endpoint.

Results are public at sifa.id/stats.

Counts: every did:plc ever registered, regardless of PDS or AppView.

Good: complete (covers the full ATmosphere, not just Bluesky), broken down by PDS provider so you can see ecosystem composition, and the export API is public so anyone can verify.

But: no way to distinguish real accounts from junk. We found 17.4M DIDs from pds.trump.com (every single one registers with the same 7 Trump family handles… none resolve) and 1.8M from plc.surge.sh/gallery. That’s 19M+ phantom entries just from those two. Crawling the full directory takes hours, and “reachable” (handle resolves) is a proxy for “exists,” not “active.”

3. Bluesky transparency report

Bluesky’s 2025 report states 41.41M registered users at end of 2025. They say this “includes accounts hosted on Bluesky’s infrastructure, as well as the thousands of Personal Data Servers operated by people across the federated AT Protocol network.” So they count third-party PDS users too, but only those visible to their AppView.

The numbers

Metric Count Source
Total did:plc registered 79.8M PLC directory crawl
Reachable (handle resolves) ~59.3M PLC crawl + sampling
Bluesky registered accounts ~43.3M theo.io / Jaz
Bluesky reported total (end 2025) 41.4M Transparency report
Bluesky DAU (end 2025) ~5.2M Third-party estimates

The gap between 79.8M and 43.3M is mostly pds.trump.com DID spam (17.4M) and plc.surge.sh junk (1.8M). Non-Bluesky ATProto users that are actually real (Bridgy Fed, independent PDS hosts, etc.) are probably in the low hundreds of thousands.

What I got wrong

Our homepage showed “60M+ identities on the AT Protocol” by taking the theo.io Bluesky count and adding a 17M offset (a number I got from an original quick PLC directory crawl). The idea was that the PLC directory has more DIDs than Bluesky tracks, so the difference must be non-Bluesky ATProto users.

It wasn’t. It was almost entirely DID spam. :sweat_smile:

I’d love to fix that number but… to what? Any consensus on what should it should actually show?

  1. ~59M (PLC reachable): technically correct for “identities that resolve,” but probably still inflated by accounts that signed up and never came back

  2. ~80M (PLC total): the raw truth, but 20M+ of those are phantom DIDs that resolve to nothing

  3. … something else?

I get that it makes no sense to include DIDs that don’t resolve. But on the other hand it feels weird for a “total ATproto account statistic to exclude certain groups. It’s a bit like saying “There’s 6.8 Billion people in the world! We know there are actually 7.3 billion people but that group of 1.5 billion we don’t like so we exclude them from the total number of people”. It’s a statistic, not a judgement call on who to exclude :person_shrugging:

Is there any consensus in the community on how to count ATmosphere users? Are there other methods I’m missing?

Also: The PLC directory not having a count endpoint makes this harder than it needs to be… if someone can make that change that would be sweet :sweat_smile:

Check sifa.id/stats for what I got so far. Happy to open-source the crawl script if anyone wants to verify or build on this.

2 Likes

if you compare these numbers

to these numbers:

it implies that 23mil of those 39mil that haven’t generated a record in over half a year. personally MAU is the metric i think matters most, particularly for such a low-friction, multi-client app.

3 Likes

Oh for sure that is more important, I was just interested in the number because in a couple AFK discussions I had this question came up and I A) wanted to be able to provide a decent answer and B) then follow up with “But what’s even more interesting than total accounts…..” :sweat_smile:

Happy to have a discussion on how we would define MAU on ATproto.

“Creation of at least a single record in your PDS?”

1 Like

Check sifa.id/stats for what I got so far. Happy to open-source the crawl script if anyone wants to verify or build on this.

I would like to view the script

1 Like

Just to add some more confusion to the topic, even non-spam DID PLC records may not be ATProto accounts.

Roomy right now creates PLC identities for every chat space and they don’t have a PDS or anything, just a reference to the the chat server for the space.

Right now the fact that they don’t have a PDS actually makes them easy to detect. But eventually we were considering making them actually have a PDS for each space, too. And I think it’s not an uncommon idea to have accounts to represent groups or community spaces.

Maybe it’s OK to count those anyway.

2 Likes

Oeh, good one!

I’m not necessarily against counting non-humans or non-PDS accounts. These also signal some kind of value of the network.

And yes, I’m still aware that total accounts is pretty much a vanity metric.

But digging through the data is quite an educational exercise in itself. Like I had no idea about the trump PDS before (let alone how big it was) and also no idea Roomy using DID:PLCs like this. Awesome to read these creative solutions @zicklag.dev!

1 Like

I’d go for MAU, if there is no activity, they’re not counted.

Then filter by:

  • Should have a profile record
  • No takedown flag (suspended)

As for spam accounts, is it doable to filter them? Usually if they get suspended, they disappear completely. But if they’re on a different PDS, they still exist, just not viewable via Bsky’s AppView, so they’ll probably still get counted?

Also, do other social networks remove spam accounts in MAU reports? From a corporate perspective, they likely don’t but what about from the Fediverse perspective?

Thanks for researching and discussing this topic. I, too, have been trying to understand the real trends behind AT Protocol usage.

A couple of other random thoughts.

  • There are also did:web DIDs (tho probably less than 1% of atproto)
  • As was mentioned above, some projects use DIDs that aren’t actual AT Protocol accounts
  • Even for valid accounts, (ie. PDS is valid and posts records), it’s hard to know what percent of them are bots used to scam.

I wish BSky PBC would publish DAU/MAU metrics based on their app analytics to give some context to all this public data. But, I think we are still in the vanity-metrics phase of network growth. If you look at the Daily Records of ( Atlas - Engagement-Based Social Graph for Bluesky by Jaz (jaz.bsky.social) ) the network has been mostly flat for almost a year. That story doesn’t interest investors and generate FOMO for people.