Bluesky Public API
Free Bluesky public API with no key: profiles, posts, followers and feeds from the AT Protocol network. No authentication for public data. Tested example.
Endpoint tested and returned HTTP 200 on 2026-08-19
What is the Bluesky Public API?
The Bluesky public API is a free, key-free interface to public AT Protocol data — user profiles, posts, follower counts and feeds — available without authentication through the public AppView endpoint.
Bluesky exposes public data through public.api.bsky.app with no authentication at all, which is unusual among modern social platforms. Profiles, post threads, follower lists and feeds are all readable anonymously.
Identity works differently here and is worth understanding: every account has a permanent DID (decentralised identifier) alongside its changeable handle. Store the DID, not the handle — users can change handles or move providers, and the DID is what stays stable.
Quick facts
- Base URL
https://public.api.bsky.app/xrpc- Authentication
- Public AppView endpoints need no auth. Posting and reading private data require an authenticated session.
- Rate limit
- Roughly 3,000 requests per 5 minutes per IP on the public AppView.
- Pricing
- Free and open protocol.
- CORS
- Enabled — callable directly from browser JavaScript
- Official docs
- Read the docs
How to use the Bluesky Public API
Every request below was executed against the live API on 2026-08-19, and the response shown is the real body it returned — not an illustration.
1. Fetch a public Bluesky profile
GET https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=bsky.app
curl 'https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=bsky.app'const res = await fetch("https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=bsky.app");
if (!res.ok) throw new Error(`Request failed: ${res.status}`);
const data = await res.json();
console.log(data);import requests
res = requests.get("https://public.api.bsky.app/xrpc/app.bsky.actor.getProfile?actor=bsky.app", timeout=20)
res.raise_for_status()
print(res.json()){
"did": "did:plc:z72i7hdynmk6r22z27h6tvur",
"handle": "bsky.app",
"displayName": "Bluesky",
"avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:z72i7hdynmk6r22z27h6tvur/bafkreihwihm6kpd6zuwhhlro75p5qks5qtrcu55jp3gddbfjsieiv7wuka",
"associated": {
"lists": 17,
"feedgens": 7,
"starterPacks": 14,
"labeler": false,
"chat": {
"allowIncoming": "none"
},
"activitySubscription": {
"allowSubscriptions": "followers"
}
},
"labels": [],
"createdAt": "2023-04-12T04:53:57.057Z",
"verification": {
"verifications": [],
"verifiedStatus": "none",
"trustedVerifierStatus": "valid"
},
"description": "official Bluesky account (check username👆)\n\nBugs, feature requests, feedback: support@bsky.app",
"indexedAt": "2025-10-27T21:05:26.152Z",
"banner": "https://cdn.bsky.app/img/banner/plain/did:plc:z72i7hdynmk6r22z27h6tvur/bafkreichzyovokfzmymz36p5jibbjrhsur6n7hjnzxrpbt5jaydp2szvna",
"followersCount": 34585239,
"followsCount": 11,
"postsCount": 808,
"pinnedPost": {
"cid": "bafyreicnt42y6vo6pfpvyro234ac4o6ijug6adwwrh7awflgrqlt4zibxq",
"uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l"
}
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
actor | string | Required | Handle or DID of the account. bsky.app |
app.bsky.actor.getProfile | path | Optional | Profile endpoint. app.bsky.actor.getProfile |
app.bsky.feed.getAuthorFeed | path | Optional | A user's posts. app.bsky.feed.getAuthorFeed |
limit | integer | Optional | Results per page on feed endpoints. 50 |
cursor | string | Optional | Pagination cursor from the previous response. abc123 |
Response fields
didstring- Permanent decentralised identifier — store this, not the handle.
handlestring- Current handle, which the user can change.
displayNamestring- Display name.
avatar / bannerstring- Profile image URLs.
followersCount / followsCount / postsCountinteger- Public engagement counts.
descriptionstring- Profile bio.
What you can build with the Bluesky Public API
- Display Bluesky follower counts or a post feed on a website
- Build a read-only Bluesky client or embed
- Monitor public posts mentioning a topic
- Analyse the AT Protocol social graph
Common errors and how to fix them
400 InvalidRequest
Missing the `actor` parameter or a malformed handle.
Fix: Pass a full handle including domain, e.g. bsky.app, or a DID.
Handle no longer resolves
The user changed their handle.
Fix: Store and query by DID, which never changes, rather than the handle.
429
Rate limit exceeded.
Fix: Public AppView allows roughly 3,000 requests per 5 minutes per IP; add caching.
Bluesky Public API — frequently asked questions
Does the Bluesky API need authentication?
Not for public data. The public AppView at public.api.bsky.app serves profiles, posts and feeds with no key. Posting or reading private data requires a session.
What is a DID and why does it matter?
A decentralised identifier — the account's permanent id. Handles can be changed by the user, so always store and query by DID for anything persistent.
Can I post to Bluesky through this API?
Not through the public endpoint. Writing requires creating an authenticated session against the user's PDS with an app password.
What is the AT Protocol?
The open protocol underlying Bluesky. It separates identity, data storage and the application view, which is why public reads can be served without any account.
Tools that pair with this API
JSON Formatter
Format, beautify and minify JSON online with 2-space, 4-space or tab indentation. Sort keys alphabetically and catch syntax errors instantly — free and private.
Word Counter
Count words, characters, sentences, paragraphs and estimated reading time instantly. Free online word counter for essays, blogs and social media.
Bluesky Public API is an independent third-party service and is not affiliated with ByteTools or ByteVancer. Details on this page were verified on 2026-08-19; always check the official documentation before relying on this API in production, as terms and limits can change.