# Bluesky Scraper & API - Posts, Search, Profiles, Followers (`apeye/bluesky-scraper`) Actor

Scrape Bluesky through the official API: keyword post search, posts with like, repost and reply counts, profiles with follower totals, follower lists, user search and full threads. Clean JSON for social listening, influencer research and AI agents. No login needed except for post search.

- **URL**: https://apify.com/apeye/bluesky-scraper.md
- **Developed by:** [Pasquale Nirta](https://apify.com/apeye) (community)
- **Categories:** Social media, AI, Automation
- **Features:** Limited permissions
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 results

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 Scraper: posts, search, profiles, followers and threads

Collect public data from Bluesky through the official AT Protocol API. Give it a list of handles, search terms or post URLs and it returns clean JSON rows: posts with full engagement counts, profiles with follower and post totals, follower and following lists, user search results, or a complete reply thread.

Because it reads Bluesky's official API rather than scraping HTML, results are fast and stable. No login or cookies are needed for anything except keyword post search, which Bluesky itself gates behind login (a revocable app password of your own).

### What it does

| Operation | You provide | You get |
|---|---|---|
| Posts | handles or profile URLs | Each user's posts with likes, reposts, replies, quotes, images, link cards |
| Profiles | handles or profile URLs | Bio, follower count, following count, post count per user |
| Followers | handles | The accounts following each user |
| Following | handles | The accounts each user follows |
| Search users | keywords | Matching accounts with profile data |
| Search posts | keywords + your app password | Latest posts matching each keyword, with engagement counts |
| Thread | post URLs | The post and every reply beneath it, flattened |

Typical uses: social listening and brand monitoring, influencer research, audience analysis, tracking what a set of accounts posts over time (run it on a schedule and diff by post URI), and feeding Bluesky data to AI agents. The Actor works from Apify's MCP server, so agents in Claude, Cursor and similar tools can call it directly.

### Input

```json
{
    "operation": "posts",
    "targets": ["bsky.app", "https://bsky.app/profile/atproto.com"],
    "maxItemsPerTarget": 100,
    "includeReplies": false,
    "includeReposts": false
}
```

Targets are flexible: handles (`name.bsky.social`), custom-domain handles (`bsky.app`), DIDs, or profile URLs all work. For the thread operation, paste a post URL straight from your browser.

### Output

One row per item. Post rows:

```json
{
    "type": "post",
    "uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l",
    "url": "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l",
    "handle": "bsky.app",
    "displayName": "Bluesky",
    "text": "…",
    "createdAt": "2026-07-01T18:04:12.000Z",
    "likeCount": 4120,
    "repostCount": 388,
    "replyCount": 214,
    "quoteCount": 77,
    "isReply": false,
    "images": ["https://cdn.bsky.app/img/feed_fullsize/..."],
    "externalLink": null,
    "source": "bsky.app"
}
```

User rows carry `handle`, `displayName`, `description`, `followersCount`, `followsCount`, `postsCount` and `avatar`.

Export as JSON, CSV, Excel or RSS, or read the dataset through the Apify API from your own code.

### Pricing

Pay per event: a small fee when a run starts, then a fee per row in your results. Duplicate items are filtered out before charging.

### Use from AI agents

This Actor works out of the box with AI agents through [Apify's MCP server](https://mcp.apify.com). Connect an agent (Claude, Cursor, or anything MCP-compatible) to Apify and it can call `apeye/bluesky-scraper` directly: ask "what has this account posted about pricing this month, and who are its most-followed followers?" and the agent picks the operations, runs them and reads the results. Row types and field names are kept flat and predictable so models can consume them without custom parsing.

### FAQ

**Is this legal?** Yes. The Actor reads the official, publicly documented AT Protocol API that serves Bluesky's own app. Only public data is collected, the same data anyone sees without logging in.

**How does post search work?** Bluesky requires login for post search (their rule, not ours), so the searchPosts operation takes your handle and an app password. App passwords are Bluesky's official mechanism for third-party tools: create one at Settings > App Passwords, revoke it any time, and it never grants access to your main password or account settings. The credential field is stored encrypted and used only to log in. Every other operation needs no credentials at all.

**How fresh is the data?** It's read live from the API at run time. Engagement counts are the values at the moment of the run.

**What about rate limits?** The Actor paces itself within Bluesky's public API limits and retries transient errors automatically.

### Support

If something breaks or you need another operation (lists, likes of a post, feeds), open an issue on the Issues tab. I check most days and usually reply within a day or two.

# Actor input Schema

## `operation` (type: `string`):

The kind of data to collect. Each run does one operation; results land in the dataset as one row per item.

## `targets` (type: `array`):

What to scrape, one entry per line. For <b>posts / profiles / followers / following</b>: Bluesky handles (<code>bsky.app</code>, <code>name.bsky.social</code>), DIDs, or profile URLs (<code>https://bsky.app/profile/handle</code>). For <b>searchUsers</b>: search keywords. For <b>thread</b>: post URLs (<code>https://bsky.app/profile/handle/post/xyz</code>) or <code>at://</code> URIs.

## `maxItemsPerTarget` (type: `integer`):

Cap on collected items per target (per handle, query or thread).

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

When scraping author feeds, keep the user's replies as well as their original posts.

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

When scraping author feeds, keep items the user reposted (marked with repostedBy).

## `blueskyIdentifier` (type: `string`):

Your Bluesky handle, e.g. <code>name.bsky.social</code>. Only needed for the searchPosts operation — Bluesky requires login for post search. All other operations need no credentials.

## `blueskyAppPassword` (type: `string`):

An app password created at Bluesky Settings > App Passwords (not your main account password). Stored encrypted, used only to log in for post search, revocable any time.

## Actor input object example

```json
{
  "operation": "posts",
  "targets": [
    "bsky.app"
  ],
  "maxItemsPerTarget": 100,
  "includeReplies": false,
  "includeReposts": false
}
```

# Actor output Schema

## `items` (type: `string`):

All collected items as JSON.

## `csvExport` (type: `string`):

The same results as a CSV download.

# 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 = {
    "targets": [
        "bsky.app"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("apeye/bluesky-scraper").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 = { "targets": ["bsky.app"] }

# Run the Actor and wait for it to finish
run = client.actor("apeye/bluesky-scraper").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 '{
  "targets": [
    "bsky.app"
  ]
}' |
apify call apeye/bluesky-scraper --silent --output-dataset

```

## MCP server setup

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

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/oZS0g003uApU3oSQR/builds/bCp8Jb5kPzmK12hfp/openapi.json
