Logo

MonoCalc

/

Bluesky Profile Stats Viewer

Social Media
A handle can change. A DID cannot.
A handle is a rented display address — it is a domain name, and it can change. Someone can move from alice.bsky.social to alice.com tomorrow, and the old handle can later be taken by someone else. A DID is the account's permanent identifier: it never changes and is never reassigned. If you need to record who an account is, record the DID, not the handle.
All three work with the network switched off. None of them is a fallback for the others.
A handle such as alice.bsky.social or nytimes.com, a DID such as did:plc:…, or a pasted bsky.app profile link. Up to 400 characters.

Try one:

What this tool does not do

Counts are shown exactly as the response reported them. They are not graded, ranked or compared against other accounts, and no engagement rate, reach or growth figure is derived from them — the endpoint does not return those, and no amount of arithmetic invents data a source never sent.

One identifier at a time. There is no multi-handle box, no side-by-side comparison and no follower ranking.

The identifier breakdown is worked out in your browser from the text itself. No request is made to Bluesky and nothing you type or paste leaves the page.

About This Tool

Bluesky Profile Stats Viewer – read an identifier before you trust it

Every Bluesky account answers to two different names, and confusing them is the source of most of the mistakes people make when they write an account down. A handle like alice.bsky.social is a domain name. A DID like did:plc:z72i7hdynmk6r22z27h6tvur is the account itself. This tool takes whichever one you have, shows you exactly what it is made of, and renders the profile card that goes with it.

Why the distinction matters

A handle is rented, not owned. Whoever holds it can change it whenever they like — moving from a default *.bsky.social address to a custom domain is a normal thing to do — and once a handle is released, somebody else can register it. So a handle answers the question “what is this account called right now?” and nothing more. A DID is assigned once, never changes, and is never reassigned to a different account.

The rule worth remembering
If you are recording who an account is — in a spreadsheet, a citation, a block list, a moderation note — record the DID. A handle tells you only who was answering to that name on the day you wrote it down.

What the breakdown shows you

Paste an identifier and it is normalised first: a leading @ is stripped, a https://bsky.app/profile/ prefix is reduced to the segment after it, invisible characters that survived the copy are removed, and a handle is lower-cased because handles are case-insensitive. Each change is reported rather than done silently, so you can see what was altered.

A handle is then checked as a domain name, because that is what it is. It must contain at least one dot — there is no such thing as a bare alice. Each part between dots may be 1–63 characters of letters, digits and hyphens, and may not start or end with a hyphen. The whole name is capped at 253 characters, the standard DNS limit. The final part cannot be all digits, and reserved suffixes such as .local, .invalid and .internal are rejected because they never resolve on the public internet. Each label is drawn as its own chip so you can see where a long handle actually breaks.

A DID is split into its three pieces: the literal did prefix, the method, and the identifier. Bluesky uses did:plc: and did:web: in practice; anything else parses but carries a warning. The identifier is left exactly as you typed it, because a DID identifier is case-sensitive — lower-casing one the way you lower-case a handle produces a different identifier entirely.

Three ways in, all of them offline

The breakdown never needs a lookup, and neither do the other two modes. Manual entry lets you type a display name, bio and counts and get the same card. Paste JSON takes a getProfile response you obtained yourself and reads it defensively — every field optional, every type checked, unknown keys ignored, and a malformed paste reported with the line and column rather than a crash.

No live lookup ships here
Whether a browser may read the public AT Protocol endpoint from another site could not be verified when this tool was built, so no fetch button is shipped rather than one that might be blocked for everybody. The exact request address is printed for you to open yourself.

Counts are counts

Followers, following and posts are shown exactly as the response reported them, or as a dash when it carried no usable number. Nothing is graded, ranked or benchmarked against other accounts, and no engagement rate, reach or growth figure is derived from them — the endpoint does not return those, and arithmetic does not invent data a source never sent. A follower count is not a measure of anybody’s worth.

Everything renders as ordinary text, so a bio containing markup shows as literal characters rather than executing, and any avatar or banner address is checked against an https-only allowlist before it is allowed to become an image. Nothing you type or paste leaves the page.

Frequently Asked Questions

Is the Bluesky Profile Stats Viewer free?

Yes, Bluesky Profile Stats Viewer is totally free :)

Can I use the Bluesky Profile Stats Viewer offline?

Yes, you can install the webapp as PWA.

Is it safe to use Bluesky Profile Stats Viewer?

Yes, any data related to Bluesky Profile Stats Viewer only stored in your browser (if storage required). You can simply clear browser cache to clear all the stored data. We do not store any data on server.

How does this Bluesky profile stats viewer work?

Type a handle such as alice.bsky.social, a custom domain such as nytimes.com, a did:plc: identifier, or a pasted bsky.app/profile/ link, and it is taken apart in your browser. The tool strips a leading @ or a profile-link prefix, lower-cases the handle, splits it into its domain labels, and reports whether each part is a valid domain label — or, for a DID, splits it into the did prefix, the method and the identifier. That breakdown is the tool's real output and it needs no lookup, so it works with the network switched off. Fill in the counts by hand or paste a getProfile response and the same profile card renders from it.

What is the difference between a handle and a DID?

A handle is a domain name, and it is rented rather than owned outright. Its holder can change it — moving from alice.bsky.social to alice.com — and once a handle is released somebody else can take it. A DID is the account's permanent identifier: it is assigned once, it never changes, and it is never reassigned to a different account. If you are recording who an account is, in a spreadsheet, a block list or a citation, record the DID. A handle only tells you who was answering to that name at the moment you wrote it down.

Why does the tool ask me to paste JSON instead of fetching it?

MonoCalc is a static export with no server, no backend and no API keys, so any lookup would have to be a request your browser makes directly to Bluesky from another site. Whether a browser is permitted to read that endpoint cross-origin could not be verified when this tool was built, and a lookup button that turns out to be blocked fails for every visitor with nothing to show for it — a blocked request surfaces in JavaScript as an opaque error that cannot even be told apart from being offline. So the exact request address is printed instead: open it in a tab, copy the response, paste it back, and the card renders from it.

Why do the counts differ from what the Bluesky app shows?

Counts come from whatever response you pasted or typed, and that response is a snapshot from the moment it was produced. Follower and post counts move constantly, indexes lag behind writes, and a profile you fetched an hour ago will already disagree with the app. Nothing here is recomputed or smoothed — the figures are shown exactly as reported, or as a dash when the response carried no usable number.

Is anything I type or paste sent anywhere?

No. The identifier breakdown and the JSON reading both happen in the page itself, and nothing you enter is transmitted, logged or stored beyond the tab you are using. MonoCalc has no server to send it to. Display names and bios are rendered as ordinary text nodes so markup in them shows as literal characters, and any avatar or banner address found in a response is checked against an https-only allowlist before it is allowed to become an image.

Can it compare several accounts or rank them by followers?

No, and that is deliberate rather than unfinished. The tool reads one identifier at a time: there is no multi-handle box, no side-by-side comparison and no leaderboard. Counts are presented plainly, with no grade, benchmark or score attached, and no engagement rate, reach or growth figure is derived from them — the endpoint does not return those, and inventing them from a follower count would be making up data.