# Bluesky Search Scraper (`indomitably_doctor/bluesky-search-scraper`) Actor

Search Bluesky posts and users, or pull full author feeds, via the AT Protocol API. Clean JSON with engagement counts, embeds and profile data — built for social listening.

- **URL**: https://apify.com/indomitably\_doctor/bluesky-search-scraper.md
- **Developed by:** [Billy DC](https://apify.com/indomitably_doctor) (community)
- **Categories:** Automation, Social media
- **Stats:** 2 total users, 1 monthly users, 36.4% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 receive 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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Bluesky Search Scraper

Search [Bluesky](https://bsky.app) posts, find user profiles, or export any account's feed as clean structured data. Built on Bluesky's AppView API. Author feeds and profile search need no login; for keyword post search, add a free Bluesky app password (see below) so it works from any IP.

### Who is this for?

- **Brand & social listening**: track mentions of your product, competitors or campaign hashtags
- **Journalists & researchers**: collect public conversation around breaking news or topics over time
- **Marketers**: find relevant creators and measure engagement (likes, reposts, replies, quotes)
- **Data teams**: feed dashboards and sentiment pipelines with fresh Bluesky data

### Modes

| Mode | What it does | Required input |
|---|---|---|
| `searchPosts` | Full-text post search, sorted by `latest` or `top` | `query` |
| `searchUsers` | Profile search by name/handle/bio | `query` |
| `authorFeed` | Export one account's posts and reposts | `authorHandle` |

`query` supports Bluesky's search operators: `"exact phrase"`, `from:handle.bsky.social`, `#hashtag`, etc.

### Input example

```json
{
    "mode": "searchPosts",
    "query": "climate change",
    "sort": "latest",
    "sinceDate": "2026-07-01",
    "untilDate": "2026-07-20",
    "maxItems": 500,
    "blueskyIdentifier": "me.bsky.social",
    "blueskyAppPassword": "xxxx-xxxx-xxxx-xxxx"
}
```

### Post search and the datacenter-IP block (read this if a search run fails with HTTP 403)

Bluesky's *unauthenticated* search backend blocks requests from datacenter IPs — which includes Apify's servers. Two ways to make `searchPosts` work reliably:

1. **Recommended — free**: add `blueskyIdentifier` (your handle or email) and `blueskyAppPassword` to the input. Create an app password in the Bluesky app under **Settings → Privacy and security → App passwords** (never use your main password; the field is stored encrypted by Apify). Authenticated search works from any IP.
2. Alternatively, set the **Proxy configuration** input to Apify **residential** proxy (paid Apify plans). The actor also auto-tries this escalation when it hits a 403.

`authorFeed` and `searchUsers` are not affected and work without login or proxy.

### Output

Post item (modes `searchPosts` and `authorFeed`):

```json
{
    "uri": "at://did:plc:6kos45lixtga3pdwuncvh32x/app.bsky.feed.post/3mqc36slinc2m",
    "url": "https://bsky.app/profile/paretooptimizer.bsky.social/post/3mqc36slinc2m",
    "authorHandle": "paretooptimizer.bsky.social",
    "authorDisplayName": "Pareto Optimizer",
    "authorDid": "did:plc:6kos45lixtga3pdwuncvh32x",
    "text": "I know this guy has a Bluesky account.",
    "createdAt": "2026-07-10T11:46:11.858Z",
    "likeCount": 6565,
    "repostCount": 544,
    "replyCount": 152,
    "quoteCount": 14,
    "langs": ["en"],
    "embeds": [{ "type": "quote", "url": "https://bsky.app/profile/dexerto.bsky.social/post/3mqbs2zzdi22y" }],
    "timestamp": "2026-07-24T12:00:00.000Z"
}
```

User item (mode `searchUsers`):

```json
{
    "did": "did:plc:wmho6q2uiyktkam3jsvrms3s",
    "handle": "nbcnews.com",
    "url": "https://bsky.app/profile/nbcnews.com",
    "displayName": "NBC News",
    "description": "News updates from around the world, all day, every day.",
    "followersCount": null,
    "createdAt": "2023-05-31T01:09:28.017Z",
    "verifiedStatus": "valid",
    "timestamp": "2026-07-24T12:00:00.000Z"
}
```

`embeds` summarizes attachments: `external` (link cards, with URL/title), `image` (full-size CDN URL + alt text), `video`, and `quote` (link to the quoted post).

### Pricing

The actor charges per item returned (`result-item` event). A run that finds 300 posts costs 300 events — you pay only for delivered data.

### Honest limitations

- Only **public** posts and profiles indexed by Bluesky's AppView are returned; blocked/private data is not accessible.
- `searchUsers` results come from the profile search endpoint, which does **not** include follower counts (`followersCount` is `null` there). `authorFeed` and post authors do not include follower counts either.
- `sinceDate`/`untilDate` are applied server-side for post search; for `authorFeed` they are applied client-side while paginating (the API has no date filter there).
- Bluesky search relevance and `hitsTotal` are approximate; deep pagination of huge result sets may be truncated by the API.
- `authorFeed` includes reposts, marked with `"isRepost": true` — filter them out downstream if you only want original posts.
- The public AppView applies IP-based rate limits. The actor throttles itself (sequential requests with delays) and backs off on HTTP 429, but very large `maxItems` runs will be slow by design.

### Usage tips

- Track a hashtag daily: schedule `{ "mode": "searchPosts", "query": "#buildinpublic", "sort": "latest" }`
- Find influencers in a niche: `{ "mode": "searchUsers", "query": "machine learning" }`
- Archive an account: `{ "mode": "authorFeed", "authorHandle": "bsky.app", "maxItems": 5000 }`

# Actor input Schema

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

What to fetch: search posts by keyword, search user profiles, or export one author's feed.

## `query` (type: `string`):

Keyword(s) to search for. Used by Search posts and Search users modes (defaults to 'news' if omitted). Supports Bluesky search operators like from:handle, quoted phrases, and #hashtags.

## `authorHandle` (type: `string`):

Handle whose feed to export in 'Author feed' mode, e.g. 'bsky.app' or '@nytimes.com'.

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

Ranking for post search results.

## `sinceDate` (type: `string`):

Only posts created at or after this time. ISO datetime or YYYY-MM-DD. Applies to 'Search posts' mode (server-side) and 'Author feed' mode (client-side).

## `untilDate` (type: `string`):

Only posts created before this time. ISO datetime or YYYY-MM-DD. Applies to 'Search posts' mode (server-side) and 'Author feed' mode (client-side).

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

Maximum number of items to return (1-10000).

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

Your Bluesky handle or email, e.g. 'me.bsky.social'. Together with an app password this enables authenticated search, which works from any IP — recommended for 'Search posts' mode. Create a free app password in the Bluesky app: Settings → Privacy and security → App passwords. Never enter your main account password.

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

App password for the handle above (format xxxx-xxxx-xxxx-xxxx). Stored encrypted by Apify. Only needed for the search modes; 'Author feed' works without login.

## `proxy` (type: `object`):

Optional. Without login, 'Search posts' from datacenter IPs gets blocked by Bluesky (HTTP 403); the actor auto-escalates to Apify residential proxy on 403. Providing a Bluesky app password above avoids the need for a proxy entirely. Set this to force a specific proxy from the start.

## Actor input object example

```json
{
  "mode": "authorFeed",
  "query": "climate change",
  "authorHandle": "bsky.app",
  "sort": "latest",
  "sinceDate": "2026-07-01",
  "untilDate": "2026-07-20",
  "maxItems": 100
}
```

# 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 = {
    "mode": "authorFeed",
    "query": "news"
};

// Run the Actor and wait for it to finish
const run = await client.actor("indomitably_doctor/bluesky-search-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 = {
    "mode": "authorFeed",
    "query": "news",
}

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

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

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

```

## CLI example

```bash
echo '{
  "mode": "authorFeed",
  "query": "news"
}' |
apify call indomitably_doctor/bluesky-search-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=indomitably_doctor/bluesky-search-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

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