# Bluesky Posts Scraper – Profiles & Threads, No Login (`forevertools/bluesky-posts`) Actor

Bluesky scraper for posts from any public profile feed or thread via the official public API — no login, no cookies. Social media data: text, date, author, likes, reposts, replies, quotes, links, images, language. $0.50 per 1,000 posts.

- **URL**: https://apify.com/forevertools/bluesky-posts.md
- **Developed by:** [Forever Tools](https://apify.com/forevertools) (community)
- **Categories:** Social media, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 1,000 post scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Bluesky Posts Scraper - profiles & threads, no login

Scrape public Bluesky posts from **profile feeds** and **reply threads** using the official public AppView API
(`public.api.bsky.app`). No login, no cookies, no browser, no app password. One dataset row per post, with likes,
reposts, replies, quotes, links, images and hashtags.

Great for: brand and account monitoring, tracking what a list of accounts posts, exporting a reply thread for
analysis, community research, and feeding public posts into your own analytics or LLM pipelines.

### How it works

1. You give handles (or DIDs / profile links) and/or post links. Handles are lowercased, a leading `@` is stripped, and duplicates are removed.
2. For each profile, the actor pages through the author feed (100 posts per request), newest first, until it reaches `maxItemsPerSource`, your `since` date, or the end of the feed.
3. For each post link, it resolves the author's handle to a DID if needed, then fetches the post's reply thread (up to 10 levels deep) and flattens it into rows with a `threadDepth`.
4. Every post is normalized into one dataset row and deduplicated by post URI across all sources in the run.

Up to 3 sources are processed in parallel. HTTP 429 and 5xx responses and network errors are retried with backoff (up to 4 retries).

### Features

- **Profiles**: newest-first posts from any handle, DID or profile link; optional replies, reposts and a `since` date cutoff.
- **Threads**: paste a `https://bsky.app/profile/<handle>/post/<id>` link (or an `at://` URI) and get the post plus its replies (nested, with `threadDepth`).
- Engagement: likes, reposts, replies, quotes.
- Links (from text and link cards), images (with alt text; video posts return the thumbnail and playlist URL), quoted post URI, hashtags, mentioned DIDs, languages.
- Deduplicated by post URI across all sources in a run.
- A bad handle or link never crashes the run: you get a row with `error` set (not charged).

### Use cases

#### Social media monitoring

Schedule a daily run over a list of brand, competitor or newsroom accounts with `since` set to yesterday, and collect only new posts with their engagement counts.

#### Thread and reply analysis

Export every reply under a post to study sentiment, questions or objections. Each row has `threadDepth`, `replyParentUri` and `replyRootUri` so the tree can be rebuilt.

#### Research and datasets

Build a corpus of public posts from chosen accounts, with language tags, hashtags, link cards and quoted-post references, as JSON, CSV or Excel.

#### AI agents and LLM pipelines

Call the actor through the Apify MCP server or API when an agent needs current public posts from a specific account.

### Input

| Field | Description |
|---|---|
| `handles` | Handles, DIDs or profile URLs, e.g. `bsky.app`, `@jay.bsky.team`, `https://bsky.app/profile/nytimes.com` |
| `postUrls` | Post links or `at://` URIs; returns the post and its reply thread |
| `maxItemsPerSource` | Max posts per handle/thread (default 100, 1 to 10,000) |
| `includeReplies` | Include the author's replies in profile feeds (default true) |
| `includeReposts` | Include reposts in profile feeds, flagged `isRepost` (default false) |
| `since` | ISO date, e.g. `2026-09-01`; stop paging a profile at older posts (profiles only) |
| `includeThreadRoot` | Also return the linked post itself (default true) |

### Output (one dataset row per post)

```json
{
  "uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3mw2cdr44fc2a",
  "url": "https://bsky.app/profile/bsky.app/post/3mw2cdr44fc2a",
  "text": "If you're in line to vote for @bsky38.com, please stay in line! ...",
  "createdAt": "2026-09-21T18:04:06.128Z",
  "author": { "handle": "bsky.app", "displayName": "Bluesky", "did": "did:plc:z72i7hdynmk6r22z27h6tvur" },
  "likeCount": 1200, "repostCount": 90, "replyCount": 97, "quoteCount": 12,
  "langs": ["en"], "links": [], "linkCards": [], "images": [], "embedType": "record",
  "quotedPostUri": "at://did:web:bsky38.com/app.bsky.feed.post/3muphbj35cs2h",
  "hashtags": [], "mentionDids": ["did:web:bsky38.com"],
  "isReply": false, "replyParentUri": null, "replyRootUri": null,
  "isRepost": false, "repostedBy": null,
  "source": "bsky.app", "sourceType": "handle", "scrapedAt": "...", "error": null
}
```

Rows also include `indexedAt`. Thread rows also carry `threadDepth` (0 = linked post, 1 = direct reply, ...). Only public post content and the
author's public handle, display name and DID are returned. No emails, no contact details, no follower lists.

### Pricing

Pay per event: **$0.0005 per post** ($0.50 per 1,000). Apify platform usage is billed separately as usual.

- 1,000 posts = $0.50
- 20 accounts x 100 posts = 2,000 posts = $1.00
- One reply thread with 350 replies (plus the root) = 351 posts = about $0.18

**Charged:** each post row saved to the dataset. **Not charged:** error rows (bad handle, post not found) and duplicate posts already returned by another source in the same run. If you set a maximum charge for the run, the actor stops before exceeding it.

### Limitations

- No keyword search: Bluesky's public API currently rejects unauthenticated keyword search (HTTP 403), and this actor does not use logins. Use profiles or thread links instead.
- Threads: up to 10 levels of replies as returned by the API; very large threads may be truncated by the API. Parent posts above the linked post are not included.
- Counts are a snapshot at scrape time.
- Deleted, blocked, private or taken-down content is not available.
- Not affiliated with Bluesky. Built and maintained with AI assistance; problems or requests go to the Issues tab.

### FAQ

**Do I need a Bluesky account?** No. Everything comes from Bluesky's public, unauthenticated API.

**Can I search posts by keyword or hashtag?** Not in this version (see Limitations). Hashtags used in each post are returned in `hashtags`, so you can filter scraped posts yourself.

**How far back can I go on a profile?** As far as the author feed pages go; set `maxItemsPerSource` and/or `since`.

**Why did a profile return fewer posts than expected?** Deleted, blocked or moderated posts are not returned by
the API, reposts are skipped unless enabled, and posts already returned by another source in the same run are deduplicated.

**Can I get all replies to a post?** Yes, pass the post link in `postUrls`. Replies come back nested up to 10 levels, each with `threadDepth`.

**Is this legal / allowed?** It reads only public data through Bluesky's documented public API with modest
request rates. You are responsible for how you use the data (respect privacy law and Bluesky's terms).

### Related tools

Other actors by the same developer (same flat pay-per-result pricing, no subscription):

- [App Store Reviews Scraper – Apple iOS, Multi-Country](https://apify.com/forevertools/apple-app-store-reviews)
- [Article Scraper & Text Extractor – Clean Markdown for LLM/RAG](https://apify.com/forevertools/article-extractor)
- [Job Postings & Career Page Scraper – Workday, Greenhouse, Lever](https://apify.com/forevertools/ats-company-jobs)
- [Company Enrichment from Domain (Logo, Socials, Tech)](https://apify.com/forevertools/company-website-enrichment)
- [DNS Lookup & WHOIS Domain Checker — SPF/DMARC, SSL Expiry](https://apify.com/forevertools/domain-whois-dns-ssl)
- [Email Validator & MX Record Checker – Bulk, Disposable, Role](https://apify.com/forevertools/email-syntax-mx-checker)
- [Bulk PageSpeed Insights, Lighthouse & Core Web Vitals](https://apify.com/forevertools/pagespeed-core-web-vitals)
- [PDF Extractor & Parser – Bulk PDF to Text with Metadata](https://apify.com/forevertools/pdf-to-text-extractor)
- [SEO Audit Crawler & Broken Link Checker – Website Health](https://apify.com/forevertools/website-seo-audit)
- [Sitemap Extractor & Bulk URL Status Checker](https://apify.com/forevertools/sitemap-url-status-checker)
- [Steam Reviews Scraper – Game Reviews & App Details](https://apify.com/forevertools/steam-reviews)
- [Website Technology Detector – Tech Stack, CMS & Analytics](https://apify.com/forevertools/website-tech-stack-detector)
- [Website Screenshot API – Bulk Full Page PNG, JPEG & PDF](https://apify.com/forevertools/website-screenshot)

### Integrations

Run it from the Apify API, a schedule, or no-code tools: the Apify apps for **Zapier**, **Make** and **n8n** can start any public actor ("Run Actor") and read its dataset. AI agents can call it through the **Apify MCP server**.

### Ready-made examples

One-click tasks you can run or copy and adapt:

- [Export recent posts from Bluesky accounts](https://apify.com/forevertools/bluesky-posts/examples/bluesky-account-posts-export)
- [Get Bluesky posts from an account since a given date](https://apify.com/forevertools/bluesky-posts/examples/bluesky-posts-since-date)
- [Monitor posts from Bluesky developer & protocol accounts](https://apify.com/forevertools/bluesky-posts/examples/bluesky-developer-accounts-posts)

# Actor input Schema

## `handles` (type: `array`):

Bluesky handles, DIDs or profile links (e.g. bsky.app, @jay.bsky.team, https://bsky.app/profile/nytimes.com). Newest posts first.

## `postUrls` (type: `array`):

Bluesky post links (https://bsky.app/profile/<handle>/post/<id>) or at:// URIs. Returns the post and its reply thread.

## `maxItemsPerSource` (type: `integer`):

Maximum posts returned per handle or per thread.

## `includeReplies` (type: `boolean`):

Include the author's replies to other posts in profile feeds.

## `includeReposts` (type: `boolean`):

Include posts the author reposted (marked isRepost=true).

## `since` (type: `string`):

ISO date, e.g. 2026-09-01. Stops paging a profile once older posts are reached.

## `includeThreadRoot` (type: `boolean`):

For post links, also return the linked post itself (not only its replies).

## Actor input object example

```json
{
  "handles": [
    "bsky.app"
  ],
  "maxItemsPerSource": 100,
  "includeReplies": true,
  "includeReposts": false,
  "includeThreadRoot": true
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "handles": [
        "bsky.app"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("forevertools/bluesky-posts").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "handles": ["bsky.app"] }

# Run the Actor and wait for it to finish
run = client.actor("forevertools/bluesky-posts").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "handles": [
    "bsky.app"
  ]
}' |
apify call forevertools/bluesky-posts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,forevertools/bluesky-posts"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/gQrpSfySO1PPUmBdt/builds/GMHM3kUGxKNGea8cv/openapi.json
