Bluesky Posts Scraper ๐ฆ Any Account, No Login
Pricing
from $1.43 / 1,000 post returneds
Bluesky Posts Scraper ๐ฆ Any Account, No Login
Scrape posts from any Bluesky account. Pass handles or profile URLs; get post text, like, repost and reply counts, author handle, timestamp and a direct post URL as JSON or CSV. No login and no app password. Since date filter makes scheduled monitoring cheap.
Pricing
from $1.43 / 1,000 post returneds
Rating
0.0
(0)
Developer
Yaniv van der Stigchel
Maintained by CommunityActor stats
1
Bookmarked
2
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Share
Bluesky Posts Scraper โ no login, no app password
Export posts from any Bluesky account. Text, likes, reposts, replies, quotes and timestamps. The AT Protocol network is public, so no authentication is required.
Scrape Bluesky posts in bulk
- Export Bluesky posts to JSON or CSV
- Download a Bluesky account's post history
- Track Bluesky engagement metrics over time
- Monitor Bluesky accounts for new posts
- Build a dataset from Bluesky
Pass several accounts at once. Accepts handles, DIDs, or bsky.app profile URLs.
Incremental mode
Set since to the date of your last run and scraping stops as soon as it
reaches older posts. Scheduled monitoring costs a fraction of a full history
pull.
What you get per post
Post text, author handle, DID and display name, like/repost/reply/quote counts,
creation and index timestamps, detected languages, the AT-URI, and a direct
bsky.app link.
Honest failure reporting
Accounts that do not exist return a row with reason: "account-not-found" and
cost you nothing. You are only charged for posts actually delivered.
Input
| Field | Required | Description |
|---|---|---|
actors | yes | Handles, DIDs, or profile URLs |
maxPostsPerActor | no | Newest first. Default 200. Your cost ceiling. |
since | no | ISO date. Only posts after it. |
Example input
{"actors": ["bsky.app", "@jay.bsky.team"],"maxPostsPerActor": 500,"since": "2026-08-01"}
Output
Every row has the same fields whether it succeeded or failed, so you can select columns without branching. Failed rows are never charged.
| Field | Type | Description |
|---|---|---|
success | boolean | True when this row carries data. Failed rows are never charged. |
sourceAccount | string | The account input this row came from. |
postUrl | string | Public bsky.app link to the post. |
postUri | string | The post's at:// record URI. |
authorHandle | string | Handle of the account that posted. |
authorDisplayName | string | Profile display name, if set. |
authorDid | string | Decentralised identifier, stable across handle changes. |
text | string | The post body. |
createdAt | string | ISO 8601 timestamp set by the author's client. |
indexedAt | string | ISO 8601 timestamp when the network indexed the post. |
languages | array | BCP-47 language codes declared on the post. |
likeCount | integer | Likes at the time of the run. |
repostCount | integer | Reposts at the time of the run. |
replyCount | integer | Replies at the time of the run. |
quoteCount | integer | Quote posts at the time of the run. |
errorCode | string | Machine-readable failure reason. Null on success. |
errorMessage | string | Human-readable explanation of the failure. Null on success. |
Example โ success
{"success": true,"sourceAccount": "bsky.app","postUrl": "https://bsky.app/profile/bsky.app/post/3k2aqvbhyq2b","postUri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3k2aqvbhyq2b","authorHandle": "bsky.app","authorDisplayName": "Bluesky","authorDid": "did:plc:z72i7hdynmk6r22z27h6tvur","text": "We just shipped a new way to browse feeds. Let us know what you think.","createdAt": "2026-08-14T09:12:04.221Z","indexedAt": "2026-08-14T09:12:05.884Z","languages": ["en"],"likeCount": 6042,"repostCount": 1180,"replyCount": 214,"quoteCount": 73,"errorCode": null,"errorMessage": null}
Example โ failure
A failure carries the same fields, so nothing downstream has to branch.
{"success": false,"sourceAccount": "not-a-real-handle.bsky.social","postUrl": null,"postUri": null,"authorHandle": null,"authorDisplayName": null,"authorDid": null,"text": null,"createdAt": null,"indexedAt": null,"languages": null,"likeCount": null,"repostCount": null,"replyCount": null,"quoteCount": null,"errorCode": "account-not-found","errorMessage": "No Bluesky account exists for this handle or DID, or the request was refused."}
Error codes
account-not-foundunparseable-actorno-posts-founderror
Use it for
- Bluesky account posts โ a profile's full public timeline
- Bluesky profile monitoring โ scheduled runs with a since filter
- AT Protocol (atproto) post data โ public records from any handle
- Social listening and brand tracking
- Research corpora and training datasets
Use it from an AI agent (MCP)
This Actor is callable as a tool through the Apify MCP server, so Claude, ChatGPT, Cursor and VS Code can run it directly.
Add the server to your MCP client:
{"mcpServers": {"apify": {"url": "https://mcp.apify.com","headers": {"Authorization": "Bearer <YOUR_APIFY_TOKEN>"}}}}
Then ask for what you want in plain language โ for example โget the recent posts from this Bluesky accountโ โ and the agent calls cleanfeed/bluesky-posts-extractor with the right input. Every output field is described in the dataset schema, so the agent knows what it is getting back before it runs anything.
Call it from code
Python
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("cleanfeed/bluesky-posts-extractor").call(run_input={"actors": ["bsky.app"],})for item in client.dataset(run["defaultDatasetId"]).iterate_items():if item["success"]:print(item)
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('cleanfeed/bluesky-posts-extractor').call({actors: ["bsky.app"],});const { items } = await client.dataset(run.defaultDatasetId).listItems();console.log(items.filter((i) => i.success));
cURL
curl -X POST "https://api.apify.com/v2/acts/cleanfeed~bluesky-posts-extractor/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \-H 'Content-Type: application/json' \-d '{"actors": ["bsky.app"]}'
Related actors
| If you need | Use |
|---|---|
| Posts from public Threads profiles | Threads Posts Scraper |
| Messages from public Telegram channels | Telegram Channel Scraper |
Limitations
- Public accounts only. Bluesky's public API is used, so no login and no app password are needed โ and nothing non-public is reachable.
- The feed is the author's timeline, which includes their reposts. Filter on
authorHandleif you want originals only. - Engagement counts are a snapshot at run time and will drift.
FAQ
Do I need a Bluesky account or app password?
No. Bluesky's public API is used, so there is no login and nothing to get rate-limited against your account.
What handle formats work?
A handle such as alice.bsky.social, a full did:plc:..., or a bsky.app/profile/... URL.
Can I fetch only new posts?
Yes โ set since to an ISO date and each run returns only posts after it, which keeps scheduled monitoring cheap.
Does this include reposts?
The author feed includes their reposts. Filter on authorHandle if you only want their own posts.
Can I read private accounts?
No. Only public posts are reachable, by design.
Notes
Only publicly available posts are collected, via the official public AT Protocol AppView. No login, no app password, no private data.