# Bluesky Feed Posts Scraper (`devilscrapes/bluesky-feed-posts`) Actor

Export posts from any public Bluesky custom or algorithm feed. No login needed. Feed metadata and engagement counts via the unauthenticated AT Protocol public API.

- **URL**: https://apify.com/devilscrapes/bluesky-feed-posts.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 0 monthly users, 50.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 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

<img src=".actor/icon.svg" width="160" alt="Bluesky Feed Posts Scraper" />

## Bluesky Feed Posts Scraper

_We do the dirty work so your dataset stays clean._ 😈

**$2.05 / 1,000 posts** — Export posts from any public Bluesky custom feed or algorithm feed, including curated feeds like "Discover" and "What's Hot" and community-built feed generators, via the unauthenticated AT Protocol public AppView API. No Bluesky account. No API key. No browser automation.

This Actor calls Bluesky's public `app.bsky.feed.getFeed` endpoint, denormalises feed metadata into every row, and emits a flat dataset ready for direct analysis in spreadsheets, BI tools, or SQL — no joins required.

### 🎯 What this scrapes
Two operating modes, controlled by which input field you set:

1. **Single-feed mode** — provide a feed URI (AT URI or `bsky.app/profile/.../feed/...` web URL) and the Actor exports every post in that feed up to the per-feed cap.
2. **Creator-discovery mode** — provide a creator's Bluesky handle (e.g. `bsky.app`) and the Actor calls `app.bsky.feed.getActorFeeds` to enumerate every feed that creator publishes, then scrapes each one in turn.

For each post you receive the post body, engagement counts (likes, reposts, replies, quotes), author handle and DID, post CID, and indexing timestamp — plus the parent feed's display name, creator handle, and description denormalised onto the row so a CSV export is entirely self-contained.

| Field | Type | Description |
|---|---|---|
| `feed_uri` | string | AT URI of the feed generator |
| `feed_display_name` | string | Human-readable feed name (e.g. `Discover`) |
| `feed_creator_handle` | string | Bluesky handle of the feed creator |
| `feed_description` | string \| null | Feed description text set by the creator |
| `post_uri` | string | AT URI of the post |
| `post_cid` | string | Content identifier (CID) of the post record |
| `post_indexed_at` | string | ISO 8601 datetime the post was indexed by the AppView |
| `post_text` | string | Body text of the post |
| `post_lang` | string \| null | Primary language code (e.g. `en`), if present |
| `post_reply_count` | integer | Number of replies |
| `post_repost_count` | integer | Number of reposts |
| `post_like_count` | integer | Number of likes |
| `post_quote_count` | integer | Number of quote posts |
| `author_did` | string | Decentralized identifier of the post author |
| `author_handle` | string | Bluesky handle of the post author |
| `author_display_name` | string \| null | Display name of the post author |
| `scraped_at` | string | ISO 8601 UTC datetime this row was written |

### 🔥 Features
- No Bluesky account required — uses the public unauthenticated AppView API at `public.api.bsky.app`.
- Two operating modes: single feed URI or discover-all-feeds-by-creator via `getActorFeeds`.
- Accepts either AT URIs (`at://did:plc:.../app.bsky.feed.generator/whats-hot`) or `bsky.app` web URLs — the Actor rewrites web URLs to AT URI form automatically.
- Denormalised output — feed metadata (name, description, creator handle) on every post row, no joins needed for downstream analytics or CSV exports.
- Cursor-based pagination with a client-side per-feed cap so you only pay for what you need.
- Exponential backoff with `Retry-After` honoured for `408 / 429 / 503` responses; max 5 attempts.
- Pure HTTP client (`curl-cffi` with browser fingerprint impersonation) — no browser automation, low compute footprint.
- Pydantic v2 input validation with XOR guard: exactly one of `feedUri` or `creatorHandle` must be set.
- Pairs with the companion `bluesky-starter-pack` Actor as the Bluesky Intel Suite.

### 💡 Use cases
- **Algorithm research** — sample what posts the "Discover" / "What's Hot" algorithmic feeds actually surface across days or weeks; analyse topic drift and amplification patterns.
- **Newsroom monitoring** — subscribe to curated topic feeds for breaking-news posts on specific beats, then pipe to Slack or a Google Sheet via Apify integrations.
- **Marketing intelligence** — see which posts are amplified by community feeds in your niche; measure which content formats dominate each feed's engagement distribution.
- **Creator analytics** — pull every post a niche feed generator surfaces and rank by like / repost / quote ratios to benchmark your own posts against feed peers.
- **Dataset bootstrap** — collect labelled training data from topic-curated feeds for downstream NLP or sentiment models without manual tagging of raw timelines.
- **Competitive monitoring** — track community-curated feeds that aggregate competitor announcements, support complaints, or product mentions.
- **Academic social-media research** — Bluesky's public AT Protocol data is significantly more accessible than Twitter/X's API; this Actor is a low-cost entry point for longitudinal feed studies.

### ⚙️ How to use it
1. Open the Actor input form.
2. **Either** paste a feed AT URI or `bsky.app` web URL into **Feed URI or URL** (single-feed mode) **or** type a Bluesky handle into **Creator handle** (discovery mode). Setting both is an error; setting neither is also an error — the Actor fails fast before making any network call.
3. Adjust **Max posts per feed** (default 100, maximum 5000).
4. In discovery mode, adjust **Max feeds** to cap how many of the creator's feeds are scraped (default 5, maximum 50).
5. Leave **Use Apify Proxy** off unless you are behind a restrictive ISP — the AT Protocol public API does not block datacenter IPs, so direct routing is faster and free.
6. Click **Start** and watch the run log. Results stream into the default dataset in real time and can be downloaded as JSON, CSV, Excel, or XML via the **Export** button.

#### Finding a feed URI

Every Bluesky feed has a `bsky.app` URL in the form `https://bsky.app/profile/<creator>/feed/<rkey>`. Examples:

- `https://bsky.app/profile/bsky.app/feed/whats-hot` — Bluesky's "Discover" feed
- `https://bsky.app/profile/bsky.app/feed/with-friends` — "With Friends"

Paste the full URL into the **Feed URI or URL** field and this Actor converts it to AT URI form internally. You can also paste the raw AT URI directly if you have it.

### 📥 Input
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| `feedUri` | string | one-of | — | AT URI or `bsky.app/profile/<handle>/feed/<rkey>` URL of one feed |
| `creatorHandle` | string | one-of | — | Bluesky handle or DID; drives `getActorFeeds` discovery |
| `maxPostsPerFeed` | integer | no | `100` | Max post rows emitted per feed (1–5000) |
| `maxFeeds` | integer | no | `5` | Max feeds processed in discovery mode (1–50) |
| `useProxy` | boolean | no | `false` | Route requests through Apify Proxy (BUYPROXIES94952) |

Exactly one of `feedUri` and `creatorHandle` must be set. Setting both, or neither, causes the Actor to exit immediately with a clear error message.

#### Single-feed mode example

```json
{
  "feedUri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot",
  "maxPostsPerFeed": 100,
  "useProxy": false
}
````

#### Creator-discovery mode example

```json
{
  "creatorHandle": "bsky.app",
  "maxPostsPerFeed": 50,
  "maxFeeds": 10,
  "useProxy": false
}
```

### 📤 Output

One row per post. Feed metadata is denormalised onto every row so a flat CSV is self-contained.

```json
{
  "feed_uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot",
  "feed_display_name": "Discover",
  "feed_creator_handle": "bsky.app",
  "feed_description": "Trending content from your personal network",
  "post_uri": "at://did:plc:sj5wj7libgr7omqiotenxadx/app.bsky.feed.post/3mlxmr4jyfs2s",
  "post_cid": "bafyreidgimgd7v3g3pazsp5oq7ur6bvedpnwohul26mss7cbffg6bdqjkm",
  "post_indexed_at": "2026-05-16T10:20:40.467Z",
  "post_text": "If you never read the book or saw the movie, you missed one of the greatest Pulitzer Prize winning sagas ever written.",
  "post_lang": "en",
  "post_reply_count": 89,
  "post_repost_count": 414,
  "post_like_count": 1288,
  "post_quote_count": 27,
  "author_did": "did:plc:sj5wj7libgr7omqiotenxadx",
  "author_handle": "louiseplease.bsky.social",
  "author_display_name": "Louise",
  "scraped_at": "2026-05-16T12:00:00+00:00"
}
```

Optional fields (`feed_description`, `post_lang`, `author_display_name`) are emitted as `null` when the API does not return them. Rows are never dropped for missing optional fields.

#### Export formats

After a run completes, click **Export** in the Apify Console to download:

- **JSON** — full fidelity, all fields, newline-delimited
- **CSV** — flat, one row per post, all columns including denormalised feed metadata
- **Excel** — `.xlsx` via the Apify dataset converter
- **XML** — structured per-item

All formats are available via the Apify API: `GET /datasets/{id}/items?format=csv&clean=true`.

### 💰 Pricing

Pay-Per-Event (PPE) — you pay only for what you use:

| Event | Price (USD) | When |
|---|---|---|
| `actor-start` | $0.05 | Once per run, at boot |
| `result-row` | $0.002 | Per post row written to the dataset |

#### Example costs

| Posts scraped | Actor starts | Total cost |
|---|---|---|
| 100 | 1 | $0.25 |
| 500 | 1 | $1.05 |
| 1,000 | 1 | $2.05 |
| 5,000 | 1 | $10.05 |

At the maximum single-run input (50 feeds × 100 posts = 5,000 rows) a single run costs around $10.05.

This rate is consistent with the companion Actor `bluesky-starter-pack` so the Bluesky Intel Suite has uniform pricing across both tools.

### 🚧 Limitations

- **Private or access-restricted feeds** are not exposed by the public AppView API — only feeds whose data is visible at `public.api.bsky.app` can be scraped.
- **Global feed discovery by keyword is not supported** — Bluesky's `getPopularFeedGenerators` endpoint returns `MethodNotImplemented` on the public AppView. Use creator-discovery mode (`creatorHandle`) to enumerate one creator's feeds at a time.
- **Post images, embeds, and quoted-post bodies are not extracted** — only the plain-text body (`post_text`) is captured. Image ALT text, external link cards, and quoted-post content are outside the current schema.
- **Reply thread expansion is out of scope** — only the top-level post-level row is emitted. Threaded context (parent/root posts) would require additional `getPostThread` calls and is not wired in this version.
- **The `maxPostsPerFeed` cap is client-side** — the Actor paginates until it has collected the cap or the API cursor is exhausted. If a feed has fewer posts than the cap, fewer rows are returned. This is expected behaviour, not a failure.
- **The Apify FREE tier retains run-scoped storage for 7 days only.** For longer retention, export your dataset immediately after the run completes or upgrade to a paid Apify plan.
- **Rate limiting** — the public AppView may rate-limit high-frequency requests. The Actor retries on `429` with exponential backoff, but very large scrapes (tens of thousands of rows) may require splitting into multiple runs.

### Tips for best results

- **Use AT URIs when possible.** The Actor resolves `bsky.app` web URLs on the fly (one extra `getProfile` API call), which adds latency. Pasting the AT URI directly skips this step.
- **Cap `maxPostsPerFeed` to what you actually need.** Feeds like "Discover" can have hundreds of posts; setting a lower cap keeps cost and runtime predictable.
- **Prefer creator-discovery mode for bulk collection.** If you want posts from all feeds by a creator like `bsky.app`, use `creatorHandle: "bsky.app"` rather than multiple single-feed runs — the Actor handles pagination for each feed sequentially.
- **Schedule recurring runs to track feed evolution.** Set up an Apify Schedule to run this Actor daily or weekly on a specific feed. Use a named dataset (via Apify API `datasetName` parameter at run time) to accumulate rows across runs.
- **Use the CSV export for spreadsheet workflows.** Because feed metadata is denormalised onto every row, no pivot or VLOOKUP is needed — the CSV is immediately usable in Google Sheets or Excel.
- **Combine with `bluesky-starter-pack`.** If you want both the posts from a community feed and the member list of the Starter Pack that drives that community, run both Actors and join on `author_handle`.

### Integrations

This Actor works natively with the Apify platform's built-in connectors:

- **Apify API** — trigger runs programmatically, poll for status, and fetch dataset items via REST. Full OpenAPI spec at `https://docs.apify.com/api/v2`.
- **Webhooks** — configure a webhook to POST the run result to your endpoint as soon as the Actor finishes.
- **Apify Schedules** — run this Actor on a cron schedule (e.g. daily at 08:00 UTC) to keep a feed dataset fresh.
- **Make (formerly Integromat)** — use the Apify Make module to trigger runs and route results to Google Sheets, Airtable, Slack, or anywhere Make connects.
- **Zapier** — Apify's Zapier integration triggers on run completion and passes dataset items downstream.
- **n8n** — use the HTTP Request node with the Apify REST API for fully self-hosted automation pipelines.

### ❓ FAQ

**Do I need a Bluesky account?**

No. The AT Protocol public AppView at `public.api.bsky.app/xrpc/` is unauthenticated by design — every endpoint this Actor calls is open to anyone without a login or API key.

**What is a feed URI?**

An AT URI like `at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot`. The part after `at://` before the second slash is a DID — a decentralized identifier. The collection is always `app.bsky.feed.generator`. The final segment is the `rkey` (record key) that identifies the specific feed. You can also just paste a `bsky.app` web URL — the Actor converts it automatically.

**How do I scrape all feeds published by a single creator?**

Set the `creatorHandle` input to the creator's Bluesky handle (e.g. `bsky.app`) and leave `feedUri` blank. The Actor calls `app.bsky.feed.getActorFeeds` and scrapes each feed in turn, up to the `maxFeeds` cap.

**Can I scrape Bluesky's built-in feeds like "Discover" or "What's Hot"?**

Yes. Those are published by the `bsky.app` account. Use the feed URI `at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot` for "Discover" / "What's Hot", or paste the `bsky.app/profile/bsky.app/feed/whats-hot` URL. You can also use creator-discovery mode with `creatorHandle: "bsky.app"` to get all feeds that account publishes.

**Why is `useProxy` off by default?**

The AT Protocol public API does not block datacenter IPs, so direct routing is faster and free. Enable proxy only if you are behind a restrictive ISP or a firewall that blocks outbound connections to `public.api.bsky.app`.

**Is scraping public Bluesky feeds legal?**

The AT Protocol is an open, federated protocol. `public.api.bsky.app` is explicitly unauthenticated and publicly accessible without login. The Bluesky Terms of Service permit accessing public data programmatically as long as you do not impersonate users or violate the AT Protocol's data-portability principles. Always verify the current Terms of Service at `bsky.social/about/support/tos` and your local jurisdiction's data-protection rules before using scraped data for commercial purposes.

**How do I export to Google Sheets?**

After the run finishes, click **Export → CSV** in the Apify Console and import the file into Google Sheets. Alternatively, use the Apify API URL shown in the run's **Output** tab to import data directly via `=IMPORTDATA("...")` in Sheets.

**What happens if a feed is empty?**

The Actor exits with a non-zero status code and a clear status message: `"No posts emitted — feed may be empty, private, or the URI invalid."` The dataset will have zero rows. Check that the feed URI is correct and the feed is publicly visible on `bsky.app`.

### Related Actors

- [Bluesky Starter Pack Scraper](https://apify.com/DevilScrapes/bluesky-starter-pack) — companion Actor in the Bluesky Intel Suite; exports full member lists from any public Bluesky Starter Pack. Pair with this Actor to cross-reference feed posts with community membership data.

### 💬 Your feedback

Found a bug, hit a rate limit, or need a new field on the output row? Open an issue on the Actor's Apify Store page or contact the Devil Scrapes team at [apify.com/DevilScrapes](https://apify.com/DevilScrapes). We ship updates within days of validated reports.

# Actor input Schema

## `feedUri` (type: `string`):

AT URI (<code>at://did:plc:.../app.bsky.feed.generator/...</code>) or Bluesky web URL (<code>https://bsky.app/profile/handle/feed/rkey</code>) of one feed generator. Mutually exclusive with <strong>Creator handle</strong>.

## `creatorHandle` (type: `string`):

Bluesky handle (e.g. <code>bsky.app</code>) or DID of a feed creator. The Actor enumerates every feed published by that user via <code>app.bsky.feed.getActorFeeds</code> and scrapes each. Mutually exclusive with <strong>Feed URI</strong>.

## `maxPostsPerFeed` (type: `integer`):

Maximum number of post rows emitted per feed. Acts as a client-side cap; pagination stops when this limit is reached. Default 100.

## `maxFeeds` (type: `integer`):

Maximum number of feeds to process when using creator-discovery mode. Ignored in single-feed mode. Default 5.

## `useProxy` (type: `boolean`):

Route requests through Apify Proxy (BUYPROXIES94952 residential). The AT Protocol public API does not block datacenter IPs — leave disabled unless you are behind a restrictive ISP.

## Actor input object example

```json
{
  "feedUri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot",
  "creatorHandle": "bsky.app",
  "maxPostsPerFeed": 100,
  "maxFeeds": 5,
  "useProxy": false
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "feedUri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot"
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/bluesky-feed-posts").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 = { "feedUri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot" }

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/bluesky-feed-posts").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 '{
  "feedUri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot"
}' |
apify call devilscrapes/bluesky-feed-posts --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Bluesky Feed Posts Scraper",
        "description": "Export posts from any public Bluesky custom or algorithm feed. No login needed. Feed metadata and engagement counts via the unauthenticated AT Protocol public API.",
        "version": "0.2",
        "x-build-id": "TNpHAj61iy3Mru0JE"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/devilscrapes~bluesky-feed-posts/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-devilscrapes-bluesky-feed-posts",
                "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/devilscrapes~bluesky-feed-posts/runs": {
            "post": {
                "operationId": "runs-sync-devilscrapes-bluesky-feed-posts",
                "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/devilscrapes~bluesky-feed-posts/run-sync": {
            "post": {
                "operationId": "run-sync-devilscrapes-bluesky-feed-posts",
                "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": {
                    "feedUri": {
                        "title": "Feed URI or URL",
                        "type": "string",
                        "description": "AT URI (<code>at://did:plc:.../app.bsky.feed.generator/...</code>) or Bluesky web URL (<code>https://bsky.app/profile/handle/feed/rkey</code>) of one feed generator. Mutually exclusive with <strong>Creator handle</strong>."
                    },
                    "creatorHandle": {
                        "title": "Creator handle (or DID)",
                        "type": "string",
                        "description": "Bluesky handle (e.g. <code>bsky.app</code>) or DID of a feed creator. The Actor enumerates every feed published by that user via <code>app.bsky.feed.getActorFeeds</code> and scrapes each. Mutually exclusive with <strong>Feed URI</strong>."
                    },
                    "maxPostsPerFeed": {
                        "title": "Max posts per feed",
                        "minimum": 1,
                        "maximum": 5000,
                        "type": "integer",
                        "description": "Maximum number of post rows emitted per feed. Acts as a client-side cap; pagination stops when this limit is reached. Default 100.",
                        "default": 100
                    },
                    "maxFeeds": {
                        "title": "Max feeds (discovery mode)",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Maximum number of feeds to process when using creator-discovery mode. Ignored in single-feed mode. Default 5.",
                        "default": 5
                    },
                    "useProxy": {
                        "title": "Use Apify Proxy",
                        "type": "boolean",
                        "description": "Route requests through Apify Proxy (BUYPROXIES94952 residential). The AT Protocol public API does not block datacenter IPs — leave disabled unless you are behind a restrictive ISP.",
                        "default": 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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
