Bluesky Posts Scraper

v1.0.2$0.0011/post rowSignal Detection

Last updated November 9, 2026

Search Bluesky posts by keyword, read an account's posts, or read a post and its replies. Exact like, reply, repost, and quote counts, with dates, hashtags, links, and images. No login and no key. You pay per row.

Install

bash
npx @mambalabsdev/mcp-bluesky-posts-scraper

Every tool here also runs hosted, with no install at all, through Apify's MCP endpoint.

Features

  • Keyword search with sort, date, and language filters.
  • An account's posts, with or without its replies and reposts.
  • A post and its replies from a post address.
  • Exact like, reply, repost, and quote counts.
  • A free status row per source says what it returned or why it stopped.
  • Pay per event: Post row at $0.0011.

Input

queriesarrayoptional

Keywords to search, up to 20. Without your own app password each search returns one page, about 100 posts. Text from Clay splits on new lines, so a query can hold a comma.

authorsarrayoptional

Bluesky handles, profile addresses, or DIDs, up to 20. Returns each account's own posts, newest first.

post_urlsarrayoptional

Addresses of Bluesky posts to read, up to 100.

sortstringoptional

latest or top. Default latest. Used for queries.

since_datestringoptional

Only posts from this date, such as 2026-10-01.

until_datestringoptional

Only posts before this date, such as 2026-11-01.

languagestringoptional

Language code such as en or de. Used for queries. Reads the language the post's author set.

max_posts_per_sourcestringoptional

Per query or account, up to 2000. Default 100. A search with no app password stops at about 100.

include_repliesstringoptional

yes or no. Default no. Reads the replies under each post found. Each reply is a charged row.

max_replies_per_poststringoptional

Up to 200. Default 20.

include_account_repliesstringoptional

yes or no. Default no. Used for accounts.

include_repostsstringoptional

yes or no. Default no. Used for accounts. A repost row shows the original author.

bluesky_handlestringoptional

Optional, with the app password. Used only to page a search past its first page.

bluesky_app_passwordstringoptional

Optional. Create an app password in Bluesky settings; never use your main password. Sent only to Bluesky. Without it a search returns one page, about 100 posts. Accounts and post addresses need no password.

max_charge_usdstringoptional

Optional. The run stops before a charge that would pass this amount. Summary rows are always returned.

Output schema

json
{
  "row_type": "string",
  "row_key": "string",
  "source_type": "string",
  "query": "string",
  "account": "string",
  "input_url": "string",
  "query_in_text": "boolean",
  "post_uri": "string",
  "url": "string",
  "text": "string",
  "author_handle": "string",
  "author_name": "string",
  "author_did": "string",
  "author_url": "string",
  "created_at": "string",
  "indexed_at": "string",
  "likes": "integer",
  "replies": "integer",
  "reposts": "integer",
  "quotes": "integer",
  "languages": "array",
  "hashtags": "array",
  "mentions": "array",
  "links": "array",
  "image_urls": "array",
  "is_reply": "boolean",
  "parent_uri": "string",
  "root_uri": "string",
  "posts_returned": "integer",
  "replies_returned": "integer",
  "list_complete": "boolean",
  "row_status": "string",
  "error_reason": "string",
  "billable_events_json": "string",
  "scraped_at": "string"
}

Pricing

$0.0011per post row
EventFree plan price
Post row$0.0011
Actor Start$0.005

Pay per event on the Apify platform. Paid Apify plans pay less per event. No subscription, no seat license.

On the Apify free plan the actor stops at $1.50 of charges a month, about 1,364 post rows. Any paid Apify plan removes the cap.

Limits

  • A search with no account returns one page, about 100 posts per query. Bluesky answers any later search page with HTTP 403 "forbidden by administrative rules" from every exit tested. The status row reads partial and says so. The actor does not slice dates to get past this. To page further, give your own bluesky_handle and bluesky_app_password.
  • The app password route has not run on a real account. Fixtures and the refused password path are the test, and the first buyer's password is the live test. Use an app password, never your main password. It is sent only to Bluesky, stays out of rows and logs, and is used only for search.
  • A login session lasts about 2 hours by Bluesky's own setting, and a longer search then ends as partial.
  • Accounts page with no account of your own: 2,000 unique posts from one account in one test run, 303 seconds. 2,000 per source is the actor's maximum.
  • Bluesky decides what a search matches, and it also matches things a row does not show, such as a link target. query_in_text reads false on those rows. In one test, 13 of 99 read false, and these rows are charged.
  • Replies come from the first 6 levels of a thread. Blocked and deleted replies are skipped.
  • If the first 5 sources return nothing, the run stops with a free row, so a list of dead entries does not run on. After any row is returned, every source runs.
  • A repost row shows the original author and post, not who reposted it.
  • An author who asks Bluesky not to show them to logged out viewers is skipped, free, on every route, including when you give an app password. On one search page, 10 of 100 posts were skipped this way, so a search can return fewer rows than the maximum. An account or post input like this reads no_results and says why.