# Bluesky Scraper — Posts, Profiles, Threads & Followers (`nomad-agent/bluesky-scraper`) Actor

All-in-one Bluesky extractor on the official AT Protocol public API. Search posts (keyword, hashtag, author, domain, date), pull an account feed, scrape a post's reply thread, read custom feeds, or list profiles and followers. Clean JSON with engagement & media — no login, no proxies.

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

## Pricing

from $2.00 / 1,000 bluesky records

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 Scraper — Posts, Profiles, Threads & Followers

Extract Bluesky data in one Actor: search posts by keyword or hashtag, pull any account's post feed, scrape a post's full reply thread, read a custom/algorithmic feed, fetch profile details, or list followers and following — all through the official AT Protocol public API. No login, no cookies, no proxies.

> **Claude / Codex skill to describe and setup this actor: [SKILL.md](https://github.com/Exdenta/OinkAIJobSearch/blob/main/skill/bluesky-scraper/SKILL.md)**

### What Bluesky data does this scraper extract?

**Post records** (`search`, `authorFeed`, `thread` and `feed` modes) — one flat JSON record per post:

| Field | Meaning |
|---|---|
| `uri` / `cid` | Stable AT Protocol identifiers of the post |
| `url` | Direct bsky.app link to the post |
| `authorHandle` / `authorDid` / `authorDisplayName` | Who posted it |
| `text` | Full post text |
| `createdAt` / `indexedAt` | When it was posted / indexed |
| `likeCount` / `repostCount` / `replyCount` / `quoteCount` / `bookmarkCount` | Engagement counts |
| `langs` | Declared post languages |
| `tags` / `mentions` / `links` | Hashtags, @-mention DIDs and hyperlinks parsed from the post's richtext facets |
| `embedType` / `mediaUrls` / `mediaAlt` / `externalUrl` / `externalTitle` / `quotedUri` | Media & embeds: images/video/gallery URLs and alt text, external link cards, and quoted-post URIs |
| `replyParentUri` / `replyRootUri` | The post this replies to, and the thread root (null if not a reply) |
| `isRepost` / `feedOf` | Repost flag and source handle/feed (`authorFeed`, `feed` modes) |
| `depth` / `parentUri` / `rootUri` / `isRoot` / `threadUri` | Thread structure (`thread` mode) |
| `aiSentiment` / `aiTopics` / `aiSummary` | Optional LLM analysis (only when the `aiAnalysis` add-on is on) |
| `mode` | Which mode produced the record |

**Profile records** (`profile`, `followers`, `following` modes): `did`, `handle`, `url`, `displayName`, `description`, `avatar`, `createdAt`, plus `followersCount` / `followsCount` / `postsCount` in `profile` mode and `subjectHandle` in follower/following modes.

### Modes

| Mode | What it returns | Key inputs |
|---|---|---|
| `search` | Posts matching a keyword/hashtag, with date, author, mention, language, domain/url/tag and engagement filters | `query`, `since`, `until`, `fromAuthor`, `mentionsAuthor`, `language`, `domain`, `url`, `tag`, `sort`, `minLikes`, `minReposts` |
| `authorFeed` | Posts by one or more accounts | `handles`, `includeReplies`, `minLikes`, `minReposts` |
| `thread` | A post plus its full reply thread (and optional ancestors) | `threadUris`, `threadDepth`, `parentHeight` |
| `feed` | Posts from a custom/algorithmic feed generator | `feedUris` |
| `profile` | Profile details (bio, counts) per account | `handles` |
| `followers` | Accounts following the given handles | `handles` |
| `following` | Accounts the given handles follow | `handles` |

Add **`onlyNewSinceLastRun: true`** to any streaming mode (`search`, `authorFeed`, `feed`) to skip records already seen in the Actor's previous run — handy for scheduled/incremental scraping. The first run returns everything.

Search supports Bluesky query operators typed straight into `query` — `#hashtag`, `"exact phrase"`, `from:user.bsky.social`, `mentions:user.bsky.social`, `lang:en`, and more. The most common ones also have dedicated inputs so you don't have to remember the operator syntax:

- **`fromAuthor`** — only posts written by this handle (same as `from:`). Uses `searchPosts`' own `author` filter param, not just a query-string trick.
- **`mentionsAuthor`** — only posts that mention this handle (same as `mentions:`). Uses the `mentions` filter param.
- **`language`** — only posts declared in this ISO 639-1 language code (same as `lang:`). Uses the `lang` filter param.

These compose safely with `query`, `since`, `until` and `sort` in the same request. The `searchPosts` endpoint's dedicated `domain`/`url`/`tag` filters are also wired up as first-class inputs:

- **`domain`** — only posts linking to this domain (e.g. `nytimes.com`).
- **`url`** — only posts linking to this exact URL.
- **`tag`** — only posts carrying these hashtags (enter each without the leading `#`).

Bluesky's unauthenticated search API does not allow cursor paging, so the Actor transparently paginates `latest` searches by walking the time window backwards — you still just set `maxItems`. `top` sort is not time-ordered and returns up to 100 posts per run.

`minLikes` / `minReposts` filter posts client-side, after they're fetched from the API — set either to skip low-engagement noise in the `search`, `authorFeed`, `thread` and `feed` post modes. Filtered-out posts are never pushed to the dataset, so you aren't billed for them.

### Thread & custom-feed modes

**`thread`** mode returns a post and its whole reply tree via the AT Protocol `getPostThread` endpoint. Put post links or `at://` URIs in `threadUris`, set `threadDepth` for how many reply levels to fetch, and `parentHeight` to also pull ancestor posts above the requested one. Every record carries `depth` (0 = the requested post, 1+ = replies, negative = ancestors), `parentUri`, `rootUri` and `isRoot`, so you can rebuild the conversation tree.

**`feed`** mode reads a custom/algorithmic feed generator via `getFeed`. Put feed links (`https://bsky.app/profile/<handle>/feed/<rkey>`) or `at://.../app.bsky.feed.generator/...` URIs in `feedUris`; handles are resolved to DIDs automatically. Records include `feedOf` (the feed) and `isRepost`.

### Optional AI analysis (bring your own key)

Turn on `aiAnalysis` to add `aiSentiment` (positive / negative / neutral / mixed), `aiTopics` (grounded topic tags) and `aiSummary` (one-sentence summary) to each post in the post modes. Supply your own **`anthropicApiKey`** or **`mistralApiKey`** (pick with `aiProvider`, override the model with `aiModel`) — that provider bills you directly, and this Actor's per-record price is unchanged. When off, the three fields are simply absent. If a post can't be analyzed, its AI fields are set to `null` rather than guessed.

### How to scrape Bluesky with this Actor

1. Click **Try for free** / **Run** — no Bluesky account needed, only public data is read.
2. Pick a `mode`, set a `query` or `handles`, adjust `maxItems` or keep the defaults.
3. Run it and export the dataset as JSON, CSV or Excel, or read it over the [API](https://docs.apify.com/api/v2).

Run it from your own code:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("nomad-agent/bluesky-scraper").call(run_input={
    "mode": "search",
    "query": "#ai",
    "since": "2026-06-01T00:00:00Z",
    "maxItems": 200,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["authorHandle"], "—", item["text"][:80], item["url"])
```

Or a single HTTP call that runs the Actor and returns items in one response:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/nomad-agent~bluesky-scraper/run-sync-get-dataset-items?token=<YOUR_APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"mode": "authorFeed", "handles": ["bsky.app"], "maxItems": 50}'
```

### Input

General fields (apply across modes):

| Field | Type | Default | Notes |
|---|---|---|---|
| `mode` | string | `search` | One of `search`, `authorFeed`, `thread`, `feed`, `profile`, `followers`, `following`. |
| `handles` | array | — | Handles or DIDs for `authorFeed`/`profile`/`followers`/`following`. Leading `@` optional. |
| `includeReplies` | boolean | `false` | Include the author's replies in `authorFeed` mode. |
| `maxItems` | integer | `100` | Maximum records for the whole run. Set 0 for no limit. |
| `onlyNewSinceLastRun` | boolean | `false` | Delta mode: skip records seen in the previous run (`search`/`authorFeed`/`feed`). |

Thread & feed fields:

| Field | Type | Default | Notes |
|---|---|---|---|
| `threadUris` | array | — | Post URLs / `at://` URIs whose reply thread to scrape (`thread` mode). |
| `threadDepth` | integer | `6` | Levels of replies to fetch below the post (`thread` mode). |
| `parentHeight` | integer | `0` | Ancestor posts above the requested one to include (`thread` mode). |
| `feedUris` | array | — | Feed URLs / `at://` generator URIs to read (`feed` mode). |

Search fields (`search` mode; `minLikes`/`minReposts` also apply to `authorFeed`/`thread`/`feed`):

| Field | Type | Default | Notes |
|---|---|---|---|
| `query` | string | — | Keyword/hashtag for `search` mode. Supports Bluesky search operators. |
| `since` | string | — | Only posts created at or after this date/time. Datepicker (`YYYY-MM-DD`) or a precise ISO 8601 timestamp. |
| `until` | string | — | Only posts created before this date/time. Datepicker (`YYYY-MM-DD`) or a precise ISO 8601 timestamp. |
| `fromAuthor` | string | — | Only posts written by this handle (`from:` operator / `author` param). |
| `mentionsAuthor` | string | — | Only posts that mention this handle (`mentions:` operator / `mentions` param). |
| `language` | string | — | Only posts in this ISO 639-1 language code (`lang:` operator / `lang` param). |
| `domain` | string | — | Only posts linking to this domain (`domain` param). |
| `url` | string | — | Only posts linking to this exact URL (`url` param). |
| `tag` | array | — | Only posts carrying these hashtags, entered without `#` (`tag` param). |
| `sort` | string | `latest` | `latest` (newest first) or `top` (by relevance) for `search` mode. |
| `minLikes` | integer | `0` | Drop posts with fewer likes than this (compares `likeCount`). 0 = no filter. |
| `minReposts` | integer | `0` | Drop posts with fewer reposts than this (compares `repostCount`). 0 = no filter. |

AI analysis fields (optional, bring your own key):

| Field | Type | Default | Notes |
|---|---|---|---|
| `aiAnalysis` | boolean | `false` | Add `aiSentiment`/`aiTopics`/`aiSummary` to posts (post modes only). |
| `aiProvider` | string | auto | Auto-detected from whichever key you supply; set `anthropic` or `mistral` only to override. |
| `aiModel` | string | — | Override the model (default: `claude-haiku-4-5` / `mistral-small-latest`). |
| `anthropicApiKey` | string (secret) | — | Your Anthropic key; billed by Anthropic. Not required. |
| `mistralApiKey` | string (secret) | — | Your Mistral key; billed by Mistral. Not required. |

### Output example

```json
{
  "mode": "search",
  "uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3lb2abcxyz",
  "cid": "bafyreib2rxk3rw6...",
  "url": "https://bsky.app/profile/bsky.app/post/3lb2abcxyz",
  "authorHandle": "bsky.app",
  "authorDid": "did:plc:z72i7hdynmk6r22z27h6tvur",
  "authorDisplayName": "Bluesky",
  "text": "Introducing new moderation tools...",
  "createdAt": "2026-06-15T18:02:11.000Z",
  "indexedAt": "2026-06-15T18:02:12.345Z",
  "langs": ["en"],
  "replyCount": 412,
  "repostCount": 1287,
  "likeCount": 9034,
  "quoteCount": 187,
  "bookmarkCount": 54,
  "replyParentUri": null,
  "replyRootUri": null,
  "tags": ["moderation"],
  "mentions": [],
  "links": ["https://bsky.social/about/blog"],
  "embedType": "external",
  "mediaUrls": [],
  "mediaAlt": [],
  "externalUrl": "https://bsky.social/about/blog",
  "externalTitle": "Bluesky Blog",
  "quotedUri": null
}
```

### Pricing

Pay per event: **$0.05 per Actor start** and **$0.004 per record returned**.
100 records ≈ $0.45. No subscription, no rental — you pay only for what you fetch.
`minLikes`/`minReposts` and `onlyNewSinceLastRun` are applied before records are pushed, so filtered-out and already-seen posts are never billed. The optional `aiAnalysis` add-on uses **your own** Anthropic/Mistral key and is billed by that provider — it does not change this Actor's per-record price.

### Integrations

Export the dataset as JSON, CSV, Excel or HTML, pull it over the [Apify API](https://docs.apify.com/api/v2) (including `run-sync-get-dataset-items` for a single blocking call), wire it into Make, Zapier or n8n, or call it as a tool from an AI agent via the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp).

### Use cases

- Brand, keyword and hashtag monitoring on Bluesky
- Social listening and sentiment datasets for AI/LLM pipelines
- Influencer discovery via follower/following graphs and engagement counts
- Archiving an account's full posting history
- Trend and virality analysis with like/repost/reply counts

### FAQ

**Is it legal to scrape Bluesky?**
This Actor reads only publicly available data through Bluesky's own public AT Protocol API (`public.api.bsky.app`) — the same data any logged-out visitor can see. No authentication is used and no private data is touched. Review Bluesky's terms and your local regulations for your specific use case.

**Do I need a Bluesky account?**
No. All seven modes use unauthenticated public endpoints.

**How fresh is the data?**
Every run hits the live API. `search` with `sort: latest` returns posts within seconds of being indexed.

**How many records can I get?**
`maxItems` caps the run; set 0 to paginate until the source is exhausted (full author feeds and follower lists). The Actor follows API cursors and respects Bluesky's rate limits automatically.

**What about deleted or blocked accounts?**
Handles that cannot be resolved (typos, deactivated accounts) are logged and skipped — one bad handle never fails the whole run.

**Which search operators are supported as dedicated inputs?**
`fromAuthor`, `mentionsAuthor`, `language`, `domain`, `url` and `tag` map to `searchPosts`' own `author`, `mentions`, `lang`, `domain`, `url` and `tag` filter params (verified against the live API) — equivalent to `from:`, `mentions:`, `lang:`, `domain:` and `#tag` in `query`, but composable with it via proper params instead of string-building.

**Something broken or missing?**
Open an issue on the Actor's **Issues** tab — it is monitored and reliability fixes ship fast.

### Related Actors

- [Hacker News Who Is Hiring Scraper — HN Jobs](https://apify.com/nomad-agent/hackernews-scraper)
- [Web Search Scraper](https://apify.com/nomad-agent/web-search-scraper)
- [AI & ML Engineer Jobs Scraper — 8 Boards in One](https://apify.com/nomad-agent/ml-ai-dev-bundle)

### Credits

Independent implementation on the official AT Protocol public API. Design informed by the MIT-licensed [deepfates/bsky-scraper](https://github.com/deepfates/bsky-scraper) firehose archiver — see `LICENSE` for the attribution note.

# Actor input Schema

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

What to scrape: <b>search</b> — posts matching a keyword/hashtag query; <b>authorFeed</b> — posts from specific accounts; <b>thread</b> — a post plus its full reply thread; <b>feed</b> — posts from a custom/algorithmic feed; <b>profile</b> — profile details for specific accounts; <b>followers</b> — accounts following the given handles; <b>following</b> — accounts the given handles follow.

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

Bluesky handles or DIDs to scrape (used in <b>authorFeed</b>, <b>profile</b>, <b>followers</b> and <b>following</b> modes), e.g. <code>bsky.app</code> or <code>jay.bsky.team</code>. The leading <code>@</code> is optional.

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

In <b>authorFeed</b> mode, also include the author's replies (default: original posts, quotes and reposts only).

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

Maximum number of records to return across the whole run. Set 0 for no limit (paginate until the source is exhausted). Each record returned is billed — see Pricing in the README.

## `onlyNewSinceLastRun` (type: `boolean`):

Delta mode: skip records already seen in this Actor's previous run (per search / handle / feed). Uses the newest <code>indexedAt</code> seen last time as a high-water mark. Applies to <b>search</b>, <b>authorFeed</b> and <b>feed</b> modes. First run returns everything.

## `threadUris` (type: `array`):

Posts whose reply thread to scrape (used in <b>thread</b> mode). Paste bsky.app post links (e.g. <code>https://bsky.app/profile/bsky.app/post/3l...</code>) or raw <code>at://</code> post URIs.

## `threadDepth` (type: `integer`):

In <b>thread</b> mode, how many levels of replies below the post to fetch (0 = just the post itself).

## `parentHeight` (type: `integer`):

In <b>thread</b> mode, how many ancestor posts above the requested post to include (0 = none). Ancestors are returned with a negative <code>depth</code>.

## `feedUris` (type: `array`):

Custom/algorithmic feeds to read (used in <b>feed</b> mode). Paste bsky.app feed links (e.g. <code>https://bsky.app/profile/\<handle>/feed/\<rkey></code>) or raw <code>at://.../app.bsky.feed.generator/...</code> URIs.

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

Keyword or hashtag to search posts for (used in <b>search</b> mode). Supports Bluesky search operators typed directly into the query, e.g. <code>#ai</code>, <code>"exact phrase"</code> — or use the dedicated <b>From author</b>, <b>Mentions author</b>, <b>Language</b>, <b>Domain</b>, <b>URL</b> and <b>Tag</b> fields below instead of typing <code>from:</code>/<code>mentions:</code>/<code>lang:</code>/<code>domain:</code>/<code>#tag</code>.

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

Only return posts created at or after this date (used in <b>search</b> mode). Pick a date, or type a precise ISO 8601 timestamp such as <code>2026-06-01T00:00:00Z</code> for finer control.

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

Only return posts created before this date (used in <b>search</b> mode). Pick a date, or type a precise ISO 8601 timestamp such as <code>2026-07-01T00:00:00Z</code> for finer control.

## `fromAuthor` (type: `string`):

Only return posts written by this account (used in <b>search</b> mode). Enter a handle, e.g. <code>bsky.app</code> — same as typing <code>from:</code> into a Bluesky search. The leading <code>@</code> is optional.

## `mentionsAuthor` (type: `string`):

Only return posts that mention this account (used in <b>search</b> mode). Enter a handle, e.g. <code>bsky.app</code> — same as typing <code>mentions:</code> into a Bluesky search. The leading <code>@</code> is optional.

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

Only return posts declared in this language (used in <b>search</b> mode). Two-letter ISO 639-1 code, e.g. <code>en</code>, <code>fr</code>, <code>ja</code>.

## `domain` (type: `string`):

Only return posts that link to this domain (used in <b>search</b> mode), e.g. <code>nytimes.com</code>. Uses searchPosts' own <code>domain</code> filter param.

## `url` (type: `string`):

Only return posts that link to this exact URL (used in <b>search</b> mode). Uses searchPosts' own <code>url</code> filter param.

## `tag` (type: `array`):

Only return posts carrying these hashtags (used in <b>search</b> mode). Enter tags without the leading <code>#</code>, e.g. <code>art</code>. Uses searchPosts' own repeatable <code>tag</code> filter param.

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

Ranking for <b>search</b> mode: newest first or by relevance/engagement.

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

Drop posts with fewer likes than this before they are returned (applies to <b>search</b>, <b>authorFeed</b>, <b>thread</b> and <b>feed</b> modes; compares against each post's <code>likeCount</code>). 0 = no filter.

## `minReposts` (type: `integer`):

Drop posts with fewer reposts than this before they are returned (applies to <b>search</b>, <b>authorFeed</b>, <b>thread</b> and <b>feed</b> modes; compares against each post's <code>repostCount</code>). 0 = no filter.

## `aiAnalysis` (type: `boolean`):

Add LLM-derived <code>aiSentiment</code>, <code>aiTopics</code> and <code>aiSummary</code> fields to each post (post modes only). Requires your own Anthropic, Mistral or OpenAI API key below — that provider bills you directly; this Actor's per-record price is unchanged. Left null when off.

## `aiProvider` (type: `string`):

Which LLM provider to use when <b>AI analysis</b> is on. Leave unset to auto-detect from whichever key you supply (Anthropic, Mistral or OpenAI); set it explicitly only to override.

## `aiModel` (type: `string`):

Override the model used for AI analysis. Defaults to a cheap model per provider (<code>claude-haiku-4-5</code> for Anthropic, <code>mistral-small-latest</code> for Mistral, <code>gpt-4.1-mini</code> for OpenAI — any chat-completions GPT model works, including the gpt-5 family).

## `anthropicApiKey` (type: `string`):

Your Anthropic API key (<code>sk-ant-…</code>). Only used when <b>AI analysis</b> is on and the provider is Anthropic; billed by Anthropic, not by this Actor. Not required.

## `mistralApiKey` (type: `string`):

Your Mistral API key. Only used when <b>AI analysis</b> is on and the provider is Mistral; billed by Mistral, not by this Actor. Not required.

## `openaiApiKey` (type: `string`):

Your OpenAI API key (<code>sk-…</code>). Only used when <b>AI analysis</b> is on and the provider is OpenAI; billed by OpenAI, not by this Actor. Not required.

## Actor input object example

```json
{
  "mode": "search",
  "handles": [
    "bsky.app"
  ],
  "includeReplies": false,
  "maxItems": 100,
  "onlyNewSinceLastRun": false,
  "threadDepth": 6,
  "parentHeight": 0,
  "query": "#ai",
  "sort": "latest",
  "minLikes": 0,
  "minReposts": 0,
  "aiAnalysis": 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 = {
    "handles": [
        "bsky.app"
    ],
    "query": "#ai"
};

// Run the Actor and wait for it to finish
const run = await client.actor("nomad-agent/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 = {
    "handles": ["bsky.app"],
    "query": "#ai",
}

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

```

## MCP server setup

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

```

## OpenAPI specification

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