How we count

Every number on this site comes from public AT Protocol data, produced by open scripts you can read and run. This page explains what each number means and how we build it, and links to the exact code. The data was last generated on 2026-10-23.

Three numbers, most certain first

The site leads with three figures, in order of how much we can stand behind them. Identified is the accounts we can place in a country from a deliberate signal, each counted once. Active is how many of those posted, replied or reposted recently. Estimate is a modelled total that tries to include the people we cannot see, and is our least certain number. You can read all three, per country, on the statistics page.

Identified: accounts we can place

AT Protocol has no country field. An account carries no location, so we place one only when it leaves a deliberate trace we can read. In order of strength, those signals are: a location you set on your Sifa ID profile, a country domain in your handle or a company's country domain, a membership or community-verifier record, and a place in a curated starter pack.

One account, one country. Each is counted once under its strongest signal, and where signals disagree we place it nowhere rather than guess. Language is never a signal: most European languages cross borders, so posting in German says nothing about living in Germany.

A few country domains (.at, .es, .is, .it, .se) are also common English word-play, so we count one only when the account is active, and never treat it as confirmed. A content check then removes the ones that clearly belong to another country. The code is in attribution.py (the precedence) and eu-stats-aggregate.py (the counting).

Active: who is still here

We call an account active when it has authored (post/reply/repost) in the last 90 days. Reading leaves no public trace on AT Protocol, so this counts only what people post, and the real number is higher: an account that only reads looks the same to us as one that has gone quiet.

The code is in eu-activity-scan.py.

Estimate: modelling the rest

The identified count is a floor. To reach a real total we model the people who never leave a trace, the same way atproto.nl does for the Netherlands. The model is

K * Σ_lang authors(lang) * speakerWeight(cc|lang)

calibrated so the Dutch figure matches atproto.nl's own model (about 230K). Every other country is expressed in those same units. GB and IE are left out of the estimate: their communities are English-first, and English is spoken everywhere, so it cannot be weighted to a single country.

Language feeds only this estimate, and never places an account in a country on its own. This is the least certain number on the site. The code is in eu-estimate.py, and the Dutch community-size page walks through the full derivation step by step.

European infrastructure

Some accounts we cannot place in a country, but we can see they run on European infrastructure: a personal data server (the host that stores an account's records) based in Europe. We count these separately and never fold them into a country total. The hosts we track:

The code is in eu-infra-pds.py.

Read it, run it

The scripts read the public Jetstream firehose, the PLC directory and the Bluesky AppView. They need no login and print the raw numbers, so anyone can check them. Everything lives in the repository on Tangled.

This page reads the same generated data as the rest of the site, so it stays in step with the numbers and the scripts on every run. The data shown here was last generated on 2026-10-23.