# Bluesky Scraper: Posts, Search, Profiles & Followers (`kvozi/bluesky-posts-profiles-followers`) Actor

Bluesky data from the official AT Protocol API: search posts by keyword, get any account's posts, profiles with follower counts, followers and follows lists, and full reply threads. No browser, no proxies.

- **URL**: https://apify.com/kvozi/bluesky-posts-profiles-followers.md
- **Developed by:** [Kvozi](https://apify.com/kvozi) (community)
- **Categories:** Social media, Lead generation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 item 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

Get Bluesky data as clean JSON from the official, public AT Protocol API. No browser, no proxies and no CAPTCHA handling.

The actor has six modes:

- **authors**: recent posts of any account, with likes, reposts, replies, links, hashtags and images.
- **profiles**: profile details with follower, following and post counts (up to 25 accounts per request).
- **followers** / **follows**: the followers or the followed accounts of any account, with their profiles.
- **thread**: a post and all replies to it, from a `bsky.app` post link.
- **search**: posts matching keywords, sorted by latest or top, with date and language filters.

Use it to monitor brand mentions, collect leads from a niche community, track a competitor's posts or research an audience.

### Input

```json
{
  "mode": "authors",
  "handles": ["bsky.app", "jay.bsky.team"],
  "includeReplies": false,
  "minLikes": 5,
  "since": "2026-10-01",
  "onlyNew": false,
  "maxItems": 200
}
```

- `mode`: one of `search`, `authors`, `profiles`, `followers`, `follows`, `thread`.
- `handles`: accounts for `authors`, `profiles`, `followers` and `follows` (for example `bsky.app` or a `did:plc:` id; `@` and `https://bsky.app/profile/...` links are accepted).
- `searchQueries`: keywords for `search`. `sort`: `latest` or `top`. `language`: for example `en`.
- `postUrls`: post links for `thread`, such as `https://bsky.app/profile/bsky.app/post/3l...`.
- `since` / `until`: keep only posts created in this period.
- `minLikes`, `includeReplies`, `includeReposts`: post filters.
- `onlyNew`: return only items you have not received before for the same input. For posts by account, latest search and followers lists this means items newer than your previous run, so a daily run gives you just what is new. `stateKey` shares this memory between inputs.
- `maxItems`: maximum items per run; `maxItemsPerQuery` limits each handle or query.

#### Search needs a Bluesky app password

Bluesky does not allow post search without signing in. For `search`, enter your Bluesky handle in `blueskyHandle` and an **app password** in `blueskyAppPassword` (create one in Bluesky: Settings → Privacy and security → App passwords). Never use your main password. The app password is stored as a secret input and is used only to call Bluesky's own API. All other modes work without signing in.

### Output

Posts:

```json
{
  "type": "post",
  "uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l",
  "url": "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l",
  "authorHandle": "bsky.app",
  "authorName": "Bluesky",
  "text": "…",
  "createdAt": "2026-10-20T16:00:00.000Z",
  "langs": ["en"],
  "replyCount": 120, "repostCount": 340, "likeCount": 2100, "quoteCount": 45,
  "isReply": false, "isRepost": false,
  "hashtags": [], "links": ["https://…"], "mentions": [], "images": [],
  "externalLink": {"uri": "https://…", "title": "…"},
  "scrapedAt": "2026-10-27T15:00:00Z"
}
```

Profiles (also used for followers and follows, with `relation` and `relationOf`; Bluesky's followers lists do not include follower counts, so run `profiles` mode on the handles you need them for). `handle` is empty when Bluesky reports the account's handle as invalid; `did` and `url` still identify it:

```json
{
  "type": "profile",
  "did": "did:plc:…",
  "handle": "example.bsky.social",
  "url": "https://bsky.app/profile/example.bsky.social",
  "displayName": "Example",
  "description": "…",
  "followersCount": 1520, "followsCount": 310, "postsCount": 890,
  "relation": "follower",
  "relationOf": "bsky.app",
  "scrapedAt": "2026-10-27T15:00:00Z"
}
```

A run summary (items returned per handle or query, accounts not found, errors) is saved as `OUTPUT` in the key-value store.

### Pricing

You pay per item returned. Failed lookups and accounts that were not found are free.

### Notes

- Only public data is read, the same data anyone sees on bsky.app without an account. Accounts that hide themselves from logged-out viewers are skipped.
- Requests are paced to respect Bluesky's API rate limits.
- This actor is not affiliated with Bluesky Social PBC.

# Actor input Schema

## `mode` (type: `string`):

Search needs your own Bluesky handle and app password if Bluesky asks for sign-in.

## `searchQueries` (type: `array`):

For search: words, hashtags (#ai), phrases in quotes, or Bluesky operators like from:handle.

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

For posts, profiles, followers and follows: handles like bsky.app or @alice.bsky.social, or profile URLs.

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

For thread: links like https://bsky.app/profile/<handle>/post/<id>.

## `sort` (type: `string`):

For search.

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

Only posts created on or after this date.

## `until` (type: `string`):

Only posts created before this date.

## `language` (type: `string`):

Two-letter code such as en or de.

## `minLikes` (type: `integer`):

Skip posts with fewer likes.

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

Keep posts that are replies to other posts.

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

For account posts: also return posts the account reposted.

## `onlyNew` (type: `boolean`):

Return only items not returned before for the same query (or the same stateKey).

## `maxItems` (type: `integer`):

Maximum items per run, shared evenly between queries or accounts.

## `maxItemsPerQuery` (type: `integer`):

Optional; overrides the even split.

## `blueskyHandle` (type: `string`):

Only needed if search asks for sign-in.

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

Create one at Settings > Privacy and security > App passwords. Never use your main password. It is used only to sign in for this run.

## `stateKey` (type: `string`):

Optional name for the only-new history.

## Actor input object example

```json
{
  "mode": "authors",
  "searchQueries": [],
  "handles": [
    "bsky.app"
  ],
  "postUrls": [],
  "sort": "latest",
  "minLikes": 0,
  "includeReplies": true,
  "includeReposts": false,
  "onlyNew": false,
  "maxItems": 20
}
```

# Actor output Schema

## `items` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("kvozi/bluesky-posts-profiles-followers").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("kvozi/bluesky-posts-profiles-followers").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 '{}' |
apify call kvozi/bluesky-posts-profiles-followers --silent --output-dataset

```

## MCP server setup

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

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/VQRXIDqFlycSjtcoc/builds/qGGJPMFmGrchaRsV0/openapi.json
