Bluesky Public Posts Scraper - Feeds & Threads avatar

Bluesky Public Posts Scraper - Feeds & Threads

Pricing

from $1.20 / 1,000 post observations

Go to Apify Store
Bluesky Public Posts Scraper - Feeds & Threads

Bluesky Public Posts Scraper - Feeds & Threads

Extract public Bluesky author posts and supplied threads with links, reply relationships and engagement metrics. Optional saved-observation change tracking. No login or API key.

Pricing

from $1.20 / 1,000 post observations

Rating

0.0

(0)

Developer

Brandt May

Brandt May

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

Public posts, with thread context — illustrative workflow

Public posts, with thread context

Collect public Bluesky posts for editorial research, account watchlists or structured archives. Each row represents a root post; optional parent and reply context stays nested within that row.

Open this Actor in Console · First run · Results · Cost · Full guide

Try this Actor

  1. Choose a small scope. Use Bluesky Official Posts and Reply Context below: it requests three posts from bsky.app with up to ten context posts per result. For a post-only run, clear the prefilled author list.
  2. Run and review. Open the dataset for post observations. Check the run's key-value-store SUMMARY, observationComplete and thread coverage before treating a result as complete.
  3. Use the results. Export JSON to retain nested author, reply, media and metric fields. The table view is useful for scanning post text and source links.

Read this before using the data: This is a bounded public view, not a complete conversation or firehose. Hidden replies may be absent. Comparison is optional metadata: unchanged saved observations are still emitted and billed.

Bluesky Official Posts and Reply Context — copy this input into the JSON editor in Console.

{
"authors": [
"bsky.app"
],
"maxPosts": 3,
"includeThread": true,
"maxContextPosts": 10
}

Result preview

The dataset view highlights these columns:

  • Post link · url
  • Author handle · author.handle
  • Post text · text
  • Source creation time · createdAt
  • Observed likes · metrics.likes
  • Observed replies · metrics.replies

Use the original source links and the field definitions below when interpreting the results. CSV works well for flat columns; JSON preserves nested values.

Usage and pricing

Base result rate on the FREE tier: $2 per 1,000 post observations. The Pricing tab shows your plan's result rate and any Actor Start charge. Set a small result limit for the first run; the requested limit is not a guarantee of that many results.


Customer workflow: An editorial watchlist with engagement checkpoints

Watch explicit public publisher accounts, retain stable post identities and source links, and separate newly observed content from ordinary engagement changes. This is an editorial queue, not network-wide listening.

Setup: Connect your own Apify and Google Sheets current-post register and optional observation history through Make or n8n. Keep credentials in your connector's credential manager.

{
"authors": [
{
"value": "bsky.app",
"externalId": "publisher-demo"
}
],
"postUrls": [],
"maxPosts": 10,
"maxPostsPerAuthor": 10,
"maxPagesPerAuthor": 3,
"includeReplies": false,
"includeReposts": false,
"includeThread": false,
"comparePrevious": true,
"baselineKey": "customer-editorial-v1",
"maxRunSeconds": 240
}

Start with a 300-second Run timeout and $0.50 maximum run charge, alongside the input's 240-second budget. Check current pricing and the selected scope before increasing either limit.

  1. Create a Posts sheet keyed by uri, then replace the demo account with your explicit public publisher watchlist. Keep your customer reference in externalId. Seed the sheet from the first run before creating editorial alerts.
  2. Require a healthy SUMMARY, no failed sources, and observationComplete: true before treating an observation as complete. Inspect source stop reasons: this input watches a bounded recent feed, not every historical post.
  3. Upsert by uri using Sheets "Append or Update Row" in n8n or a lookup/update branch in Make. Flatten metrics into columns; preserve requestedBy as JSON because several requested sources can point to one post.
  4. Reuse baselineKey sequentially. Route first_observation or contentChanged: true to editorial review, and metricsChanged to a separate engagement checkpoint. Null deltas stay unknown; unchanged posts are still saved and billed.
Destination informationActor fields
Stable key and linkuri, url
Author and attributionauthor.handle, requestedBy
Contenttext, contentHash
Engagementmetrics.likes, metrics.reposts, metrics.replies, metrics.quotes
ComparisoncomparisonStatus, contentChanged, metricDeltas, observedAt

Keep the meaning: There is no onlyChanges input. A recent window can miss posts between runs, and absence does not prove deletion. Thread context is off here; when enabled, it remains a bounded public view, never a guaranteed complete conversation.

Empty or interrupted runs: No public posts may match the selected feed scope. A healthy unchanged repeat normally still contains rows. An unavailable supplied post is an operational issue, not an automatic deletion signal.

Reliable delivery: Read the completed run's own SUMMARY and paginated dataset. Retain its run ID; if destination delivery fails, replay that dataset and deduplicate by run ID plus row key. Keep destination writes sequential, and write source text literally.

Validation: Inputs and mappings were checked locally against this Actor. The exact customer connection has not been run end to end. Choose recurrence after a manual bootstrap; this guide creates no schedule. See the run API, pagination guide, and the full Actor guide below for detailed setup and limits.

Full guide

Extract recent public posts from supplied Bluesky accounts, or inspect known public post URLs. Each saved row is one root post with its text, source URL, stable URI/CID, links, hashtags, facet byte offsets, media references, author attribution, reply relationships and engagement counts.

The optional thread view puts bounded parent/reply context inside the same row. Optional change tracking compares a root post's content and metrics with its previously saved observation.

Quick start

Run with {} for three recent original posts from bsky.app, with up to 10 visible context posts each. No Bluesky login, app password, API key or proxy is required. Only the official public API is used. Source availability and public visibility can change.

Inputs and scope

  • authors: up to 20 public handles, DIDs or profile URLs. Entries can be strings or {"value":"bsky.app","externalId":"crm-123"}.
  • postUrls: up to 50 supplied public bsky.app post URLs or post AT-URIs; the same object form preserves an external ID.
  • maxPosts defaults to 3, maximum 200. All sources share this limit; authors are processed before supplied posts. A post selected more than once is saved once with requestedBy attribution for sources reached before the global cap.
  • maxPostsPerAuthor defaults to 25; maxPagesPerAuthor defaults to 3. The Actor stops at the first applicable bound and records why.
  • Original non-reply posts are the default. includeReplies and includeReposts apply to author feeds. Supplied post URLs are always eligible. Repost provenance remains separate from the original author.
  • includeThread defaults to true. Reply depth defaults to 1, parent height to 1 and retained context to 10 posts. Maximum reply depth 3, parent height 5, context 50. The context limit is shared by parents and replies; parents are visited first, then replies breadth-first.
  • maxRunSeconds defaults to 240 and is capped at900. The Actor also stops 25 seconds before the platform deadline.

An empty authors list and empty post list use the default account. A list supplied only in postUrls does not add the default account. Invalid URLs and input types fail with a diagnostic.

Output and billing

One paid result is one saved public root-post observation. Nested thread context is included in that result. Error messages and inaccessible posts are never paid placeholder rows. Unchanged observations are still saved and billed; comparison is metadata, not an output filter.

Key fields: url, uri, cid, postId, contentHash, author, text, createdAt, links, hashtags, facets, media, replyTo, threadRoot, metrics, requestedBy, thread, threadCoverage, observationComplete and observedAt. Missing optional source fields are null. Facet positions are UTF-8 byte offsets, not JavaScript character indexes. Images/video are linked, not downloaded.

Source createdAt is retained as supplied and may differ from indexing time. Metrics are observations, can decrease, and are not historical lifetime guarantees. A quoted record is a reference; quoted-post bodies are not separately expanded.

Coverage and failures

This Actor reads a bounded public view. It does not provide keyword search, follower graphs, private content, a firehose, exhaustive history or a complete conversation. The API can omit moderated, deleted, blocked or otherwise hidden material. A reported reply count can exceed visible replies. completeConversation is always false; contextTruncated reports the Actor's own output cap separately.

If thread expansion fails but a valid feed post was obtained, that real post can still be saved with observationComplete:false. It does not update comparison history. Supplied unavailable posts and wholly failed sources produce diagnostics in SUMMARY. A run with no usable rows and upstream failures fails honestly. A valid empty feed or exhausted spending limit can finish with a clear empty/budget status. Intentional maxPosts/page/context caps are scope controls; they are distinct from source failures or timeouts.

The SUMMARY record contains saved totals, selected posts, per-source stop reasons, failed and skipped sources, unsaved counts, deadline/spend flags and baseline commits. Check it when a run is partial. The overview dataset table shows the main observation fields.

Change tracking

Set comparePrevious:true and choose a baselineKey. Snapshots are stored in the named key-value store maydit-bluesky-post-observations-v1, keyed by namespace and stable post URI. They retain only the URI, hash, metrics, version and observation time—not post text or context bodies.

First observations use comparisonStatus:first_observation and no numeric deltas. Later observations include contentChanged, metricsChanged and signed metricDeltas. The comparison covers root content and metrics only; thread context changes, handle/display-name changes and deletion are not compared. Missing posts or missing replies never produce deletion claims.

Only a confirmed saved, complete row updates its baseline. A final accepted row at the charge limit counts as saved; an unsaved row does not advance history. A storage-write failure is visible in SUMMARY. Use one writer at a time per namespace, because key-value storage provides no transaction across concurrent runs. Use a new namespace to start a fresh comparison; remove the relevant records in the named store to clear retained observations.

Three exact examples

Bluesky Official Posts and Reply Context

Three recent original posts from the public Bluesky account, with up to 10 visible thread context posts per result.

Use the copyable first-run input above.

AT Protocol Public Updates

Three recent original posts from the public AT Protocol account, with links and engagement metrics. No thread expansion.

{
"authors": [
"atproto.com"
],
"maxPosts": 3,
"includeThread": false
}

Bluesky Public Thread with Reply Relationships

Inspect one supplied public Bluesky post and a bounded view of its reply relationships. No search or login is used.

{
"authors": [],
"postUrls": [
"https://bsky.app/profile/bsky.app/post/3mx5e63uvns2d"
],
"maxPosts": 1,
"includeThread": true,
"threadDepth": 2,
"parentHeight": 1,
"maxContextPosts": 20
}

Source, content requests and support

Source: Bluesky public API, author-feed definition, thread definition, rate limits and developer guidelines.

For support or a content-removal request, open this Actor's Issues tab or email bmay@mayd-it.com. Include the public post URL and relevant run/dataset record reference; do not send credentials. We can address retained data under our control. You control your run datasets and downstream exports, and should provide a deletion/reporting method for any service you build using them. Public access does not transfer content ownership. Respect source policies and applicable rights; this Actor does not automate posting, liking, following or messaging.

Help with your run

Open the Issues tab on this Actor with the run URL, the input field that caused trouble and what you expected to receive. Remove API keys and private information before posting.

Explore more Mayd-It Actors

Understand your run

Open Run report in the run’s Output tab for saved-record counts, reported source issues and limits, and suggested next steps. Use CSV export to take the saved results into a spreadsheet. The existing JSON results and detailed machine-readable summary remain available.

The report reflects this run’s recorded coverage. A successful run or a saved result does not establish that every possible source record was collected.