Bluesky Scraper - Posts, Threads, Likes & Profiles
Pricing
from $0.46 / 1,000 posts
Bluesky Scraper - Posts, Threads, Likes & Profiles
Bluesky scraper: extract public posts from author feeds and threads, with text, date, likes, reposts, replies, quotes, hashtags, mentions, links and images. Optional author profiles. Public AT Protocol API, no login, flat JSON.
Pricing
from $0.46 / 1,000 posts
Rating
0.0
(0)
Developer
CrawlKit
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Security
Limited permissionsShare
Extract public Bluesky posts as flat JSON rows: from the feeds of the accounts you choose, from threads (a post with its replies), or from a one-page search. Each row has the post text, date, like, repost, reply and quote counts, hashtags, mentions, links, images and reply references. Author profiles are optional.
What it does
- Author feeds: give handles (
bsky.app,@jay.bsky.team), profile URLs or DIDs. The Actor follows the feed's pagination cursor untilmaxItemsposts per account or the end of the feed. Replies by the author are left out unlessincludeRepliesis on; reposts are kept and flagged (isRepost,repostedBy) unlessincludeRepostsis off. - Threads: give post URLs (
https://bsky.app/profile/<handle>/post/<id>). The Actor returns the post, the posts above it in the thread (root first) and its replies, up tomaxItemsrows per thread. - Search: give a
searchQuery. Bluesky serves only the first page of search results without login, so the search returns at most 25 posts (see Limitations). - Profiles (optional): with
includeProfiles, one extra row per handle with followers, follows, post count, bio, avatar and creation date. - A post is returned once per run, even if several inputs lead to it. An invalid handle or URL is skipped and named in the run's status message; the run fails with an explicit message only when no post at all could be returned.
- Uses the public Bluesky AppView API of the AT Protocol (
public.api.bsky.app,api.bsky.appfor search). No login, no API key, no browser, no proxy. Requests are sent one at a time; on HTTP 429 the Actor waits for the time the API asks for.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
handles | array of strings | One of the three sources | — | Handles, profile URLs or DIDs. A name without a dot gets .bsky.social appended |
postUrls | array of strings | One of the three sources | — | Post URLs or at:// URIs; each one gives its thread |
searchQuery | string | One of the three sources | — | Full-text search, first page only (25 posts at most) |
includeReplies | boolean | No | false | Author feeds: also return the author's replies to other posts |
includeReposts | boolean | No | true | Author feeds: also return posts the author reposted |
includeProfiles | boolean | No | false | Also return one profile row per handle |
maxItems | integer | No | 50 | Maximum posts per handle, per thread and for the search |
Example:
{"handles": ["bsky.app", "https://bsky.app/profile/pfrazee.com"],"postUrls": ["https://bsky.app/profile/bsky.app/post/3mz4cvpstb22v"],"includeProfiles": true,"maxItems": 100}
Output
One dataset row per post ("type": "post"). Real example (feed of bsky.app, run of 2 November 2026; this row is a repost by bsky.app of a post by avclub.com):
{"type": "post","uri": "at://did:plc:kwxpje5qog6wwndagwbssatp/app.bsky.feed.post/3mviutosqmk2t","url": "https://bsky.app/profile/avclub.com/post/3mviutosqmk2t","cid": "bafyreigyzxfb3tynf6hus4cshhzcrwr7sht4vfp2l5phbbfephvn7bcd7a","authorHandle": "avclub.com","authorDisplayName": "The A.V. Club","authorDid": "did:plc:kwxpje5qog6wwndagwbssatp","text": "Less than 4 hours until the #Emmys kick off! You can keep up with all the commentary, winners, joy—and, let's face it, disappointment—via our Emmys Watch feed right here on @bsky.app. Pin it now so you don't miss a thing!\n\nbsky.app/profile/avcl...","createdAt": "2026-09-14T19:47:12.655Z","indexedAt": "2026-09-14T19:47:15.764Z","likeCount": 546,"repostCount": 42,"replyCount": 31,"quoteCount": 4,"langs": ["en"],"replyParent": null,"replyRoot": null,"hashtags": ["Emmys"],"mentions": ["bsky.app"],"links": ["https://bsky.app/profile/avclub.com/feed/emmys-watch-r"],"embedType": "images","images": [{"url": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:kwxpje5qog6wwndagwbssatp/bafkreicwxzp6lnqvuetiytyeanq3wynihsneq4qqdvv7bzhkrmw4nv36oy","alt": null}],"videoUrl": null,"externalUrl": null,"externalTitle": null,"quotedPostUri": null,"isRepost": true,"repostedBy": "bsky.app","source": "author:bsky.app","scrapedAt": "2026-11-02T22:24:50+00:00"}
| Field | Notes |
|---|---|
uri, cid | AT Protocol identifiers of the post; url is the same post on bsky.app |
createdAt | Time set by the author's app; indexedAt is when Bluesky indexed the post |
hashtags, mentions, links | From the post's rich-text facets; links also contains the link card URL. Shortened links in text (bsky.app/profile/avcl...) are shown in full in links |
embedType | images, video, external (link card), record (quote), recordWithMedia (quote with media), gallery, or null |
images | Full-size image URLs and alt texts (null when the author wrote none) |
videoUrl | HLS playlist (.m3u8) of an attached video |
quotedPostUri | at:// URI of the quoted post |
replyParent, replyRoot | at:// URIs of the post replied to and of the first post of the thread; null for top-level posts |
isRepost, repostedBy | Set when the row comes from a repost in an author feed; the author fields are those of the original post |
source | Input that produced the row: author:<handle>, thread:<url> or search:<query> |
Profile rows ("type": "profile", only with includeProfiles) contain did, handle, url, displayName, description, followersCount, followsCount, postsCount, avatar, banner, createdAt, indexedAt and scrapedAt.
The dataset has two views: posts and profiles.
Pricing
Pay-per-event, no start fee: $0.77 per 1,000 posts (event POST) on the Apify Free plan, lower on paid plans. You only pay for results pushed to the dataset.
| Apify plan | Price per 1,000 posts |
|---|---|
| Free | $0.77 |
| Starter | $0.65 |
| Scale | $0.58 |
| Business | $0.46 |
- Additional event
PROFILE(profile): $0.77 per 1,000 on the Free plan, $0.46 on Business. Charged only when that data is returned.
Set a maximum cost per run in the run options: the Actor stops cleanly when it is reached.
Limitations
- Search returns at most 25 posts per run. Without login, Bluesky's search API serves the first page of results and refuses the next pages (HTTP 403). The Actor does not log in and does not split the search into date ranges to get around this. For more posts, scrape the authors' feeds or the threads.
- Only public posts that the Bluesky AppView serves without login. Deleted posts and posts the AppView does not serve (blocked or removed by moderation) are not returned.
- A thread is read in one request. For very large threads the AppView may not return every reply, and
maxItemscaps the rows per thread. - Counts (likes, reposts, replies, quotes, followers) are those of the moment of the run.
langsis what the author's app declared, and can be empty.- Likes, followers lists and direct messages are not included.
Related Actors
- Reddit Scraper API - Subreddit Posts & Comments, No Login — Scrape Reddit posts and comments from any subreddit: title, text, date, link and author. Reddit data API alternative for social listening, no login.
- Telegram Channel Scraper API - Messages & Views, No Login — Scrape public Telegram channel messages: text, dates, views, media and links. Telegram data API with no account, phone number or any API key needed.
- Substack Scraper - Newsletter Posts, Authors and Engagement — Substack scraper and API alternative: newsletter posts from any Substack publication or custom domain, or find publications by keyword, with title, authors, date, free or paid audience, word count, likes, comments, restacks, tags and optional full text of free posts.