Bluesky Scraper: Posts, Followers & Engagement Tracker
Pricing
Pay per event
Bluesky Scraper: Posts, Followers & Engagement Tracker
Get Bluesky profiles and recent posts with likes, reposts, replies and quotes, plus follower changes, new posts and engagement gained since your last run. No login; $0.50 per 1,000 posts plus $0.002 per profile.
Pricing
Pay per event
Rating
0.0
(0)
Developer
Changefeeds Tools
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
- What you get: for each Bluesky account, a profile row (followers, following, posts) and its recent posts with likes, reposts, replies, quotes, links, hashtags and mentions.
- Compared with your last run: follower and following changes, which posts are new, and how much engagement each earlier post gained since you last looked. Built for competitor, creator and brand tracking. No Bluesky login.
- Price: $0.50 per 1,000 posts plus $0.002 per profile. Handles that are not found or fail to load are free.
Sample output
Changes. We ran this actor on bsky.app and jay.bsky.team on 2026-09-29
and again on 2026-10-23 (50 posts each). The second run's profile rows:
| handle | followers | followers_delta | follows_delta | posts_count_delta | new_posts_found |
|---|---|---|---|---|---|
| bsky.app | 35,348,998 | +266,114 | +8 | +31 | 13 |
| jay.bsky.team | 594,468 | −118 | +8 | +13 | 3 |
And the posts that gained the most engagement between the two runs:
| handle | posted | text (start) | likes | like_delta | engagement_delta |
|---|---|---|---|---|---|
| bsky.app | 2026-09-21 | If you're in line to vote for @bsky38.com, please stay in line! | 820 | +68 | +83 |
| bsky.app | 2026-09-09 | Not to brag, but ... we snagged a couple of passes to today’s Apple event | 2,361 | +35 | +43 |
| jay.bsky.team | 2026-09-19 | good dogs | 693 | +25 | +29 |
The top post row in full:
{"type": "post","profile_did": "did:plc:z72i7hdynmk6r22z27h6tvur","profile_handle": "bsky.app","uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3mw2cdr44fc2a","cid": "bafyreicrjbyelww7gvuymagi7g2rirokyrvedwzeh5vflmsvnwhnwjvnyi","url": "https://bsky.app/profile/bsky.app/post/3mw2cdr44fc2a","author_did": "did:plc:z72i7hdynmk6r22z27h6tvur","author_handle": "bsky.app","text": "If you're in line to vote for @bsky38.com, please stay in line! Polls close in just under 5 hours.","created_at": "2026-09-21T18:04:06.128Z","indexed_at": "2026-09-21T18:04:06.866Z","like_count": 820,"repost_count": 105,"reply_count": 103,"quote_count": 47,"bookmark_count": 41,"engagement": 1075,"embed_type": "record","links": [],"hashtags": [],"mentions": [{ "did": "did:web:bsky38.com", "handle": "bsky38.com" }],"language": "en","languages": ["en"],"is_reply": false,"reply_parent_uri": null,"reply_root_uri": null,"is_repost": false,"reposted_at": null,"is_new": false,"previous_seen_at": "2026-09-29T08:35:00.772Z","like_delta": 68,"repost_delta": 12,"reply_delta": 3,"quote_delta": 0,"engagement_delta": 83,"checked_at": "2026-10-23T03:50:08.281Z"}
Your first run is a baseline. It returns the same profile and post rows
with is_baseline: true on profiles, is_new: true on every post, and null
deltas, and saves the state. Deltas start from the second run of the same list.
How to run in 30 seconds
- Click Try for free. The input already holds
bsky.appandjay.bsky.team, 20 posts each. - Click Start. Our first run of that input took 16 seconds and cost $0.024 (2 profiles, 40 posts).
- Run it again later: the rows now carry follower changes,
is_newand engagement deltas. Export from the Output tab as CSV, JSON or Excel.
To track your own list, replace the handles (handles, @handles, custom
domains, DIDs or bsky.app profile URLs all work), then save it as a task and add
a daily or weekly schedule.
Pricing
- $0.002 per profile checked (found and compared).
- $0.0005 per post returned ($0.50 per 1,000 posts).
- Free: handles that are not found or fail to load.
- Every run is charged the same way, baseline or not: Posts per profile posts are returned each time, not only new ones; the comparison changes what each row says, not how many rows you pay for.
- Examples: 5 handles × 20 posts = $0.01 + $0.05 = $0.06 per run, so
$1.80 a month daily. 50 handles × 50 posts = $1.35 per run, about
$40.50 a month daily. Posts per profile
0costs only the profile checks, e.g. $0.02 per run for 10 handles. - With a maximum total charge set, the actor returns only as many rows as fit,
saves state for what it returned, stops, and says so in
OUTPUT(stopped_reason: "max_total_charge_reached").
FAQ
Do I need a Bluesky account? No. It reads Bluesky's public AppView API
(public.api.bsky.app) without logging in.
How do I get a daily digest in Slack? Schedule a task with your handle list
and add the Slack (or Zapier, Make, Google Sheets) integration on "run
succeeded", mapping the OUTPUT record or the dataset into the message. Or set
Webhook URL and the run POSTs its summary there.
Why are all my posts is_new: true? It is the first run of that list (the
baseline). Run the same list again and only genuinely new posts are marked new.
Can it search Bluesky posts by keyword? No. Bluesky's search endpoint returns 403 to logged-out requests on the public AppView (checked 2026-09-28).
Can it export follower lists? No, only follower counts.
Limits
- Public data only. Private data, DMs, blocked content, and accounts that
asked not to be shown to logged-out viewers are not returned. For those
(
logged_out_visible: false) you get the profile row but no posts. - Counts are the AppView's at the time of the run; the public API is cached for about 30 seconds, and other clients can show different numbers.
- Reposts carry the original post's counts, not engagement on the repost.
- One run per list at a time. Two runs with the same snapshot key at once: the one that finishes last wins.
- It stays polite: at most 5 requests per second for the whole run, HTTP 429
waited out (honouring
Retry-AfterandRateLimit-Reset), and a clear User-Agent. One request per 25 profiles, plus at least one feed request per profile when posts are requested (a page holds up to 100 posts).
How the comparison works
- State lives in the named key-value store
skywatch-snapshotsin your account, one record per profile and snapshot key, keyed by DID, so a handle change does not reset history. - A profile whose lookup fails keeps its previous state. If its post feed fails part-way, the profile numbers are updated and every remembered post is kept.
- Only posts returned to you are remembered.
is_newmeans "not returned by an earlier run of this snapshot key", so raising Posts per profile also marks older posts that are now included for the first time as new. - If the same account appears twice in the list (say as a handle and its DID), it is checked and charged once.
- Each profile remembers its newest 3,000 posts.
Input reference
| Field | Default | Notes |
|---|---|---|
handles | required | Handles, @handles, custom-domain handles, DIDs, or bsky.app profile URLs. Up to 1,000. A bare name with no dot is read as name.bsky.social. |
postsPerProfile | 50 | 0 to 1,000. 0 returns profile rows only. |
since | none | ISO date. Older posts are skipped and paging stops at that date. |
includeReplies | false | Include the account's replies. |
includeReposts | false | Include reposts (their counts belong to the original post). |
snapshotKey | derived | Which saved state to compare against. By default derived from the sorted handle list, so the same list always compares with itself. Set it yourself to keep history when you add or remove handles. |
webhookUrl | none | Receives the run summary as a JSON POST. |
Output reference
profile rows: DID, handle, display name, description, avatar, account creation
date; followers, following, posts count; followers_delta, follows_delta,
posts_count_delta versus the previous run (null on the baseline, which has
is_baseline: true); previous_checked_at, posts_found, new_posts_found;
status: ok, not_found (deleted, suspended or misspelled handle) or error.
post rows, newest first: uri, url, text, created_at; like_count,
repost_count, reply_count, quote_count, bookmark_count (when the AppView
reports it) and engagement = likes + reposts + replies + quotes; is_new;
like_delta, repost_delta, reply_delta, quote_delta, engagement_delta
for posts seen before (null for new posts); embed_type (images, video,
external, record, recordWithMedia), links, hashtags, mentions,
language; is_reply with parent and root URIs, is_repost with
reposted_at.
Every run returns a profile row per account, so a quiet run still shows the
current numbers with zero deltas and new_posts_found: 0. The key-value store record
OUTPUT holds a summary per profile: new posts, posts returned, average
engagement per post, the top post by engagement, and follower change.