# Bluesky Posts Scraper (`parsebird/bluesky-posts-scraper`) Actor

Search Bluesky for posts by keyword. Filter by sort order, date range, and language. Get post text, author, images, links, and engagement counts. Export JSON, CSV, Excel.

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

## Pricing

from $2.29 / 1,000 post scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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 Posts Scraper

The Bluesky Posts Scraper searches Bluesky for posts matching one or more keywords and returns post text, author details, images, external links, and engagement counts — no login or API key required.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Search any keyword, sort by latest or top engagement, filter by date range and language, and get clean, structured post data ready for social listening, trend tracking, or research.
</td>
</tr></table>

##### Copy to your AI assistant

```
Use the Apify Actor "parsebird/bluesky-posts-scraper" (Bluesky Posts Scraper) via the ApifyClient: client.actor("parsebird/bluesky-posts-scraper").call(run_input={"queries": ["bluesky", "decentralized social media"], "limit": 100, "sort": "latest", "lang": "en"}) — inputs are queries (array of keywords — required), limit (integer, max posts per query, default 5), sort ("latest" or "top", default "latest"), since / until (date or ISO 8601 timestamp), lang (language code, e.g. en, de), and proxyConfiguration (optional — Bluesky's public API has no bot protection); output items contain id, authorId, authorName, authorUsername, authorAvatar, text, images, link, primaryImage, createdAt, langs, replyCount, repostCount, likeCount, url, and searchTerm; full API spec at https://apify.com/parsebird/bluesky-posts-scraper/api and get an API token at https://console.apify.com/account/integrations.
```

#### What does the Bluesky Posts Scraper do?

[Bluesky](https://bsky.app/) is the fastest-growing decentralized alternative to X/Twitter, built on the AT Protocol. The Bluesky Posts Scraper searches Bluesky's public post index the same way the in-app search does, and returns the results as structured data:

- 🔍 Search by keyword or phrase — run multiple queries in a single job
- 📊 Sort by **latest** (newest first) or **top** (most engagement)
- 📅 Filter by date range with `since` and `until`
- 🌐 Filter by post language (e.g. `en`, `de`, `ja`)
- 🖼️ Extracts images, external link cards, and a convenience `primaryImage` for the post's lead visual
- 💬 Returns like, repost, and reply counts alongside full author details (name, handle, DID, avatar)
- ⚡ No login, API key, or proxy required — Bluesky's public search API is open

#### Input parameters

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `queries` | array | **Yes** | — | Keywords or phrases to search for. |
| `limit` | integer | No | `5` | Maximum number of posts to scrape per query. |
| `sort` | string | No | `latest` | Sorting order: `latest` or `top`. |
| `since` | string | No | — | Only return posts created on or after this date. |
| `until` | string | No | — | Only return posts created on or before this date. |
| `lang` | string | No | — | Filter posts by language code, e.g. `en`, `de`. |
| `proxyConfiguration` | object | No | off | Apify Proxy settings — optional, only useful under heavy rate limiting. |

```json
{
  "queries": ["bluesky", "decentralized social media"],
  "limit": 100,
  "sort": "latest",
  "lang": "en"
}
```

#### Output example

```json
{
  "id": "bafyreibqjfx2ejvxkd3okjtodoyqvoyk7wuberwonsakdjv4yahp2lrn4a",
  "authorId": "did:plc:pc2aiklrpzwgsiq3fuohbui4",
  "authorName": "Keri Warbis",
  "authorUsername": "keriwarbis.bsky.social",
  "authorAvatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:pc2aiklrpzwgsiq3fuohbui4/bafkreihgejbtckxrsgrba7ckx6mlsofe6nzvs4t2m54y2in6edcp65tlne@jpeg",
  "text": "Bit sunburnt from yesterday's stint in the garden.\n\nBit hungover from Eurovision.\n\nAnother day of sun and entertaining ahead.\n\nSunday roast at The Grand will be happening to round of the day.",
  "images": [
    {
      "thumb": "https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:pc2aiklrpzwgsiq3fuohbui4/bafkreiejc6jc4z47urksbwn7owoyyi4o46ufi362e52bscl4bsjrj4izyq@jpeg",
      "fullsize": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:pc2aiklrpzwgsiq3fuohbui4/bafkreiejc6jc4z47urksbwn7owoyyi4o46ufi362e52bscl4bsjrj4izyq@jpeg",
      "alt": "",
      "aspectRatio": { "height": 820, "width": 828 }
    }
  ],
  "link": null,
  "primaryImage": "https://cdn.bsky.app/img/feed_fullsize/plain/did:plc:pc2aiklrpzwgsiq3fuohbui4/bafkreiejc6jc4z47urksbwn7owoyyi4o46ufi362e52bscl4bsjrj4izyq@jpeg",
  "createdAt": "2024-05-12T08:36:29.345Z",
  "langs": ["en"],
  "replyCount": 0,
  "repostCount": 0,
  "likeCount": 0,
  "url": "https://bsky.app/profile/keriwarbis.bsky.social/post/3kxkwdhu77o23",
  "searchTerm": "bluesky"
}
```

| Field | Description |
|---|---|
| `id` | The post's record key (its unique ID within the author's repo) |
| `authorId` | The author's DID (decentralized identifier) |
| `authorName` / `authorUsername` | The author's display name and `@handle` |
| `authorAvatar` | URL of the author's avatar image |
| `text` | The post's text content |
| `images` | Array of attached images (`thumb`, `fullsize`, `alt`, `aspectRatio`) |
| `link` | URL of an attached external link card, if any |
| `primaryImage` | A single representative image URL for the post (first image, or a link/video thumbnail) |
| `createdAt` | When the post was created |
| `langs` | Language codes the author tagged the post with |
| `replyCount` / `repostCount` / `likeCount` | Engagement counts at scrape time |
| `url` | The post's `bsky.app` URL |
| `searchTerm` | Which of your input queries returned this post |

Download results in **JSON, CSV, Excel, HTML, or XML** directly from the Apify Console, or pull them via the [Dataset API](https://docs.apify.com/api/v2) / [Apify SDK](https://docs.apify.com/sdk).

#### How to use the Bluesky Posts Scraper

1. Open the Bluesky Posts Scraper on the Apify Store, or call it via the API below.
2. Enter one or more search keywords, and optionally set a limit, sort order, date range, or language filter.
3. Run the Actor and download the dataset as JSON, CSV, or Excel — or read it straight from your own code.

**Python:**

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run = client.actor("parsebird/bluesky-posts-scraper").call(run_input={
    "queries": ["bluesky", "decentralized social media"],
    "limit": 100,
    "sort": "latest",
    "lang": "en",
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["authorUsername"], item["text"][:80])
```

**JavaScript (Node.js):**

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });

const run = await client.actor('parsebird/bluesky-posts-scraper').call({
    queries: ['bluesky', 'decentralized social media'],
    limit: 100,
    sort: 'latest',
    lang: 'en',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

#### Use cases

- **Social listening** — track what people are saying about a brand, product, or topic on Bluesky
- **Trend research** — pull the top-engagement posts for a keyword over a date range
- **Academic and market research** — build datasets of public discourse on a subject
- **Content curation** — surface the best recent posts on a topic for a newsletter or feed
- **Competitive monitoring** — watch how a keyword or hashtag is trending relative to competitors

#### How it works

1. Sends each query to Bluesky's public `app.bsky.feed.searchPosts` endpoint, with your `sort`, `since`, `until`, and `lang` filters applied server-side.
2. Paginates automatically (100 posts per page) until your requested `limit` is reached or Bluesky has no more matches.
3. Flattens each post into a clean record: author details, text, images, external link, and engagement counts.
4. Pushes one row per post to the dataset.

#### How much does it cost to scrape Bluesky posts?

This Actor uses [Pay-Per-Event pricing](https://docs.apify.com/platform/actors/publishing/monetize#pay-per-event-pricing-model) — you pay per post returned.

| Event | Price per event | Price per 1,000 posts |
|---|---|---|
| `post-scraped` | $0.00299 | **$2.99** |

A `post-scraped` event fires once for every post pushed to the dataset. Scraping 1,000 posts across any number of queries costs about $2.99. Apify's free monthly platform usage credits apply to this Actor like any other.

#### FAQ

**Do I need a Bluesky account or API key?**
No. This Actor uses Bluesky's public, unauthenticated AppView API — the same data anyone can see by searching on bsky.app.

**Why did my run return fewer posts than my `limit`?**
Bluesky applies bursty rate limiting to its search endpoint, especially on deep pagination. This Actor retries automatically with backoff, but a very large `limit` on a single query may still return fewer posts than requested if Bluesky throttles the run. Splitting a very large request across a scheduled run, or spacing out queries, usually helps.

**What format should `since` and `until` be in?**
Either a plain date (`2026-01-01`) or a full ISO 8601 timestamp (`2026-01-01T00:00:00Z`). Plain dates are treated as the start/end of that day.

**Does this include replies and reposts that match my keyword?**
It returns whatever Bluesky's search index returns for your query — this is typically top-level posts and replies whose text matches, not reposts (which have no text of their own).

**Can I schedule this to run automatically?**
Yes — use [Apify Schedules](https://docs.apify.com/platform/schedules) to re-run your queries daily, weekly, or on any interval, and pair it with [webhooks](https://docs.apify.com/platform/integrations/webhooks) or the [Google Sheets](https://docs.apify.com/platform/integrations/google-sheets), [Slack](https://docs.apify.com/platform/integrations/slack), [Zapier](https://docs.apify.com/platform/integrations/zapier), or [Make](https://docs.apify.com/platform/integrations/make) integrations to route the results.

**Can I access this via API?**
Yes — every Actor on Apify has a full [REST API](https://docs.apify.com/api/v2), plus native clients for [Python](https://docs.apify.com/api/client/python) and [JavaScript](https://docs.apify.com/api/client/js). See the code samples above.

**Need profiles, follower lists, or comment threads instead of just search?**
See the [Bluesky Scraper](https://apify.com/parsebird/bluesky-scraper) below — it covers author feeds, profiles, followers/follows, and comment threads in addition to search.

#### Is it legal to scrape Bluesky?

Yes. This Actor only reads posts that are already public on Bluesky's own search index — the same data any visitor can see without logging in. That said, always respect Bluesky's terms of service and applicable data-protection law for how you subsequently use any personal data in the results. See Apify's [blog post on the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) for a broader overview.

#### Related Actors

- [Bluesky Scraper - Search, Profiles & Posts](https://apify.com/parsebird/bluesky-scraper) — the full toolkit: author feeds, profiles, followers/follows, comment threads, and sentiment analysis

# Actor input Schema

## `queries` (type: `array`):

Keywords or phrases to search for, e.g. "bluesky" or "decentralized social media".

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

The maximum number of posts to scrape per query.

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

The sorting order for the posts.

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

Only return posts created on or after this date (e.g. 2026-01-01, or a full ISO 8601 timestamp).

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

Only return posts created on or before this date (e.g. 2026-01-31, or a full ISO 8601 timestamp).

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

Filter posts by language code, e.g. en, de, ja.

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

Bluesky's public API has no bot protection and works fine without a proxy. Enable Apify Proxy only if you hit rate limits on a very large run.

## Actor input object example

```json
{
  "queries": [
    "bluesky"
  ],
  "limit": 20,
  "sort": "latest",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `dataset` (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 = {
    "queries": [
        "bluesky"
    ],
    "limit": 20,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/bluesky-posts-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 = {
    "queries": ["bluesky"],
    "limit": 20,
    "proxyConfiguration": { "useApifyProxy": False },
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parsebird/bluesky-posts-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/WaozXfbt1GWXOdQjq/builds/Zxy7cQadB54mlyVV9/openapi.json
