# Bluesky Scraper (`lulzasaur/bluesky-scraper`) Actor

Scrape Bluesky social network posts, profiles, followers, and search results. Extract engagement metrics, hashtags, and user data via the open AT Protocol API.

- **URL**: https://apify.com/lulzasaur/bluesky-scraper.md
- **Developed by:** [lulz bot](https://apify.com/lulzasaur) (community)
- **Categories:** Other
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, NaN 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

Scrape Bluesky social network posts, profiles, followers, and search results via the open AT Protocol API. No authentication required — Bluesky's public API is fully open.

### Features

- **Search Posts** — Find posts by keyword with date range filters, language filter, and sort order
- **Search Users** — Find user accounts by keyword
- **User Profile** — Fetch detailed profiles for one or more handles (batched, up to 25 at a time)
- **User Posts** — Get all recent posts from a specific user
- **Post Thread** — Fetch a full post thread including all replies
- **Followers** — Get the followers list for a user
- **Following** — Get the accounts a user follows

### Input Parameters

| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `mode` | select | Scrape mode (see options below) | `searchPosts` |
| `query` | string | Search keyword or phrase | `artificial intelligence` |
| `handles` | string[] | Bluesky handles (e.g. `jay.bsky.team`) | `[]` |
| `postUri` | string | AT Protocol URI for postThread mode | `""` |
| `sort` | select | `latest` or `top` (searchPosts only) | `latest` |
| `since` | string | Start date ISO 8601 (searchPosts only) | `""` |
| `until` | string | End date ISO 8601 (searchPosts only) | `""` |
| `lang` | string | Language code filter, e.g. `en` (searchPosts only) | `""` |
| `limit` | integer | Max results (1–10000) | `100` |
| `proxyConfiguration` | object | Optional proxy (not required) | `{"useApifyProxy": false}` |

#### Available Modes

| Mode | Description | Required Fields |
|------|-------------|-----------------|
| `searchPosts` | Search posts by keyword | `query` |
| `searchUsers` | Search user accounts by keyword | `query` |
| `userProfile` | Get profile details for specific handle(s) | `handles` |
| `userPosts` | Get posts from a specific user | `handles` |
| `postThread` | Get a post and all its replies | `postUri` |
| `followers` | Get followers of a user | `handles` |
| `following` | Get accounts a user follows | `handles` |

### Output

#### Post Object

```json
{
    "type": "post",
    "uri": "at://did:plc:abc123/app.bsky.feed.post/xyz456",
    "cid": "bafyreid...",
    "text": "Excited about the future of AI on Bluesky! #AI #tech",
    "createdAt": "2024-03-15T10:30:00.000Z",
    "author": {
        "did": "did:plc:abc123",
        "handle": "user.bsky.social",
        "displayName": "Jane Doe",
        "avatar": "https://cdn.bsky.app/img/avatar/...",
        "followersCount": 1500
    },
    "handle": "user.bsky.social",
    "displayName": "Jane Doe",
    "avatar": "https://cdn.bsky.app/img/avatar/...",
    "followersCount": 1500,
    "likeCount": 42,
    "replyCount": 7,
    "repostCount": 15,
    "quoteCount": 3,
    "hashtags": ["AI", "tech"],
    "mentions": ["did:plc:xyz789"],
    "links": ["https://example.com/article"],
    "embed": {
        "type": "external",
        "url": "https://example.com/article",
        "title": "Article Title",
        "description": "Article description"
    },
    "labels": [],
    "scrapedAt": "2024-03-15T12:00:00.000Z"
}
````

#### Profile Object

```json
{
    "type": "profile",
    "did": "did:plc:abc123",
    "handle": "jay.bsky.team",
    "displayName": "Jay Graber",
    "description": "CEO of Bluesky. Building the AT Protocol.",
    "avatar": "https://cdn.bsky.app/img/avatar/...",
    "followersCount": 125000,
    "followsCount": 500,
    "postsCount": 3200,
    "createdAt": "2023-04-24T00:00:00.000Z",
    "labels": [],
    "scrapedAt": "2024-03-15T12:00:00.000Z"
}
```

### Usage Examples

#### Search recent AI posts in English

```json
{
    "mode": "searchPosts",
    "query": "artificial intelligence",
    "sort": "latest",
    "lang": "en",
    "limit": 500
}
```

#### Search posts from a specific date range

```json
{
    "mode": "searchPosts",
    "query": "bluesky",
    "since": "2024-01-01T00:00:00Z",
    "until": "2024-03-01T00:00:00Z",
    "sort": "top",
    "limit": 200
}
```

#### Get profiles for multiple users

```json
{
    "mode": "userProfile",
    "handles": ["jay.bsky.team", "atproto.com", "pfrazee.com"]
}
```

#### Get all posts from a user

```json
{
    "mode": "userPosts",
    "handles": ["jay.bsky.team"],
    "limit": 500
}
```

#### Fetch a full thread and all replies

```json
{
    "mode": "postThread",
    "postUri": "at://did:plc:abc123/app.bsky.feed.post/xyz456"
}
```

#### Get followers of a user

```json
{
    "mode": "followers",
    "handles": ["atproto.com"],
    "limit": 1000
}
```

### Technical Notes

- **No authentication required** — Uses Bluesky's fully open public AT Protocol API
- **No anti-bot protection** — Direct HTTP requests via `got-scraping`
- **Rate limits** — 3,000 requests per 5 minutes per IP. The scraper automatically adds 100ms delays between requests and uses exponential backoff on 429 responses
- **Pagination** — Cursor-based pagination is handled automatically up to the specified `limit`
- **Facets** — Hashtags, mentions, and links are parsed from AT Protocol `facets` arrays in post records
- **Base URL** — `https://public.api.bsky.app/xrpc/`
- **Billing** — Pay-per-result (PPE) at $0.005/result

### Data Sources

All data comes directly from the official Bluesky AT Protocol public API:

- `app.bsky.feed.searchPosts` — Post search
- `app.bsky.actor.searchActors` — User search
- `app.bsky.actor.getProfiles` — Batch profile fetch
- `app.bsky.feed.getAuthorFeed` — User's posts
- `app.bsky.feed.getPostThread` — Full thread with replies
- `app.bsky.graph.getFollowers` — Follower list
- `app.bsky.graph.getFollows` — Following list

# Actor input Schema

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

What to scrape: search posts, search users, user profiles, user posts, post threads, followers, or following.

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

Search keyword or phrase. Used for searchPosts and searchUsers modes.

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

One or more Bluesky handles (e.g. 'jay.bsky.team'). Used for userProfile, userPosts, followers, and following modes.

## `postUri` (type: `string`):

AT Protocol URI for a post (e.g. 'at://did:plc:abc123/app.bsky.feed.post/xyz'). Used for postThread mode.

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

Sort order for post search results. 'latest' returns newest posts first, 'top' returns most popular.

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

Filter posts created on or after this date (ISO 8601 format, e.g. '2024-01-01T00:00:00Z'). Only for searchPosts mode.

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

Filter posts created on or before this date (ISO 8601 format, e.g. '2024-12-31T23:59:59Z'). Only for searchPosts mode.

## `lang` (type: `string`):

Filter posts by language code (e.g. 'en' for English, 'es' for Spanish). Leave empty for all languages. Only for searchPosts mode.

## `limit` (type: `integer`):

Maximum number of results to return. Default is 100, maximum is 10000.

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

Optional proxy configuration. Not required — Bluesky's public API has no geo-restrictions.

## Actor input object example

```json
{
  "mode": "searchPosts",
  "query": "artificial intelligence",
  "handles": [],
  "postUri": "",
  "sort": "latest",
  "since": "",
  "until": "",
  "lang": "",
  "limit": 100,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# 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("lulzasaur/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 = {}

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

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Bluesky Scraper",
        "description": "Scrape Bluesky social network posts, profiles, followers, and search results. Extract engagement metrics, hashtags, and user data via the open AT Protocol API.",
        "version": "1.0",
        "x-build-id": "VNvqot56jOKYOyeX0"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/lulzasaur~bluesky-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-lulzasaur-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/lulzasaur~bluesky-scraper/runs": {
            "post": {
                "operationId": "runs-sync-lulzasaur-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/lulzasaur~bluesky-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-lulzasaur-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",
                "required": [
                    "mode"
                ],
                "properties": {
                    "mode": {
                        "title": "Scrape Mode",
                        "enum": [
                            "searchPosts",
                            "searchUsers",
                            "userProfile",
                            "userPosts",
                            "postThread",
                            "followers",
                            "following"
                        ],
                        "type": "string",
                        "description": "What to scrape: search posts, search users, user profiles, user posts, post threads, followers, or following.",
                        "default": "searchPosts"
                    },
                    "query": {
                        "title": "Search Query",
                        "type": "string",
                        "description": "Search keyword or phrase. Used for searchPosts and searchUsers modes.",
                        "default": "artificial intelligence"
                    },
                    "handles": {
                        "title": "Bluesky Handles",
                        "type": "array",
                        "description": "One or more Bluesky handles (e.g. 'jay.bsky.team'). Used for userProfile, userPosts, followers, and following modes.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "postUri": {
                        "title": "Post URI (AT Protocol)",
                        "type": "string",
                        "description": "AT Protocol URI for a post (e.g. 'at://did:plc:abc123/app.bsky.feed.post/xyz'). Used for postThread mode.",
                        "default": ""
                    },
                    "sort": {
                        "title": "Sort Order",
                        "enum": [
                            "latest",
                            "top"
                        ],
                        "type": "string",
                        "description": "Sort order for post search results. 'latest' returns newest posts first, 'top' returns most popular.",
                        "default": "latest"
                    },
                    "since": {
                        "title": "Since Date",
                        "type": "string",
                        "description": "Filter posts created on or after this date (ISO 8601 format, e.g. '2024-01-01T00:00:00Z'). Only for searchPosts mode.",
                        "default": ""
                    },
                    "until": {
                        "title": "Until Date",
                        "type": "string",
                        "description": "Filter posts created on or before this date (ISO 8601 format, e.g. '2024-12-31T23:59:59Z'). Only for searchPosts mode.",
                        "default": ""
                    },
                    "lang": {
                        "title": "Language Filter",
                        "type": "string",
                        "description": "Filter posts by language code (e.g. 'en' for English, 'es' for Spanish). Leave empty for all languages. Only for searchPosts mode.",
                        "default": ""
                    },
                    "limit": {
                        "title": "Max Results",
                        "minimum": 1,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Maximum number of results to return. Default is 100, maximum is 10000.",
                        "default": 100
                    },
                    "proxyConfiguration": {
                        "title": "Proxy Configuration",
                        "type": "object",
                        "description": "Optional proxy configuration. Not required — Bluesky's public API has no geo-restrictions.",
                        "default": {
                            "useApifyProxy": false
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
