# 🦋 Bluesky Scraper - Posts, Profiles & Search (`benthepythondev/bluesky-scraper`) Actor

Scrape Bluesky (bsky.app) via the public AT Protocol API — no login needed. Get a user's posts, profile data, followers/follows, or search posts by keyword/hashtag. Clean JSON with engagement counts, links & images.

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

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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 Scraper — Posts, Profiles, Followers & Keyword Search

Extract **Bluesky** (bsky.app) data through the official **AT Protocol** API — a
user's posts and timeline, full profile stats, their followers/follows graph, or a
**keyword/hashtag search** across the network. Bluesky is the fastest-growing open
social network, and it's still wide open for data: pull clean, structured JSON with
engagement counts, images, links and author details — **no login required** for
posts, profiles and followers. Export to JSON/CSV/Excel, run on a schedule, call via
API, or connect to Make, Zapier or n8n.

### 🦋 What is the Bluesky Scraper?

It turns any Bluesky account or search into a structured dataset. Pick a mode — a
user's posts, a profile, a follower/follows list, or a keyword search — give it
handles (like `bsky.app` or `nytimes.com`) or search terms, and it returns every
matching record with full engagement metrics straight from the public AT Protocol
endpoints. Because it reads a clean JSON API instead of a headless browser, it's fast
and cheap, with no residential proxy needed.

#### What data does it extract?

- **Post text, created date and language** for every post
- **Engagement counts** — likes, reposts, replies and quotes
- **Author info** — handle, display name, DID and avatar
- **Images and external link** attached to each post
- **Reply / repost flags** (`is_reply`, `is_repost`) and who reposted it
- **Profile stats** — followers, follows, post count, bio, banner and join date
- **Follower / follows lists** with each account's profile
- **Post and profile URLs**, plus a `scraped_at` timestamp

### ⬇️ Input

Pick a `mode`, then supply `handles` (for posts/profile/followers/follows) or
`searchTerms` (for keyword search):

| Field | Description |
|-------|-------------|
| `mode` | `posts`, `search`, `profile`, `followers` or `follows` |
| `handles` | Accounts to scrape (handles or DIDs), e.g. `bsky.app`, `nytimes.com`, `did:plc:...` |
| `searchTerms` | Keywords or #hashtags to search (search mode) |
| `maxItems` | Max records to return, split across handles/terms (1–50000) |
| `includeReplies` | Include the user's replies in posts mode |
| `includeReposts` | Include reposts (boosts) in the user's feed |
| `identifier` / `appPassword` | Optional Bluesky handle + **app password** to make keyword search reliable |
| `proxyConfiguration` | Optional Apify Proxy for IP rotation on large runs |

#### Example input

```json
{
  "mode": "search",
  "searchTerms": ["#immobilien", "bitcoin"],
  "maxItems": 500,
  "identifier": "you.bsky.social",
  "appPassword": "xxxx-xxxx-xxxx-xxxx"
}
````

### ⬆️ Output

Every post (or profile/account) is one clean row — view it as a **table**, or export
**JSON / CSV / Excel**:

```json
{
  "uri": "at://did:plc:abc.../app.bsky.feed.post/3kxyz...",
  "url": "https://bsky.app/profile/bsky.app/post/3kxyz...",
  "text": "Welcome to Bluesky!",
  "created_at": "2026-06-26T09:00:00.000Z",
  "indexed_at": "2026-06-26T09:00:02.000Z",
  "language": "en",
  "author_handle": "bsky.app",
  "author_display_name": "Bluesky",
  "author_did": "did:plc:abc...",
  "like_count": 1240,
  "repost_count": 312,
  "reply_count": 88,
  "quote_count": 15,
  "is_reply": false,
  "is_repost": false,
  "reposted_by": null,
  "images": [],
  "external_link": null,
  "scraped_at": "2026-06-26T15:30:00.000Z"
}
```

### 💡 Use cases

- **👂 Social listening & brand monitoring:** track every mention of a brand, product or topic across the network everyone's migrating to.
- **📈 Trend & sentiment analysis:** pull keyword/hashtag streams and feed them straight into an LLM.
- **🔍 Influencer & audience research:** profile stats plus follower/follows graphs to map who matters in a niche.
- **🎯 Lead generation:** find accounts posting about a topic or following a competitor.

### ❓ FAQ

**How do I scrape Bluesky posts?** Set `mode: posts`, add one or more `handles` (e.g.
`bsky.app`), and Run. You get every post with text, date, language, engagement counts,
images and the post URL.

**Do I need an API key or login?** No — posts, profiles and follower/follows graphs
work with no login at all, straight from the public AT Protocol endpoints.

**Why does keyword search need an app password?** Bluesky's search endpoint is more
reliable when authenticated. Create a Bluesky **app password** (Settings → App
Passwords — never your main password) and pass it as `identifier` + `appPassword`.
Without it, search may return few or no results; the other modes stay login-free.

**What's a DID?** A DID (`did:plc:...`) is Bluesky's permanent account ID. You can
pass either a handle or a DID in `handles`.

**Can I get a user's followers and follows?** Yes — use `mode: followers` or
`mode: follows` to pull each account in their network with full profile data.

**How many records can it return?** Up to your `maxItems` cap (up to 50,000); it
paginates automatically and splits the cap across the handles or terms you give it.

**Is there a rate limit?** The public API is generous. The Actor paginates politely
and backs off automatically on throttling, so large runs just keep flowing.

**Can I run it on a schedule or via API?** Yes — schedule recurring runs in Apify,
call it via the API/SDK, or connect it to Make, Zapier or n8n.

**Is scraping Bluesky legal?** It reads publicly available data via Bluesky's own
public API. Use it responsibly for research and monitoring, and follow applicable
laws and Bluesky's terms.

### 🔗 You might also like

- **[Mastodon Scraper](https://apify.com/benthepythondev/mastodon-scraper)** — posts, hashtags & trends from any instance
- **[Lemmy Scraper](https://apify.com/benthepythondev/lemmy-scraper)** — the federated Reddit alternative
- **[Reddit Scraper](https://apify.com/benthepythondev/reddit-scraper)** — posts, comments & communities
- **[Instagram Scraper](https://apify.com/benthepythondev/instagram-scraper)** — posts, profiles & hashtags

***

**Keywords:** Bluesky scraper, bsky scraper, AT Protocol API, Bluesky API, Bluesky posts, Bluesky search, Bluesky followers, Bluesky profile scraper, social media scraper, social listening, atproto, fediverse scraper, Bluesky data export, sentiment analysis, Twitter alternative data.

# Actor input Schema

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

posts = a user's posts/timeline; search = keyword/hashtag search; profile = account data; followers / follows = a user's network.

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

Accounts to scrape (for posts / profile / followers / follows), e.g. 'bsky.app', 'nytimes.com', or a 'did:plc:...'. The leading @ is optional.

## `searchTerms` (type: `array`):

Keywords or #hashtags to search posts for, e.g. 'bitcoin', '#immobilien'. Used only when mode = search.

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

Maximum number of records to return (split across the handles/terms).

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

Include the user's replies in posts mode (otherwise only top-level posts).

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

Include reposts (boosts) in the user's feed in posts mode.

## `identifier` (type: `string`):

Optional: your Bluesky handle or email. Only needed to make keyword search more reliable. Leave empty for posts/profile/followers.

## `appPassword` (type: `string`):

Optional: a Bluesky APP PASSWORD (Settings > App Passwords — NOT your main password). Used only to authenticate keyword search.

## `proxyConfiguration` (type: `object`):

Optional. The Bluesky API is public, so a proxy is not required; Apify Proxy (auto) is fine for IP rotation on large runs.

## Actor input object example

```json
{
  "mode": "posts",
  "handles": [
    "bsky.app"
  ],
  "maxItems": 100,
  "includeReplies": true,
  "includeReposts": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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": "posts",
    "handles": [
        "bsky.app"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("benthepythondev/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 = {
    "mode": "posts",
    "handles": ["bsky.app"],
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "🦋 Bluesky Scraper - Posts, Profiles & Search",
        "description": "Scrape Bluesky (bsky.app) via the public AT Protocol API — no login needed. Get a user's posts, profile data, followers/follows, or search posts by keyword/hashtag. Clean JSON with engagement counts, links & images.",
        "version": "0.1",
        "x-build-id": "qO3XuqygWKZawBBuG"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/benthepythondev~bluesky-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-benthepythondev-bluesky-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/benthepythondev~bluesky-scraper/runs": {
            "post": {
                "operationId": "runs-sync-benthepythondev-bluesky-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/benthepythondev~bluesky-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-benthepythondev-bluesky-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "mode": {
                        "title": "What to scrape",
                        "enum": [
                            "posts",
                            "search",
                            "profile",
                            "followers",
                            "follows"
                        ],
                        "type": "string",
                        "description": "posts = a user's posts/timeline; search = keyword/hashtag search; profile = account data; followers / follows = a user's network.",
                        "default": "posts"
                    },
                    "handles": {
                        "title": "Bluesky handles or DIDs",
                        "type": "array",
                        "description": "Accounts to scrape (for posts / profile / followers / follows), e.g. 'bsky.app', 'nytimes.com', or a 'did:plc:...'. The leading @ is optional.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "searchTerms": {
                        "title": "Search terms (for search mode)",
                        "type": "array",
                        "description": "Keywords or #hashtags to search posts for, e.g. 'bitcoin', '#immobilien'. Used only when mode = search.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxItems": {
                        "title": "Max items",
                        "minimum": 1,
                        "maximum": 50000,
                        "type": "integer",
                        "description": "Maximum number of records to return (split across the handles/terms).",
                        "default": 100
                    },
                    "includeReplies": {
                        "title": "Include replies",
                        "type": "boolean",
                        "description": "Include the user's replies in posts mode (otherwise only top-level posts).",
                        "default": true
                    },
                    "includeReposts": {
                        "title": "Include reposts",
                        "type": "boolean",
                        "description": "Include reposts (boosts) in the user's feed in posts mode.",
                        "default": true
                    },
                    "identifier": {
                        "title": "Bluesky handle/email (optional)",
                        "type": "string",
                        "description": "Optional: your Bluesky handle or email. Only needed to make keyword search more reliable. Leave empty for posts/profile/followers."
                    },
                    "appPassword": {
                        "title": "Bluesky app password (optional)",
                        "type": "string",
                        "description": "Optional: a Bluesky APP PASSWORD (Settings > App Passwords — NOT your main password). Used only to authenticate keyword search."
                    },
                    "proxyConfiguration": {
                        "title": "Proxy",
                        "type": "object",
                        "description": "Optional. The Bluesky API is public, so a proxy is not required; Apify Proxy (auto) is fine for IP rotation on large runs.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
