Bluesky Social Scraper avatar

Bluesky Social Scraper

Pricing

from $2.10 / 1,000 results

Go to Apify Store
Bluesky Social Scraper

Bluesky Social Scraper

Profiles, posts, followers, follows, user search and full reply threads from Bluesky, via the public AT Protocol AppView API. No login, no API key, cursor pagination followed to the end.

Pricing

from $2.10 / 1,000 results

Rating

0.0

(0)

Developer

Ibnu Adzim

Ibnu Adzim

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Categories

Share

Profiles, posts, followers, follows, user search and full reply threads from Bluesky — through the public AT Protocol AppView API.

No login, no API key, no OAuth, no rate-limit token. Cursor pagination is followed to the end unless you cap it.

Modes

ModeReadsReturns
profilesactorsfull profile records, 25 per request
authorFeedactorsa user's posts, paginated
followersactorsaccounts following a user
followsactorsaccounts a user follows
searchActorsqueryuser search results
threadpostUrisa post plus every reply, flattened with depth

Post search is not offered — see the first known limit below.

Input

actors accepts whatever you have to hand — all three of these are the same account:

{ "mode": "profiles",
"actors": ["@bsky.app", "did:plc:z72i7hdynmk6r22z27h6tvur",
"https://bsky.app/profile/bsky.app"] }

postUris accepts an at:// URI or a bsky.app post URL; when the URL carries a handle instead of a DID, the DID is resolved for you first.

{ "mode": "thread",
"postUris": ["https://bsky.app/profile/alice.bsky.social/post/3labc123xyz"] }

What you get

Three record types share one dataset, told apart by recordType:

  • QUERY_SUMMARY — one per input: the XRPC method called, pages fetched, rows returned, whether a cap bound, and which actors upstream silently dropped.
  • PROFILE / POST — one per row, upstream's object passed through verbatim (handle, displayName, followersCount, record, likeCount, embed, …) plus the envelope fields.
  • ERROR — one per input that failed or was silently dropped, so every input maps to at least one row.

Thread rows additionally carry threadDepth and parentUri, so the reply tree is reconstructable from the flat dataset. A 234-reply thread came back as 280 posts across 7 depth levels in testing.

Known limits — read these before you rely on the output

Post search is not available and this actor does not pretend otherwise. app.bsky.feed.searchPosts returns 403 with an HTML body to unauthenticated callers. It was measured from three exits on three continents — Indonesia, Brazil and the United States, via three different CDN edges — and blocked in all three, while every other method on the same host answered normally in the same session. So it is not geo-gating and pinning a proxy country does not help. The mode is therefore absent from the mode list rather than offered and broken. Use searchActors for user search (unaffected), or authorFeed to read a known account's posts. An API caller that passes searchPosts explicitly still gets an ERROR row explaining this rather than a silent empty run.

profiles mode: upstream silently drops actors it cannot resolve. getProfiles answers HTTP 200 with fewer profiles than you asked for and no error field — measured: 4 requested, 2 returned, response body containing only profiles. (The single-actor endpoint answers 400 Profile not found for the same input, so the batch endpoint is strictly less honest.) This actor diffs requested against returned and emits an actor_not_returned ERROR row per dropped actor, and lists them in the summary's actorsSilentlyDropped.

Follower lists can be enormous. bsky.app alone has ~34.8M followers. followers mode without maxItems will page until it finishes. Set a cap.

pageLimit above 100 is refused up front. Upstream's ceiling is 100 — 101 returns 400 integer too big, 0 returns 400 integer too small.

Post records are not rendered. record.text is the raw post text and embed/facets are passed through as upstream sends them; links, mentions and rich text are yours to resolve.

Technical

Public AppView (public.api.bsky.app/xrpc/), HTTP only, no browser. No WAF on the methods used: 4/4 TLS profiles identical. bsky.social is the PDS and answers 401 AuthMissing for these methods — it is a different role, not a fallback.

robots.txt checked on both public.api.bsky.app and bsky.app: no ClaudeBot/anthropic-ai group and no blanket disallow on either.

Full recon trail, including how each ceiling was bisected, is in CRAWLING_METHOD.md.