# Bluesky Scraper: Posts, Profiles, Feeds and Threads

> Bluesky scraper: search posts, get account posts, profiles, reply threads and custom feeds as clean JSON. Likes, reposts and links. No login needed.

URL: https://cliqtomedia.com/actors/bluesky-scraper/

Category: Social media & communities · Status: live on Apify Store · Apify page: https://apify.com/cliqtomedia/bluesky-scraper?fpr=cliqto

Get public Bluesky posts, profiles, threads and feeds as clean rows. You need no account and no app password.

## How to use it: 3 steps

1. **Make a free Apify account.** Apify is the cloud platform where our tools run. The free plan gives you $5 of usage every month, no credit card needed. You pay Apify, not us.
2. **Paste your input and press Start.** No code needed: you fill in a form (the input). It already has a working example. For example: `apify` in Search queries (mode: Search posts). Each start is one run.
3. **Download the results.** When the run ends, the results are in a table (the dataset). Open Output, press Export and pick Excel or CSV. JSON and the API are there too.

## What it does

Scrape public Bluesky posts, profiles, custom feeds, lists and reply threads with no login, and get clean JSON rows with text, engagement counts, links, mentions, hashtags, image alt text, quoted posts and author details.



### Good for

- Track what people post about a brand, product, hashtag or domain on Bluesky.
- Collect the posts and profiles of a list of accounts for research or lead lists.
- Pull a full reply thread for sentiment or discussion analysis.
- Feed clean, typed Bluesky rows into an AI agent, a spreadsheet or a database.

### Not a good fit

- No private data: no DMs, no muted or blocked lists, nothing that needs login.
- No followers or following lists in this version.
- Search returns at most 100 posts per query, because Bluesky blocks further search pages without login. The Actor does not try to get around this.
- Counts (likes, reposts, followers) are a snapshot at fetch time.

## Price

Pay per event. Apify bills you, not us.

| What you pay for | Price | When |
|---|---|---|
| Start fee | $0.001 | Charged once per run. This tool uses 1 GB of memory or less by default; more memory costs more. |
| Post | $0.0009 (from $0.00055 on paid Apify plans) | One Bluesky post row saved to the Dataset (search, account posts, thread or feed). |
| Profile | $0.0027 (from $0.0016 on paid Apify plans) | One Bluesky profile row saved to the Dataset. |
| Empty result | $0.0005 | One input value that returned no data: a search or account with no matching posts, or a profile, post, feed or list that does not exist or cannot be read. |

- One post: about $0.0019.
- 1,000 posts: about $0.90.
- Every day 100 posts, for 30 days: about $2.73 a month.

Free to try: the Apify free plan gives you $5 of usage every month, no credit card needed.

Prices checked on 24 October 2026. Current price: https://apify.com/cliqtomedia/bluesky-scraper?fpr=cliqto

## Questions

### Why do I get only 100 posts per search?

Bluesky shows more search pages only to logged-in users. The tool respects that limit.

### Can I get a follower list?

Not in this version. You get the follower count in profile rows.

### Are likes and reposts up to date?

They are a snapshot from the time of the run. Run again to refresh them.

### Do I pay for posts that do not exist?

An input with no data is one small empty-result event. Error rows and duplicates are free.

### Do I need a Bluesky account or app password?

No. The Actor reads only public data from the public Bluesky API and never asks for login.

### Are the counts live?

They are a snapshot at `fetchedAt`. Run again to refresh them.

### Is this data complete?

It is what the Bluesky API returns at fetch time. Deleted posts, blocked content and posts hidden by moderation are not included, and counts can be null when Bluesky does not report them.

### Can I scrape followers or DMs?

Not in this version. DMs are private and will never be supported.

### Is scraping Bluesky allowed?

The Actor uses only public endpoints at a modest request rate and does not bypass any limit. You are responsible for how you store and reuse the content, including personal data and authors' rights.

## Data fields

- `recordType` (string): Row type: post, profile or status. Error rows are free; a not-found or invalid value is charged as one empty result.
- `status` (string): complete for data rows; not_found, invalid_input or error for status rows.
- `mode` (string): Mode that produced the row.
- `input` (string): Your input value (query, handle, post URL or feed URL) that produced the row.
- `errorCode` (string): Status rows: machine code such as NOT_FOUND, INVALID_INPUT, RATE_LIMITED, SOURCE_FORBIDDEN, SOURCE_UNAVAILABLE.
- `message` (string): Status rows: plain-English reason.
- `uri` (string): Post AT URI, e.g. at://did:plc:…/app.bsky.feed.post/3l…
- `cid` (string): Post content ID (CID).
- `url` (string): bsky.app link to the post or profile.
- `author` (object): Post author: did, handle, displayName, avatar, url.
- `text` (string): Post text.
- `createdAt` (string): When the post or account was created (ISO 8601, as stated by the author record).
- `indexedAt` (string): When Bluesky indexed the post or profile (ISO 8601).
- `langs` (array): Language codes declared by the post, e.g. ["en"].
- `replyCount` (integer): Replies at fetch time.
- `repostCount` (integer): Reposts at fetch time.
- `likeCount` (integer): Likes at fetch time.
- `quoteCount` (integer): Quote posts at fetch time.
- `bookmarkCount` (integer): Bookmarks at fetch time, when Bluesky reports it.
- `isReply` (boolean): true when the post is a reply.
- `replyTo` (object): Parent post of a reply: uri and url.
- `rootPost` (object): Thread root of a reply: uri and url.
- `isRepost` (boolean): true when the row comes from a repost in a feed (see repostedBy, repostedAt).
- `repostedBy` (object): Who reposted it into the feed: did and handle.
- `repostedAt` (string): When it was reposted.
- `isPinned` (boolean): true when the post is pinned on the author profile.
- `isQuote` (boolean): true when the post quotes another post.
- `quotedPost` (object): Quoted post: uri, url, authorHandle, text.
- `embedType` (string): Attached media: images, video, external, record (quote), recordWithMedia or null.
- `images` (array): Images: url, thumbnailUrl, alt text, width, height.
- `video` (object): Video: playlistUrl, thumbnailUrl, alt text.
- `externalLink` (object): Link card: url, title, description.
- `links` (array): All links in the post text and link card.
- `hashtags` (array): Hashtags without #.
- `mentions` (array): Mentioned accounts: did and handle.
- `labels` (array): Moderation and self labels on the post or profile.
- `threadRole` (string): Thread mode: parent, anchor or reply.
- `threadDepth` (integer): Thread mode: 0 for the requested post, negative for parents, positive for replies.
- `did` (string): Profile DID (stable account ID).
- `handle` (string): Profile handle, e.g. bsky.app.

## Input settings

- `mode` (string, required): searchPosts: posts matching keywords, hashtags or from:/lang: operators (up to 100 per query). authorFeed: posts from accounts. profiles: profile details and follower counts. thread: a post with its parents and replies. feed: posts from a custom feed or list.
- `queries` (array): Keywords, phrases in quotes, #hashtags, or Bluesky search operators such as from:bsky.app, lang:en, domain:example.com. One query per line, up to 100. Bluesky returns at most 100 posts per query without login.
- `handles` (array): Bluesky handles (bsky.app, @jay.bsky.team), DIDs or profile links (https://bsky.app/profile/…). A bare name becomes name.bsky.social. Up to 100 accounts for posts, 1,000 for profiles.
- `postUrls` (array): Post links like https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l or at:// URIs. Up to 100.
- `feedUrls` (array): Custom feed links (https://bsky.app/profile/…/feed/…) or list links (https://bsky.app/profile/…/lists/…). Up to 50.
- `maxItems` (integer): Upper limit of posts for each input value (profiles mode: ignored, one row per handle). Search stops at 100 per query. You pay per row written; a value with no data at all is one empty result.
- `since` (string): Only posts created on or after this date, e.g. 2026-10-01 or 2026-10-01T12:00:00Z (UTC). Applies to search, account posts and feeds.
- `until` (string): Only posts created before this date (UTC).
- `searchSort` (string): latest: newest first. top: Bluesky's ranking of popular posts.
- `language` (string): Language code for search, e.g. en, de, ja, pt-BR. Empty: all languages.
- `includeReplies` (boolean): Keep replies in search and account posts. Turn off to get only top-level posts.
- `includeReposts` (boolean): Also return posts the account reposted, marked isRepost with repostedBy and repostedAt.
- `threadDepth` (integer): How many reply levels below the post to load. 0 returns only the post and its parents.

## Step by step on Apify

1. Open the Input tab.
2. Keep What to scrape on Search posts and add a word to Search queries, e.g. `apify`.
3. Keep Max posts per query at the prefilled `30` (the runtime default is `100`).
4. Click Start.
5. Open the Posts view in the Output tab and check `text`, `author.handle` and `likeCount`.

## Use cases

| Task | Input | You get | Key fields | Next step |
|---|---|---|---|---|
| Brand or keyword listening | `mode: searchPosts`, `queries` | post | `text`, `createdAt`, `likeCount`, `author.handle`, `links` | Schedule the Actor, export to Sheets or a database |
| Account research | `mode: authorFeed`, `handles`, `since` | post | `text`, `isRepost`, `replyCount`, `externalLink` | Compare accounts, build datasets |
| Influencer or lead list | `mode: profiles`, `handles` | profile | `displayName`, `description`, `followersCount`, `postsCount` | CRM import |
| Discussion analysis | `mode: thread`, `postUrls` | post | `threadRole`, `threadDepth`, `text`, `replyTo` | Sentiment or topic analysis |
| Curated topic monitoring | `mode: feed`, `feedUrls` | post | `text`, `hashtags`, `images[].alt` | AI summarisation |

## Tips

- Split a big topic into narrow queries; search gives 100 posts per query.
- Use date filters to get posts from one week only.
- Turn off reposts if you want original posts only.

## Limits



- Post row / profile row: one per data row written.
- Empty result: one per input value that produced no data: a search query with no matches, an account with no matching posts, a profile, post or feed that does not exist, or a value that cannot be read (for example a typo in a link). If every value is unreadable, the run ends as `NO_RESULTS` with a message saying so, and each value is one empty result. It covers the requests made for that value.
- Actor start: charged by Apify once per run (per GB of memory; the default 256 MB counts as one).
- Free: `error` rows (Bluesky failed), skipped inputs, duplicate posts and duplicate input values (the same account, post or feed written another way, e.g. `@Name.bsky.social` and its profile link).
- Search: up to 100 posts per query (Bluesky's limit without login). Split the topic into narrower queries or date ranges to see more.
- Account posts: up to 10,000 feed items scanned per account. A scan also stops early when fewer than 1 in 100 items match the filters after the first 1,000 items, so a sparse filter does not read the whole history.
- Feeds: the same sparse stop applies.
- Speed at 256 MB: one account's 1,030 posts in about 5 s; 10,000 account posts took about 2–3 minutes in tests. Large jobs need a longer run timeout than the default 300 s; an input cut by the timeout is marked `partial` with its row count.

## Sample result

```json
{
  "recordType": "post",
  "status": "complete",
  "mode": "searchPosts",
  "input": "opendata",
  "uri": "at://did:plc:aaaaaaaaaaaaaaaaaaaaaaaa/app.bsky.feed.post/3mexample2abc",
  "url": "https://bsky.app/profile/author.example/post/3mexample2abc",
  "author": {
    "did": "did:plc:aaaaaaaaaaaaaaaaaaaaaaaa",
    "handle": "author.example",
    "displayName": "Sample Author",
    "url": "https://bsky.app/profile/author.example"
  },
  "text": "Our open dataset is live! Thanks @team.example #opendata https://data.example/downloads",
  "createdAt": "2026-10-12T09:15:00.000Z",
  "likeCount": 2431,
  "repostCount": 318,
  "replyCount": 154,
  "isReply": false,
  "isRepost": false,
  "embedType": "images",
  "images": [
    { "url": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:aaaaaaaaaaaaaaaaaaaaaaaa/bafkexample@jpeg", "alt": "Chart of monthly downloads" }
  ],
  "links": ["https://data.example/downloads"],
  "hashtags": ["opendata"],
  "mentions": [{ "did": "did:plc:bbbbbbbbbbbbbbbbbbbbbbbb", "handle": "team.example" }],
  "quotedPost": null,
  "threadRole": null,
  "fetchedAt": "2026-10-13T01:52:14.278Z",
  "source": "Bluesky AppView API (AT Protocol)"
}
```

## Use it from code

Actor ID: `cliqtomedia/bluesky-scraper`

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("cliqtomedia/bluesky-scraper").call(run_input={
    "mode": "searchPosts",
    "queries": [
        "apify"
    ]
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

```bash
curl -X POST "https://api.apify.com/v2/acts/cliqtomedia~bluesky-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode": "searchPosts", "queries": ["apify"]}'
```

```python
# pip install langchain-apify
# set APIFY_TOKEN in your environment
from langchain_apify import ApifyActorsTool

tool = ApifyActorsTool("cliqtomedia/bluesky-scraper")
result = tool.invoke({"run_input": {"mode": "searchPosts", "queries": ["apify"]}})
print(result)
```

run-sync waits up to 300 seconds; for longer runs start a run and use a webhook. LlamaIndex and MCP: https://cliqtomedia.com/actors/ai-agents/

## Use cases with this tool

- [Hear what people say about you](https://cliqtomedia.com/actors/use-cases/social-listening/): Find what people say about your brand and your topic on Bluesky, Hacker News, YouTube and more.

## Similar tools

- [Substack Newsletter Scraper](https://cliqtomedia.com/actors/substack-newsletter-scraper/)
- [Hacker News Stories & Comments Scraper](https://cliqtomedia.com/actors/hacker-news-stories-comments-scraper/)
- [Bilibili Scraper: Videos, Comments & Creators, No Login](https://cliqtomedia.com/actors/bilibili-scraper/)
- [Medium Article Scraper: Tags, Authors & Publications](https://cliqtomedia.com/actors/medium-articles-scraper/)
- [Pinterest Search Scraper: Pins & Boards, No Login](https://cliqtomedia.com/actors/pinterest-search-scraper/)
- [Product Hunt Launches Scraper – Daily Top, No Login](https://cliqtomedia.com/actors/product-hunt-launches/)
