Bluesky Scraper icon

Social media

Bluesky Scraper — Feed Posts

Export posts from any public Bluesky custom or algorithm feed via the AT Protocol API — feed metadata and engagement counts — to JSON or CSV. No login needed; we page through and retry so the whole feed lands.

Free Apify credit covers a first run. No credit card to try.

What this Actor scrapes

Two operating modes, controlled by which input field you set:

1. Single-feed mode — provide a feed URI (AT URI or bsky.app/profile/.../feed/... web URL) and the Actor exports every post in that feed up to the per-feed cap. 2. Creator-discovery mode — provide a creator's Bluesky handle (e.g. bsky.app) and the Actor calls app.bsky.feed.getActorFeeds to enumerate every feed that creator publishes, then scrapes each one in turn.

What we handle for you

  • What we handle for you: fingerprint rotation (curl-cffi browser impersonation — Chrome / Firefox profiles), exponential back-off on 408 / 429 / 503 with Retry-After honoured, up to 5 retries per failed request, proxy routing via Apify Proxy on demand, and Pydantic v2-validated rows. You get the clean CSV; we get the error logs.
  • Two operating modes: single feed URI or discover-all-feeds-by-creator via getActorFeeds.
  • Accepts either AT URIs (at://did:plc:.../app.bsky.feed.generator/whats-hot) or bsky.app web URLs — the Actor rewrites web URLs to AT URI form automatically.
  • Denormalised output — feed metadata (name, description, creator handle) on every post row, no joins needed for downstream analytics or CSV exports.
  • Cursor-based pagination with a client-side per-feed cap so you only pay for what you need.
  • Pure HTTP scraping with browser fingerprint impersonation — no browser automation overhead.
  • Pydantic v2 input validation with XOR guard: exactly one of feedUri or creatorHandle must be set.
  • Pairs with the companion bluesky-starter-pack Actor as the Bluesky Intel Suite.
  • Pay only for results that land — no data written means no result-row charges (only the small actor-start warm-up fee).

Use cases

  • Algorithm research — sample what posts the "Discover" / "What's Hot" algorithmic feeds actually surface across days or weeks; analyse topic drift and amplification patterns.
  • Newsroom monitoring — subscribe to curated topic feeds for breaking-news posts on specific beats, then pipe to Slack or a Google Sheet via Apify integrations.
  • Marketing intelligence — see which posts are amplified by community feeds in your niche; measure which content formats dominate each feed's engagement distribution.
  • Creator analytics — pull every post a niche feed generator surfaces and rank by like / repost / quote ratios to benchmark your own posts against feed peers.
  • Dataset bootstrap — collect labelled training data from topic-curated feeds for downstream NLP or sentiment models without manual tagging of raw timelines.
  • Competitive monitoring — track community-curated feeds that aggregate competitor announcements, support complaints, or product mentions.
  • Academic social-media research — Bluesky's public AT Protocol data is significantly more research-accessible than the current Twitter / X API; this Actor is a low-cost entry point for longitudinal feed studies.

Input

Paste this into the Apify Console, or send it as the run input over the API. Proxy settings are on by default; you rarely need to touch them.

FieldTypeRequiredWhat it does
feedUri string no AT URI (at://did:plc:.../app.bsky.feed.generator/...) or Bluesky web URL (https://bsky.app/profile/handle/feed/rkey) of one feed generator. Mutually exclusive with Creator handle.
creatorHandle string no Bluesky handle (e.g. bsky.app) or DID of a feed creator. The Actor enumerates every feed published by that user via app.bsky.feed.getActorFeeds and scrapes each. Mutually exclusive with Feed URI.
maxPostsPerFeed integer no Maximum number of post rows emitted per feed. Acts as a client-side cap; pagination stops when this limit is reached. Default 100.
maxFeeds integer no Maximum number of feeds to process when using creator-discovery mode. Ignored in single-feed mode. Default 5.
useProxy boolean no Route requests through Apify Proxy (BUYPROXIES94952, a static US datacenter pack). The AT Protocol public API does not block datacenter IPs — leave disabled unless you are behind a restrictive ISP.
{
  "feedUri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot",
  "maxPostsPerFeed": 100,
  "useProxy": false
}

Output

One row per result, schema-validated before it is written. Export JSON, CSV, Excel or XML from the run, or read it over the API.

feed_urifeed_display_namefeed_creator_handlefeed_descriptionpost_uripost_cidpost_indexed_atpost_textpost_langpost_reply_countpost_repost_countpost_like_countpost_quote_countauthor_didauthor_handleauthor_display_name

{
  "feed_uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot",
  "feed_display_name": "Discover",
  "feed_creator_handle": "bsky.app",
  "feed_description": "Trending content from your personal network",
  "post_uri": "at://did:plc:sj5wj7libgr7omqiotenxadx/app.bsky.feed.post/3mlxmr4jyfs2s",
  "post_cid": "bafyreidgimgd7v3g3pazsp5oq7ur6bvedpnwohul26mss7cbffg6bdqjkm",
  "post_indexed_at": "2026-05-16T10:20:40.467Z",
  "post_text": "If you never read the book or saw the movie, you missed one of the greatest Pulitzer Prize winning sagas ever written.",
  "post_lang": "en",
  "post_reply_count": 89,
  "post_repost_count": 414,
  "post_like_count": 1288,
  "post_quote_count": 27,
  "author_did": "did:plc:sj5wj7libgr7omqiotenxadx",
  "author_handle": "louiseplease.bsky.social",
  "author_display_name": "Louise",
  "scraped_at": "2026-05-16T12:00:00+00:00"
}

Pricing

EventPriceWhen
Actor start$0.20Once per run, covers warm-up and proxy session setup.
Post row emitted$0.0020Per result written to the dataset.

You pay only for results that land. Cap any run with maxTotalChargeUsd. See pricing & billing for worked examples.

Limitations

  • Private or access-restricted feeds are not exposed by the public AppView API — only feeds whose data is visible at public.api.bsky.app can be scraped.
  • Global feed discovery by keyword is not supported — Bluesky's getPopularFeedGenerators endpoint returns MethodNotImplemented on the public AppView. Use creator-discovery mode (creatorHandle) to enumerate one creator's feeds at a time.
  • Post images, embeds, and quoted-post bodies are not extracted — only the plain-text body (post_text) is captured. Image ALT text, external link cards, and quoted-post content are outside the current schema.
  • Reply thread expansion is out of scope — only the top-level post row is emitted. Threaded context (parent / root posts) would require additional getPostThread calls and is not wired in this version.
  • The maxPostsPerFeed cap is client-side — the Actor paginates until it has collected the cap or the API cursor is exhausted. If a feed has fewer posts than the cap, fewer rows are returned. This is expected behaviour, not a failure.
  • Storage retention on FREE Apify plans — run-scoped storage is retained for 7 days. Export your dataset immediately after the run or upgrade to a paid plan for longer retention.
  • Rate limiting — the Actor retries on 429 with exponential back-off and honours Retry-After, but very large scrapes (tens of thousands of rows) may require splitting into multiple runs to stay within per-window limits.
  • AT Protocol is pre-1.0 — Bluesky's endpoint surface has changed without warning in the past. We monitor the AT Protocol Discord #breaking-changes channel and ship patches within days of validated breakage reports.

FAQ

Do I need a Bluesky account to use this Actor?
The AT Protocol public AppView at public.api.bsky.app/xrpc/ is unauthenticated by design — every endpoint this Actor calls is open without a login or API key. You run the Actor; we handle the protocol plumbing.
What is a feed URI?
An AT URI like at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot. The segment after at:// is a DID — a decentralized identifier. The collection is always app.bsky.feed.generator. The final segment is the rkey that identifies the specific feed. You can also paste a bsky.app web URL — the Actor converts it automatically.
How do I scrape all feeds published by a single creator?
Set the creatorHandle input to the creator's Bluesky handle (e.g. bsky.app) and leave feedUri blank. The Actor calls app.bsky.feed.getActorFeeds and scrapes each feed in turn, up to the maxFeeds cap.
Can I export Bluesky's built-in feeds like "Discover" or "What's Hot"?
Yes. Those are published by the bsky.app account. Use the feed URI at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot for "Discover" / "What's Hot", or paste the bsky.app/profile/bsky.app/feed/whats-hot URL. You can also use creator-discovery mode with creatorHandle: "bsky.app" to get all feeds that account publishes.
Is this a good Twitter / X API alternative in 2026?
For public feed data, yes — AT Protocol is explicitly designed as a research-accessible open protocol, and the data model is significantly more predictable than Twitter's current API. That said, we recommend framing your project as "Bluesky-native" rather than "Twitter replacement" — the audiences and content patterns differ.
Is exporting public Bluesky feeds legal?
The AT Protocol is an open, federated protocol. public.api.bsky.app is explicitly unauthenticated and publicly accessible. The Bluesky Terms of Service permit accessing public data programmatically as long as you do not impersonate users or violate AT Protocol data-portability principles. Always verify the current Terms of Service at bsky.social/about/support/tos and your local jurisdiction's data-protection rules before using scraped data commercially.
How do I export to Google Sheets?
After the run finishes, click Export → CSV in the Apify Console and import the file into Google Sheets. Alternatively, use the Apify API URL shown in the run's Output tab to import data directly via =IMPORTDATA("...") in Sheets.
What happens if a feed is empty or the URI is wrong?
The Actor exits with a non-zero status code and a clear status message: "No posts emitted — feed may be empty, private, or the URI invalid." The dataset will have zero rows and the actor-start fee is the only charge.

Ready to run it?

Open the listing on Apify, paste the input above, and watch rows land. If it ever breaks, it is our problem before it is yours.

Related Actors

Teams that run this also run