Bluesky Posts Scraper — Search, Feeds & Threads
Pricing
from $5.00 / 1,000 public bluesky post scrapeds
Bluesky Posts Scraper — Search, Feeds & Threads
Search public Bluesky posts, export author feeds and threads, and get clean engagement data for research. Works with Apify MCP and the API.
Pricing
from $5.00 / 1,000 public bluesky post scrapeds
Rating
0.0
(0)
Developer
Khadin Akbar
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
17 days ago
Last modified
Categories
Share
What is Bluesky Posts Scraper — Search, Feeds & Threads?
Bluesky Posts Scraper — Search, Feeds & Threads returns one dataset row per public Bluesky post from keyword searches, author feeds or post threads: post text, AT URI and web URL, author handle, DID and display name, created and indexed times, like, repost, reply and quote counts, languages, hashtags, mentions, links, media URLs, reply context and the query or URL that found it. Social listening teams, brand and PR managers, journalists, researchers and AI agents use it to monitor conversations and build Bluesky datasets, with no Bluesky account or app password.
Why people use this Bluesky scraper
- Three ways in.
queriessearches all public posts,handlescollects author feeds, andpostUrlsexports a post with its reply thread. - Search filters that matter.
since,until,language,author,mentions,domain,exactUrlandtagsnarrow searches on Bluesky itself. - Engagement thresholds.
minLikes,minRepostsandminReplieskeep only posts that drew a reaction. - Stable IDs.
postUriandauthorDidstay the same when handles change, so they make clean keys for deduplication and joins. - Provenance on every row.
sourceTypeandsourceQueryorsourceUrlshow which search, feed or thread each post came from.
Best fit for this Actor
- Best fit for brand monitoring, news and link tracking, community research and conversation exports on Bluesky.
- Designed for public posts: searches, public author feeds and public threads.
- Use
domainto see who shares links to a publication or website, andpostUrlswithincludeThreadRepliesto export a whole discussion. - When you want account details such as bio and follower counts, then pass the
authorHandlevalues to Bluesky Profile Details Scraper. - To track the same topic on X, continue with X Twitter Search Scraper and compare the two conversations.
Example workflow: from a publication domain to a share report
A newsroom audience editor starts with domain set to their site, sort set to latest and maxResults at 200. The dataset returns every recent post linking to the site, with authorHandle, likeCount, repostCount and createdAt. They group posts by links and text to see which articles travel, rank sharers by engagement, and pass the most active handles to their community team. They then schedule the same input daily with since set to the previous day and export each run to their analytics sheet.
Input
Search recent posts:
{"queries": ["climate tech", "renewable energy"],"sort": "latest","language": "en","minLikes": 10,"maxResults": 100}
Collect author feeds:
{"handles": ["bsky.app", "https://bsky.app/profile/apify.com"],"authorFeedFilter": "posts_no_replies","maxResults": 50}
Export a thread:
{"postUrls": ["https://bsky.app/profile/bsky.app/post/3mw2cdr44fc2a"],"includeThreadReplies": true,"threadDepth": 2,"maxResults": 100}
| Field | Type | What it controls |
|---|---|---|
queries | array of strings | Keywords, phrases, hashtags, URLs or Bluesky search syntax, up to 50. |
handles | array of strings | Handles, DIDs or profile URLs whose feeds to collect. |
postUrls | array of strings | Post URLs or at:// URIs. |
maxResults | integer | Cap on posts saved across the run, up to 1,000. Default 50. |
sort | string | Search order: latest or top. Default latest. |
authorFeedFilter | string | posts_with_replies, posts_no_replies, posts_with_media, posts_and_author_threads or posts_with_video. |
includeThreadReplies, threadDepth | boolean, integer | Collect public replies under each post, up to 20 levels deep. |
since, until | strings | Search date range as ISO dates or datetimes. |
language | string | Two-letter language code for search results. |
author, mentions | strings | Limit search to posts by, or mentioning, a handle or DID. |
domain, exactUrl | strings | Limit search to posts linking to a domain or an exact URL. |
tags | array of strings | Limit search to tags, entered without #. |
minLikes, minReposts, minReplies | integers | Minimum engagement to keep a post. |
With every target field empty, the Actor runs a small AI search, so {} works as a quick check.
Output
Every row is a post record.
| Field | What it contains |
|---|---|
postUri, postUrl, cid | Stable AT URI, web link and content ID |
text, languages | Post text and declared languages |
hashtags, mentions, links | Tags, mentioned accounts and links marked up in the post |
mediaUrls, embedType | Images or link cards and the embed type |
authorDid, authorHandle, authorDisplayName, authorAvatar | Author identity |
createdAt, indexedAt | When the post was written and indexed |
likeCount, repostCount, replyCount, quoteCount | Engagement at collection time |
isReply, replyParentUri, replyRootUri | Reply context |
isRepost, repostedByHandle | Repost context in author feeds |
sourceType, sourceQuery, sourceUrl, provider | How the post was found: search, author feed, direct_post or thread_reply |
scrapedAt | Collection time |
Example row from a search (author details are illustrative):
{"recordType": "post","postUri": "at://did:plc:exampleauthor000000000000/app.bsky.feed.post/3mwst2vdkgc2b","postUrl": "https://bsky.app/profile/sam-writes.bsky.social/post/3mwst2vdkgc2b","cid": "bafyreigkx65iafsp4wxivkccboe5vomqlta6khublouehpr6qzjckdvpc4","text": "Good overview of where AI chips are heading this year www.theverge.com/tech/...","createdAt": "2026-10-01T12:07:15.907Z","indexedAt": "2026-10-01T12:07:18.761Z","authorDid": "did:plc:exampleauthor000000000000","authorHandle": "sam-writes.bsky.social","authorDisplayName": "Sam Writes","likeCount": 3,"repostCount": 1,"replyCount": 0,"quoteCount": 0,"languages": ["en"],"hashtags": [],"mentions": [],"links": [],"mediaUrls": ["https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:exampleauthor000000000000/bafkreihc4xslm66qsulrmzoks7s3i7a754o4tnxplgasilzwmplzizjday"],"embedType": "external","isReply": false,"isRepost": false,"sourceType": "search","sourceQuery": "AI","provider": "bluesky-appview","scrapedAt": "2026-10-01T12:11:16.133Z"}
Each run also writes OUTPUT and RUN_SUMMARY records to the default key-value store with the run outcome and totals.
Pricing
This Actor uses Pay per event plus Apify platform usage. Each unique post saved is one Public Bluesky post scraped event, and each run has one Actor Start event plus the platform usage of the run. Duplicates across queries, feeds and threads are merged before saving, so each post counts once. For example, a daily search capped at 200 posts is up to 200 post events plus the start event and usage. maxResults doubles as a spending limit. The live Pricing tab on this page shows the current event prices.
API example
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~bluesky-posts-scraper/run-sync-get-dataset-items?token=YOUR_API_TOKEN" \-H "Content-Type: application/json" \-d '{"queries": ["open source AI"], "sort": "latest", "maxResults": 100}'
from apify_client import ApifyClientclient = ApifyClient("YOUR_API_TOKEN")run = client.actor("khadinakbar/bluesky-posts-scraper").call(run_input={"handles": ["bsky.app"], "maxResults": 50})for post in client.dataset(run["defaultDatasetId"]).iterate_items():print(post["createdAt"], post["likeCount"], post["text"][:80])
Use with AI agents (MCP)
Connect the Actor to Claude, ChatGPT or Cursor through Apify MCP and ask:
Search Bluesky for the latest 50 English posts about open-source AI, then summarize the recurring complaints and cite each post by its URL.
The agent sets queries, language and maxResults, reads rows with get-dataset-items, and cites postUrl or postUri. It can check OUTPUT.outcome to tell a quiet topic from a full result set, and each unique post is one event, so maxResults keeps the cost of the request predictable.
Best results
| Starting situation | Helpful action | Expected outcome |
|---|---|---|
| Brand monitoring | Search the brand with sort set to latest and schedule it | New mentions each run |
| Signal over noise | Set minLikes or minReposts | Posts that drew engagement |
| Link tracking | Use domain or exactUrl | Posts sharing your site or article |
| A creator's output | Use handles with posts_no_replies | Their original posts only |
| A full discussion | Use postUrls with includeThreadReplies and a higher threadDepth | The post and its reply tree |
| Joining datasets | Key on postUri and authorDid | Stable joins across runs |
Builder's note
I built one Actor for search, feeds and threads because Bluesky research usually moves between all three, and a single row shape keeps the analysis simple. I chose the AT URI and DID as the identity of every row since handles on Bluesky can change while those stay fixed, and I kept the source query on each post so every row can be traced back to why it was collected.
FAQ
Do I need a Bluesky account?
No. The Actor reads public Bluesky data with no login or app password.
Are engagement counts live?
They are the counts at collection time. Re-run the same input to refresh them.
How are duplicates handled?
Posts are merged by postUri across every query, feed and thread in a run, and each is saved once.
Responsible use
This Actor collects public Bluesky posts. Posts include handles and display names, which are personal data under laws such as the GDPR and CCPA, so process them with a lawful basis, respect Bluesky's terms, and use the data for research and monitoring rather than profiling individuals. Bluesky is a trademark of its owner; this independent Actor is not affiliated with or endorsed by Bluesky Social PBC.