TL;DR, Quick Answer
9 min readBluesky exposes no view count, no impression count and no analytics endpoint. The app.bsky.feed.defs#postView definition carries exactly five counters, likeCount, repostCount, replyCount, quoteCount and bookmarkCount, and none of the thirteen namespaces under app.bsky is an analytics namespace. The protocol does define an interactionSeen event, but it is write only and it goes to feed generators, not to the author of the post.
Does Bluesky have analytics?
Ask does Bluesky have analytics and the answer is no: the AT Protocol lexicons that define every Bluesky API response carry no view count, no impression count and no analytics endpoint. A post comes back with five engagement counters. A profile comes back with follower, following and post totals. Nothing anywhere tells you how many people saw the thing you published.
That is a claim about an absence, so here is exactly what was checked before making it, on 10 September 2026:
- Every lexicon file in
bluesky-social/atprotoon themainbranch, 404 JSON files in total. A case insensitive search across all of them returns zero occurrences ofimpression,viewCount,analyticandinsight. - The
postViewdefinition inlexicons/app/bsky/feed/defs.json, field by field. - The directory listing of
lexicons/app/bsky, to name every namespace that exists. - A live unauthenticated call to the public AppView, to confirm the running service returns what the schema says it returns.
The claim covers the first party lexicons and the public AppView. It says nothing about whatever internal dashboards Bluesky PBC runs for itself, and nothing about third party services that model reach from other signals.
What fields does app.bsky.feed.defs#postView actually carry?
Fifteen, and five of them are counters.
| Field | Type | What it gives you |
|---|---|---|
uri | string, at-uri | The post's address |
cid | string, cid | Content hash of this version of the record |
author | ref | app.bsky.actor.defs#profileViewBasic |
record | unknown | The post record itself, text and all |
embed | union | Images, video, external link or quoted record |
replyCount | integer | Replies |
repostCount | integer | Reposts |
likeCount | integer | Likes |
quoteCount | integer | Quote posts |
bookmarkCount | integer | Bookmarks |
indexedAt | string, datetime | When the AppView indexed the post, not when it was written |
viewer | ref | Your own relationship to the post, such as whether you liked it |
labels | array | Moderation labels attached to the post |
threadgate | ref | Reply restrictions on the thread |
debug | unknown | Described in the lexicon as "Debug information for internal development" |
Two details in that table are easy to miss. indexedAt is an indexing timestamp, so it is the wrong field to use as a publish time; the createdAt value inside record is the one you want. And the counters are not in the definition's required list, which reads ["uri", "cid", "author", "record", "indexedAt"]. A conforming response is allowed to omit likeCount entirely, so code that reads it should treat a missing value as unknown rather than as zero.
Here is the running service saying the same thing:
GET https://public.api.bsky.app/xrpc/app.bsky.feed.getAuthorFeed?actor=bsky.app&limit=1
"post": {
"uri": "at://...",
"cid": "...",
"author": { ... },
"record": { ... },
"embed": { ... },
"replyCount": 1,
"repostCount": 2,
"likeCount": 132,
"quoteCount": 3,
"bookmarkCount": 3,
"indexedAt": "...",
"labels": []
}Five keys ending in Count. No sixth.
Is there an analytics namespace under app.bsky?
No. Thirteen namespaces sit under app.bsky, and every one of them has a job that is not measurement.
| Namespace | What it covers |
|---|---|
app.bsky.actor | Profiles, preferences, actor search |
app.bsky.ageassurance | Age verification state |
app.bsky.bookmark | Creating, deleting and listing bookmarks |
app.bsky.contact | Contact import, phone verification, match dismissal |
app.bsky.draft | Server stored drafts |
app.bsky.embed | Image, video, external and record embed shapes |
app.bsky.feed | Posts, likes, reposts, quotes, threads, feed generators |
app.bsky.graph | Follows, blocks, mutes, lists, starter packs |
app.bsky.labeler | Labeling services |
app.bsky.notification | Notification list, unread count, push registration |
app.bsky.richtext | Text facets such as links and mentions |
app.bsky.unspecced | Unstable endpoints the official client uses |
app.bsky.video | Video upload and job status |
Widen the search past app.bsky and the picture holds. The repository's other roots are com.atproto for protocol plumbing, chat.bsky for direct messages, tools.ozone for moderation, plus internal.bsky, site.standard and com.germnetwork. The only endpoints in the entire set with a statistical flavour are tools.ozone.report.getLiveStats, tools.ozone.report.getHistoricalStats, tools.ozone.report.refreshStats and tools.ozone.moderation.getReporterStats. Those report on moderation queues for moderators. getLiveStats is documented as "Get live report statistics from the past 24 hours. Filter by queue, moderator, or report type." None of it touches post performance.
Why does the protocol define a seen event but never report it?
Because the seen event flows to feed generators, not to authors. This is the part worth quoting when someone insists the data must be in there somewhere.
app.bsky.feed.sendInteractions is a procedure whose input is an array of app.bsky.feed.defs#interaction objects. Each interaction names an item by AT URI and an event token. The known values include:
| Token | Lexicon description |
|---|---|
app.bsky.feed.defs#interactionSeen | "Feed item was seen by user" |
app.bsky.feed.defs#clickthroughItem | "User clicked through to the feed item" |
app.bsky.feed.defs#clickthroughAuthor | "User clicked through to the author of the feed item" |
app.bsky.feed.defs#interactionLike | "User liked the feed item" |
app.bsky.feed.defs#requestLess | "Request that less content like the given feed item be shown in the feed" |
So the vocabulary for an impression exists. interactionSeen is, in plain terms, a view event. What is missing is a read path. The procedure's own description says it sends information "back to the feed generator that served them", and its output schema is an empty object, {"type": "object", "properties": {}}. A feed operator who runs a custom feed can count seen events for items their feed served. You, as the author of a post, have no endpoint that returns how many times your post was seen, in that feed or any other.
That asymmetry is the honest answer to why Bluesky feels like it should have view counts. The signal is defined, collected by clients and delivered to feed generators. It stops there.

What can you measure on Bluesky today?
Plenty, as long as you stop looking for reach.
AdaptlyPost
Start Your 7-Day Free Trial
All-platform analytics
Social Inbox
AI-powered assistant
| Question | Endpoint | Available |
|---|---|---|
| How many likes, reposts, replies, quotes, bookmarks? | app.bsky.feed.getPosts or app.bsky.feed.getAuthorFeed | Yes |
| Which accounts liked this post? | app.bsky.feed.getLikes | Yes |
| Which accounts reposted it? | app.bsky.feed.getRepostedBy | Yes |
| Which accounts quoted it? | app.bsky.feed.getQuotes | Yes |
| How many followers and posts does this account have? | app.bsky.actor.getProfile | Yes, as followersCount, followsCount, postsCount |
| How many people saw the post? | none | No |
| What was the impression to engagement rate? | none | No |
The named account lists deserve more attention than they get. On most networks you receive a like total and nothing else. Bluesky hands you the accounts, which means you can ask who your reposts come from, whether the same twenty handles carry every launch, and which followers have never once engaged. That is a different kind of analysis from impressions, and on some questions it is a better one.
app.bsky.feed.getPosts takes a uris array with a maxLength of 25, so a batch job checking a month of posts pages through in chunks of 25. app.bsky.feed.getAuthorFeed takes limit with a maximum of 100 and a default of 50, plus a cursor, and it is documented as "Does not require auth", which is why the example above runs against public.api.bsky.app with no token.

What can a Bluesky analytics tool honestly give you?
Two things, and it should be clear about which is which.
The first is its own publishing record. A scheduler knows what it sent, from which account, at what minute, with what text, hashtags and media, because it did the sending. No API grants that; it is first party data the tool already holds. It is also the half most people are missing, because a spreadsheet of send times is what turns a pile of counters into a comparison.
The second is the public counters, sampled over time. Calling getAuthorFeed or getPosts on a schedule and storing likeCount, repostCount, replyCount, quoteCount and bookmarkCount at each pass turns one number into a curve, which shows how long a post kept collecting engagement after it went out.
Join those two and you can answer real questions: which of your Bluesky posts earned engagement, published at what hour, in what format, next to the same posts on the other networks in your calendar. That join is what AdaptlyPost's Bluesky analytics reports, and the same shape of report covers the other networks through social media analytics.
What no tool can give you, this one included, is impressions, reach, video views or profile visits for a Bluesky post. Those numbers are not in the API, so a dashboard displaying them is either modelling them or relabelling something else. The useful question to ask any vendor is which field the number came from. If the answer is not one of the five counters or a follower total, the number is an estimate.
Scheduling changes none of this either. Publishing through a Bluesky post scheduler gives you a clean send log to measure against; it does not give Bluesky a view counter it does not have.
What this page does not claim
It does not claim Bluesky will never ship view counts. The field list grows: bookmarkCount sits alongside the four older counters, and app.bsky.bookmark is a full namespace with its own create, delete and list endpoints. If a viewCount ever lands, it will appear in lexicons/app/bsky/feed/defs.json before it appears in any client, and that file is public. Check it there rather than trusting a screenshot.
Frequently Asked Questions
Does the Bluesky app show a view count anywhere?
No. The official client renders the same counters the API returns, which are likes, reposts, replies, quotes and bookmarks. There is no view or impression figure on a post, on a profile or in any settings screen, because no endpoint supplies one.
Is there an analytics endpoint anywhere in the AT Protocol lexicons?
No. A search across all 404 lexicon files in bluesky-social/atproto returns no file or field named for analytics, insights or impressions. The four endpoints containing "Stats" all live under tools.ozone, the moderation tooling namespace, and they report on moderation reports rather than on posts.
Can a tool estimate Bluesky impressions from the firehose?
Not measure, only model. The com.atproto.sync firehose streams repository commits, so a consumer sees the creation of app.bsky.feed.like and app.bsky.feed.repost records as they happen. Viewing a post creates no record, which means nothing crosses the firehose when someone reads and scrolls past. Any impression figure derived from it is a model output.
Does app.bsky.feed.sendInteractions let me see who saw my post?
No. It is a procedure, not a query. Clients push interaction events into it, including interactionSeen, and its output schema is an empty object. The events are delivered to the feed generator that served the item, so there is no route back to the author of the post.
Are the engagement counts always present in an API response?
No. The required list on app.bsky.feed.defs#postView is ["uri", "cid", "author", "record", "indexedAt"], which leaves every counter optional. Treat an absent likeCount as an unknown value rather than defaulting it to zero, or a service outage will look like a post that nobody liked.
AdaptlyPost
Start Your 7-Day Free Trial
All-platform analytics
Social Inbox
AI-powered assistant
How many posts can I check for counts in one call?
Twenty five with app.bsky.feed.getPosts, which caps its uris array at maxLength: 25. app.bsky.feed.getAuthorFeed returns up to 100 posts per page with a cursor for the next page, and it needs no authentication, so it is the cheaper route when you want a whole account's recent history.
Does Bluesky's bookmarkCount mean more metrics are coming?
bookmarkCount is the newest of the five counters, added alongside likeCount, repostCount, replyCount and quoteCount, and app.bsky.bookmark already has its own full namespace with create, delete and list endpoints. A viewCount could follow the same path. If it ships, it will show up in lexicons/app/bsky/feed/defs.json before it reaches any client, so that file is the place to check rather than a screenshot.
Do the tools.ozone stats endpoints count as Bluesky post analytics?
Not for posts. The four stats endpoints in the repository, getLiveStats, getHistoricalStats, refreshStats and getReporterStats, all live under tools.ozone, the moderation namespace, and they report on moderation queues and reporters for moderators. None of them touches replies, likes or reach on a post.
Do I need to log in to check a Bluesky post's engagement numbers?
Public counters don't require a login. app.bsky.feed.getAuthorFeed is documented as not requiring auth, which is why a call to public.api.bsky.app with no token returns the same likeCount, repostCount, replyCount, quoteCount and bookmarkCount fields shown in this post. Anything gated behind your own account, such as notification settings, is a different matter, but reading another account's public counters needs nothing more than the URL.
Should I trust a Bluesky dashboard that shows impressions or reach?
Treat it with suspicion if the vendor can't name the field. Impressions, reach, video views and profile visits sit outside the AT Protocol lexicons entirely, so a dashboard showing them is either modelling the number from other signals or relabelling one of the five real counters. Ask which field the number came from; if the answer isn't likeCount, repostCount, replyCount, quoteCount, bookmarkCount or a follower total, it's an estimate.
Put this into practice with AdaptlyPost
Was This Article Helpful?
Let us know what you think!
See us more often in Google
One click marks AdaptlyPost as a preferred source, so our articles sit higher in your Top Stories, AI Mode, and AI Overviews.
Before you go...
AdaptlyPost
Schedule your content across all platforms
Manage all your social media accounts in one place with AdaptlyPost.
All-platform analytics
Social Inbox
AI-powered assistant
Related Glossary Terms


How to Post a Bluesky GIF That Keeps Moving
How a Bluesky GIF reaches a post: the KLIPY picker, uploads the app turns into video, image embeds that show one frame, and what AdaptlyPost sends.


How a Bluesky Feed Generator Works, From Lexicon to Live Feed
A Bluesky feed generator is one HTTPS service answering one XRPC query. The lexicons, the DID document entry, the JWT, and the gaps in the docs.


Why Bluesky Facets byteStart byteEnd Count Bytes, Not Characters
Bluesky facets byteStart byteEnd offsets count UTF-8 bytes, not JavaScript UTF-16 indexes. The lexicon warning, a worked example, and code that gets it right.
Related Articles


How a Bluesky threadgate Decides Who Can Reply to a Post
A Bluesky threadgate limits replies to mentioned users, followers, people you follow or a list. How the record works, and the postgate that stops quotes.


Why the Bluesky Image Size Limit Is 2,000,000 Bytes
The Bluesky image size limit is 2,000,000 bytes per post image, set by maxSize in the images lexicon. Avatars and banners stop at 1,000,000 bytes.


Where l.facebook.com Comes From and Why Clicks Land as Direct
Facebook routes outbound clicks through l.facebook.com, its link shim. Here is what the hop does to your referrer and why a visit can land as direct.

