Most of what I write about this category is about platforms that don't want to answer. Bluesky and Mastodon are the opposite: both expose a genuine public API, no key, no account, no TLS impersonation, no reading state out of a rendered page.
They are the two easiest platforms I cover, and the ones whose traps are least documented — precisely because nobody expects difficulty from something that works on the first try.
Everything below was measured against the live APIs between 10 and 15 September 2026. If you are building on this, verify before you rely on it.
The easy part
Bluesky. A public profile comes from the AT Protocol's own app view. No authentication. 634 bytes on the wire in the sample I measured — among the smallest responses of any platform I cover, alongside GitHub and Mastodon. Posts come from app.bsky.feed.getAuthorFeed, also public.
Mastodon. A public profile comes from the account's own instance, via the protocol's documented API. No authentication. 932 bytes.
For scale: a Threads profile crosses the wire at about 153 KB, and it has to be extracted from a rendered page. Bluesky's is 240 times smaller and arrives as the object you asked for. I measured all eight platforms here.
If your project only needs these two, you do not need a provider. You need an afternoon. What follows is what that afternoon will teach you the hard way.
Mastodon is federated, and the handle is the proof
This is the one that breaks naive implementations immediately, and it is not a quirk — it is the architecture.
There is no such thing as a Mastodon username. A handle is always user@instance. Two different people can hold the same local name on two different servers, and both are correct. If your input field accepts @alice and your code tries to resolve it, there is no correct answer to give back — so the only honest behaviour is to reject it. I return 400, not a guess.
Ask the origin instance. Any server that has federated the account holds a copy of it, and copies go stale. The account's own instance is authoritative. Route the request there.
The numeric id is local. The same person has a different numeric id on every server that has ever seen them. If you store that id as your key, you have stored a fact about one server's database, not about the person. The stable identifier is the ActivityPub URI, and that is what I return in the envelope.
verified is not what it looks like. Mastodon verifies links — you prove you control a website by putting a tag on it. It does not verify identity. There is no "this is the real person" badge to read. I return null rather than promote link verification into an identity claim.
Boosts are most of the feed
Pull a Mastodon account's recent posts without filtering and 15 out of every 20 items are boosts — other people's posts, repeated by this account.
Filtering them is obvious once you see the number. What isn't obvious is the failure when you don't: the outer object of a boost arrives with empty text and zeroed metrics. So an unfiltered pipeline doesn't fill up with other people's content, which you'd notice. It fills up with blank rows showing zero engagement, attributed to the account you were measuring. Average engagement per post collapses and nothing anywhere reports an error.
Bluesky has the same structure at about 1 in 20, which is arguably the more dangerous rate. A bug affecting three quarters of your rows gets found. A bug affecting five percent looks like a slow week.
One distinction worth getting right on both: a reply the account wrote is their post and should stay. A boost or repost of someone else's post is not. Filter by authorship, not by post type.
The limit parameter, and why I reject values the source accepts
Bluesky's author feed takes limit from 1 to 100, default 25. Mastodon's takes 1 to 40, default 20.
Here's the part that decides a design question. Ask Mastodon for 100 and it does not error. It silently gives you 40.
That is a reasonable thing for a server to do and a terrible thing to pass through. A caller who asks for 100, receives 40, and gets a 200 will conclude the account has 40 posts. They have no way to tell the difference between "this account posted 40 times" and "your request was quietly trimmed."
So I return 400 for out-of-range values instead of clamping them. The caller finds out at the moment they are wrong, not three weeks later in a report. If you're building this yourself, I'd argue for the same choice — but whichever you pick, pick it deliberately, and write it down where your users will see it.
Related, and easy to miss: cache by endpoint and parameters. A response for limit=25 is not a valid answer to limit=50. Each limit needs its own cache line.
The XSS one
This is the item on the page I'd most want someone to read before shipping.
Mastodon returns post bodies as HTML, authored by a third party on a server you do not control. It is an open federated network: anyone can stand up an instance and post anything into it, including markup crafted for whoever consumes it downstream.
If you take that HTML and put it into your page, you have handed an arbitrary stranger a script tag in your application.
I return two fields: text, already stripped of HTML and safe to render as text, and text_html, the original. The second one exists because formatting is sometimes what you need — but it must be sanitized before it reaches a DOM. That is not a hardening suggestion. Skipping it is the vulnerability.
Any provider handing you Mastodon post bodies should tell you which of those two you're holding. If the documentation doesn't say, assume it's the dangerous one.
What these APIs do not give you
Worth stating, because "public API" gets read as "complete":
- Bluesky publishes a bookmark count (
bookmarkCount) that no other platform has. I don't return it — a field that exists on exactly one platform can't be part of a shared shape without lying about the others by omission. - Bluesky post thumbnails I don't return either, for a duller reason: the image embed hasn't been measured across enough samples for me to promise its structure.
- Mastodon posts have no title. A status is a status.
titleisnull, always. - Neither has a ranking. Chronological order is not a rank, so
positionisnullon both.
The honest recommendation
If Bluesky and Mastodon are all you need: build it yourself. Two public APIs, no keys, no anti-bot layer, no cost beyond the bandwidth. Take the six traps above with you and you'll have working code today. I'd rather you did that than paid me for something you can do in an afternoon.
What I'm actually selling is the other eight platforms — the ones with no public API, where the work is TLS fingerprinting, picking the right field out of forty-two candidates, and re-doing it when the front end ships. Bluesky and Mastodon come along in the same response shape because consistency is the product, not because they're hard.
HonestHook covers ten platforms. Both of these cost 1 credit, same as the rest. Every key gets 1,000 credits a month free, no card. Prices are here.
Measured against the live AT Protocol and Mastodon APIs between 10 and 15 September 2026, one to three accounts per platform. Response sizes are on-the-wire bytes.