# Bluesky Scraper — Posts, Profiles, Followers & Trends (`nice_dev/bluesky-posts-scraper`) Actor

Scrape Bluesky posts by keyword with no 100-post cap, plus account posts, profiles, followers, likes, reply threads, quotes, feeds, lists, starter packs and trending topics. No login. Export JSON, CSV, Excel.

- **URL**: https://apify.com/nice_dev/bluesky-posts-scraper.md
- **Developed by:** [Nice Dev](https://apify.com/nice_dev) (community)
- **Categories:** Social media, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.36 / 1,000 results

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?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

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

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 🦋 What is Bluesky Scraper?

**Bluesky Scraper** extracts **posts, profiles, followers, likes, reply threads, quotes, feeds, lists, starter packs and trending topics from [Bluesky](https://bsky.app)**: text, **likes, reposts, replies, quotes and bookmarks**, images with their descriptions, videos, link cards, hashtags, mentions, and the author's followers — for brand monitoring, research, lead lists or social listening.

Type a **keyword** (`climate`, `#ai`, `"open source"`), an **account** (`nytimes.com`) or paste any **Bluesky URL**, click **Start**, and download the results in JSON, CSV or Excel. No Bluesky account, no app password, nothing to set up — and it is **fast: 1,000 posts in under 3 minutes for $0.89**, with **no 100-post cap on searches**.

### 📋 What data can you extract from Bluesky?

One item per result — a post, an account, a trending topic, a list or a starter pack — 125 fields:

| Category                         | What you get                                                                                                                                                                                                                          |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 📝 **Post**                      | text, link, creation date, language — `A new era of sleep tech tracks your brain waves…`                                                                                                                                              |
| 📊 **Engagement**                | likes, reposts, replies, quotes, bookmarks and their total, and the **engagement rate** against the author's followers — `13 likes · 2 reposts · 1 quote · 7 bookmarks`                                                               |
| 🖼️ **Media and links**           | every image (full size, thumbnail, description), video, link card (title, description, picture), quoted post                                                                                                                          |
| #️⃣ **Hashtags, mentions, links** | hashtags, mentioned accounts, every link of the post                                                                                                                                                                                  |
| 🧵 **Thread**                    | reply or not, parent and root post (with their links and the handle of the account answered), depth in a reply thread, repost and pinned marks                                                                                                                                                  |
| 👤 **Author**                    | handle, name, avatar, verified check, pronouns, followers, follows, posts count, bio with the e-mail addresses and phone numbers written in it, website, banner                                                                                          |
| 🪪 **Account**                   | bio with the e-mail addresses and phone numbers written in it, pronouns, website, avatar, banner, followers, follows, posts, verified check, lists / feeds / starter packs created, pinned post, starter pack it joined by                               |
| 📈 **Account activity (optional)** | the account's **latest post** (date, text, link) and its **posting statistics** — posts per week, average and median likes, replies and reposts, its most liked post — `3.5 posts a week · median 12 likes` |
| 🤖 **AI (optional)**             | an **AI sentiment label** (positive, neutral or negative, with a score) and **your own AI labels** (the ones you wrote that apply to the post, with a score) — `negative, 0.91` · `pricing, 0.82`                                     |
| 📁 **Extras (optional)**         | a **summary of each keyword** (posts per day, average and median likes, top hashtags, top authors, top posts) and the **contacts found on the websites of the authors** — `climate: 412 posts, median 3 likes` · `hello@acme-shop.fr` |
| 📰 **Feed**                      | for the posts of a feed (or of the feeds an account created): the feed's name, description and creator                                                                                                                                |
| 📚 **List / starter pack**       | name, description, purpose, number of members, last update and creator of a list or a starter pack — `Community Showcase · 21 members` |
| 🔥 **Trending topic**            | title, category, post count, start time, rank, top accounts                                                                                                                                                                           |
| 🔗 **Where it comes from**       | the keyword, account or URL that found it, the post or account it relates to, when the account liked it                                                                                                                               |

Every field, with an example, is listed in the **Output** section below.

### ✅ Why use Bluesky Scraper?

- 🚀 **Fast**: 1,000 search results in under 3 minutes, 180 mixed results (accounts, followers, lists, feeds) in 3 seconds.
- 🔎 **Searches with no 100-post cap**: the search goes back in time page after page, as deep as **Max results**, with every Bluesky search filter (language, dates, author, mentions, website, hashtags, exact phrase).
- 🌐 **The whole network, not only the search**: the **Network stream** reads every post published on Bluesky in the last hours (up to 36) and keeps the ones that match your keywords.
- 🧩 **All of Bluesky in one Actor**: searches, accounts (profile, posts, followers, follows, **liked posts**, reposts, the **feeds and starter packs they created**), a post's reply thread, **quotes**, likers and reposters, custom feeds, lists, starter packs, trending topics **with their posts** — combined in one run.
- 🤖 **What they think**: tick **AI sentiment label** for a positive / neutral / negative label on each post, and write **AI labels** (`pricing`, `complaint: The author reports a problem`) to see which of your topics each post is about.
- 📊 **A report per keyword**: tick **Keyword statistics** and get, next to the dataset, one record that sums up each keyword you searched: how many posts and replies, posts per day, average and median likes, replies, reposts and quotes, median engagement rate, the top hashtags, authors and posts.
- 🔔 **Monitoring built in**: tick **Only new results**, schedule the Actor, and each run returns (and charges) only what it has never delivered before.
- 🔐 **No login**: no account, no app password to hand over.
- 🔌 API, scheduling, monitoring, integrations (Make, Zapier, n8n, Google Sheets…) and JSON/CSV/Excel export via the Apify platform.

### 🚀 How to scrape Bluesky

1. Create a free Apify account.
2. Open **Bluesky Scraper** and type a **Search keyword** (e.g. `climate`), or add **Accounts** (e.g. `nytimes.com`).
3. Or paste Bluesky URLs into **Bluesky URLs**: a post, a profile, a custom feed, a list, a starter pack, a search or a hashtag page.
4. Set **Max results** (100 by default, 0 = no limit) — and **Max per source** when you combine several sources — then click **Start**.
5. Download the dataset in JSON, CSV, Excel or via API.

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

This Actor uses **pay per event** pricing: **$0.89 per 1,000 results** (posts, accounts, topics, lists or starter packs) — plus **$0.0006 per run start** (one per GB of memory: one at the default 512 MB, 6 cents per 100 runs). Higher Apify plans pay less per result: $0.72 (Bronze), $0.54 (Silver) and $0.36 (Gold) per 1,000. The **Network stream** adds **$0.002 per hour of the network read** (6 hours = $0.012; a started hour counts as a full one), whatever the number of posts it finds. The filters Bluesky does not apply itself (dates, `language`, the likes / reposts / replies / engagement minimums, `mediaOnly`, `withLinksOnly`, `excludeKeywords`, and `minFollowers`) are checked by the Actor on every post it reads, kept or not: each check costs **$0.01143 per 1,000 posts checked** ($0.01095 Bronze, $0.01048 Silver, $0.01 Gold) — `filter-check`, and `detail-filter-check` for `minFollowers`. **Author profiles** (`includeAuthorProfiles`, off by default: the author's followers, follows, posts count, bio, website and banner added to each post, and the counts and website added to each follower, follow, liker or list member) are charged apart, as the **Author profile** event: **$0.19 per 1,000 rows completed** ($0.18 Bronze, $0.17 Silver, $0.16 Gold); leave the option unticked to pay for the rows alone. Four more options are off by default and charged apart, each by its own event (see the **Pricing** tab for the amounts): a price per post given an **AI sentiment label** (`post-sentiment`; a post without text costs nothing), a price per post and per label judged with **AI labels** (`ai-label`; each label you write is charged once for each post it is judged on, whether it applies or not), a price per keyword summarised (**Keyword statistics**, `keyword-stats`; a keyword needs at least 5 posts in the run, at most 50 keywords are given), and a price per author whose website gives an e-mail or a phone number (**Contacts from the author's website**, `website-contacts`; a website that gives neither costs nothing). The two AI options need 2 GB of memory (Run options → Memory): with less, they are skipped, the log says so and nothing is charged. The engagement rate is free. Example: 20,000 posts ≈ $17.80; a daily watch of 300 new posts ≈ $0.27 a day. Platform usage (compute, proxy) is included in the price.

### ⚙️ Input

```json
{
    "query": "climate",
    "language": "en",
    "maxItems": 500
}
```

Several keywords and accounts, a cap per source, only recent posts, only the ones not delivered before:

```json
{
    "searchQueries": ["climate", "#ai", "\"open source\""],
    "handles": ["nytimes.com"],
    "accountData": ["profile", "posts", "followers"],
    "maxItemsPerQuery": 200,
    "postedAfter": "7 days",
    "onlyNew": true,
    "stateKey": "brand-watch"
}
```

Or with Bluesky URLs:

```json
{
    "startUrls": [
        { "url": "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l" },
        { "url": "https://bsky.app/starter-pack/emilyliu.me/3kvq2t2ctis2z" }
    ],
    "postData": ["replies", "quotes", "likers"],
    "maxItems": 1000
}
```

| Field                                                                   | Notes                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ----------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`, `searchQueries`                                                | Keyword, hashtag or phrase, as typed in the Bluesky search box (`climate`, `#ai`, `"open source"`); `searchQueries` adds more searches.                                                                                                                                                                                                                                                                                                                                                                              |
| `sort`                                                                  | `latest` (no cap, goes back in time as deep as `maxItems`) or `top` (Bluesky's most engaged posts, 100 per search at most).                                                                                                                                                                                                                                                                                                                                                                                          |
| `searchEngine`, `streamHours`                                           | `auto` (search, network stream if Bluesky refuses the search), `search`, or `stream`: every post of the last `streamHours` hours (1-36) whose text has the keyword.                                                                                                                                                                                                                                                                                                                                                  |
| `handles`                                                               | Accounts: a handle (`nytimes.com`, `@user.bsky.social`), a DID or a profile URL.                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `accountData`                                                           | What to collect for each account: `profile`, `posts`, `followers`, `follows`, `likes`, `reposts`, `feeds` (the posts of every feed the account created) `starter-packs` (the members of every starter pack it created, after the pack's own card) and `lists` (one card row for each list it made); each feed and pack has its own **Max per source** cap, up to 500 of each per account.                                                                                                                                                                                                    |
| `authorFeedFilter`, `includeReposts`                                    | Which posts of an account: `posts_with_replies`, `posts_no_replies`, `posts_with_media`, `posts_with_video`, `posts_and_author_threads`; reposts kept or not.                                                                                                                                                                                                                                                                                                                                                        |
| `profileSearchQueries`                                                  | Find accounts by name or bio keyword.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| `includeLatestPost`, `includeAccountStats` | Two extras on the profile row of each account of `accountData` (Profile) and of `profileSearchQueries`, off by default and included in the price of the row (one extra request per account): its latest own post (date, text, link), and its posting rate and engagement over its last 100 own posts (no reposts, no replies). |
| `startUrls`                                                             | Bluesky URLs (or at:// URIs): post, profile, followers / follows page, custom feed, list, starter pack, search, hashtag — e.g. `https://bsky.app/profile/nytimes.com`.                                                                                                                                                                                                                                                                                                                                               |
| `postData`, `threadDepth`                                               | For each post URL: its `replies` (reply thread, `threadDepth` levels), `quotes`, `likers`, `reposters`.                                                                                                                                                                                                                                                                                                                                                                                                              |
| `repliesPerPost` | Also read the replies under each post found by a search, an account, a feed or a list: up to this many per post (0 = off). Each reply is a result of its own and counts in `maxItems`; a post that has replies keeps room for them (up to this number), and the room a post's replies do not use goes back to the next posts. |
| `feedPresets`                                                           | Public feeds: `discover`, `hot-classic`, `news`, `science`, `bsky-team`.                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `includeTrends`, `maxPostsPerTrend`                                     | The current trending topics (up to 25), and up to N posts of each.                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `maxItems`, `maxItemsPerQuery`                                          | Stop after this many results for the whole run / for each source (`0` = unlimited).                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `includeAuthorProfiles`                                                 | Author followers, follows, posts count, bio (with its e-mail addresses), website, banner and profile indexing date on each post; counts and website on each account a page gives short (followers, likers, list members). Default off, charged per row it completes (**Author profile** event); off = the rows alone. `minFollowers` reads the counts by itself (not charged as **Author profile**).                                                                                                                 |
| `includeSentiment`                                                      | An AI sentiment label (positive / neutral / negative) and its score on each post and reply, in two extra fields (off by default). Charged once per row labelled; nothing for a post without text. Requires 2 GB of memory (Run options → Memory); with less the option is skipped and nothing is charged.                                                                                                                                                                                                            |
| `aiLabels`                                                              | AI labels: your own labels, one per entry — a name (`pricing`) or a name and a sentence that is true when the label applies (`competitor: The author compares tools`); up to 20. Each post and reply gets the labels that apply, with a score from 0 to 1, in `aiLabelMatches`. Empty (the default) = off. Charged per row and per label judged, whether it applies or not; nothing for a post without text. Requires 2 GB of memory (Run options → Memory); with less the option is skipped and nothing is charged. |
| `includeKeywordStats`                                                   | A summary of each searched keyword in the `KEYWORD_STATS` record of the run's key-value store, never in the dataset (off by default). Charged once per keyword given; a keyword needs at least 5 posts in the run. A run with no keyword search gives nothing and charges nothing.                                                                                                                                                                                                                                   |
| `includeWebsiteContacts`                                                | Open the website of each author (the profile's website, the links of its bio, or its handle when that is a domain of its own) and add the e-mails, phone numbers and social links found there (off by default; needs `includeAuthorProfiles`, without it nothing happens). Charged once per author for whom at least one e-mail or phone number is found; a website that cannot be opened or gives none costs nothing.                                                                                               |
| `postedAfter`, `postedBefore`                                           | Creation date range of posts: `2026-09-01`, or a period before now (`7 days`, `24 hours`, `2 weeks`).                                                                                                                                                                                                                                                                                                                                                                                                                |
| `language`                                                              | Language of the posts, as a code (`en`, `fr`, `pt-br`); posts without a declared language are dropped.                                                                                                                                                                                                                                                                                                                                                                                                               |
| `author`, `mentions`                                                    | Search filters: posts of an account, posts mentioning an account (a handle such as `nytimes.com`, or a DID).                                                                                                                                                                                                                                                                                                                                                                                                         |
| `domain`, `exactUrl`                                                    | Search filters: posts linking to a website (`nytimes.com`), or to one exact page.                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `hashtags`                                                              | Search filter: posts carrying all these hashtags (`ai`, `climate`).                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| `includeReplies`, `mediaOnly`, `withLinksOnly`                          | Keep replies or not; only posts with images or video; only posts with a link.                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `minLikes`, `minReposts`, `minReplies`, `minEngagement`, `minFollowers` | Minimum likes, reposts, replies, total engagement, author followers.                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| `includeKeywords` | Keep only the posts whose text, image descriptions or link card contains at least one of these words (case and accents ignored). |
| `excludeKeywords`                                                       | Drop the posts whose text, image descriptions or link card contains one of these words (case and accents ignored).                                                                                                                                                                                                                                                                                                                                                                                                   |
| `onlyNew`, `stateKey`, `resetState`                                     | Monitoring: only the results never delivered under this memory key; `resetState` forgets the memory.                                                                                                                                                                                                                                                                                                                                                                                                                 |
| Advanced                                                                | `proxyConfiguration` (Apify proxy by default, included in the price; the residential proxy is not available), `maxConcurrency`, `maxRequestsPerMinute`, `maxRequestRetries`, `debugLog`.                                                                                                                                                                                                                                                                                                                             |

### 📦 Output

A post (shortened: empty fields left out):

```json
{
    "type": "post",
    "id": "at://did:plc:eclio37ymobqex2ncko63h4r/app.bsky.feed.post/3mw5qqzz4cl2o",
    "url": "https://bsky.app/profile/nytimes.com/post/3mw5qqzz4cl2o",
    "source": "account-posts",
    "sourceInput": "nytimes.com",
    "scrapedAt": "2026-09-23T03:18:35.976Z",
    "uri": "at://did:plc:eclio37ymobqex2ncko63h4r/app.bsky.feed.post/3mw5qqzz4cl2o",
    "text": "A new era of sleep tech tracks your brain waves to gauge your sleep stages. […] Wirecutter tested three of these devices: nyti.ms/4ArDN3l",
    "createdAt": "2026-09-23T03:00:03.221Z",
    "indexedAt": "2026-09-23T03:00:06.375Z",
    "langs": [],
    "likeCount": 13,
    "repostCount": 2,
    "replyCount": 0,
    "quoteCount": 1,
    "bookmarkCount": 7,
    "engagementTotal": 16,
    "hashtags": [],
    "mentions": [],
    "links": ["https://nyti.ms/4ArDN3l"],
    "images": [],
    "externalLink": {
        "url": "https://nyti.ms/4ArDN3l",
        "title": "I Tried to Hack My Brain Waves to Improve My Sleep",
        "description": "EEG is the next frontier of sleep tech. But does it work?",
        "thumb": "https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:eclio37ymobqex2ncko63h4r/bafkreicnzvgcnslu3wavzowzodglmefukxisgzsh2tfrw4df3o477poph4"
    },
    "embedType": "external",
    "hasMedia": false,
    "isReply": false,
    "isRepost": false,
    "labels": [],
    "facets": [],
    "authorDid": "did:plc:eclio37ymobqex2ncko63h4r",
    "authorHandle": "nytimes.com",
    "authorDisplayName": "The New York Times",
    "authorVerified": true,
    "authorFollowersCount": 1348269,
    "authorFollowsCount": 123,
    "authorPostsCount": 43234,
    "authorEmails": [],
    "authorPhones": [],
    "authorWebsiteEmails": [],
    "authorWebsitePhones": [],
    "authorSocialLinks": [],
    "authorLabels": [],
    "authorUrl": "https://bsky.app/profile/nytimes.com",
    "emails": [],
    "phones": [],
    "topAccounts": []
}
```

You can download the dataset in various formats such as JSON, HTML, CSV or Excel.

#### Keyword statistics

With **Keyword statistics**, the run also writes one record, `KEYWORD_STATS`, to its key-value store (a link is in the run's log). It is not a row of the dataset. Shortened example:

```jsonc
{
    "generatedAt": "2026-10-10T12:00:00.000Z",
    "onlyNew": false,
    "rowsRead": 412,
    "minRowsPerKeyword": 5,
    "keywordsFound": 1,
    "keywordsDelivered": 1,
    "keywords": [
        {
            "keyword": "climate",
            "posts": 380,
            "replies": 32,
            "firstPostAt": "2026-10-09T09:42:16.000Z",
            "lastPostAt": "2026-10-10T08:58:13.000Z",
            "periodDays": 0.95,
            "postsPerDay": 412,
            "perPost": {
                "likes": { "mean": 6.34, "median": 1 },
                "replies": { "mean": 0.66, "median": 0 },
                "reposts": { "mean": 1.48, "median": 0 },
                "quotes": { "mean": 0.28, "median": 0 },
            },
            "engagementRateMedian": null,
            "mediaShare": 0.169,
            "authors": 260,
            "verifiedAuthorsShare": 0.0769,
            "rowsWithLanguage": 398,
            "languages": [{ "language": "en", "share": 0.71, "rows": 283 }],
            "topHashtags": [{ "hashtag": "climate", "rows": 41 }],
            "topAuthors": [{ "username": "example.bsky.social", "rows": 12, "likes": 285 }],
            "topPosts": [
                {
                    "id": "at://did:plc:x/app.bsky.feed.post/3abc",
                    "url": "https://bsky.app/profile/example.bsky.social/post/3abc",
                    "likes": 806,
                },
            ],
            "sentiment": null,
        },
    ],
    "notDelivered": [],
}
```

- A post counts under the keyword it was found with (a search keyword, a search or hashtag URL, or a keyword read from the **Network stream**), once: a post found by two keywords of the same run counts under the first one only. Posts of accounts, feeds, threads and trending topics, and profile rows, belong to no keyword.
- Averages and medians cover posts and replies together; a count Bluesky does not give is left out, never counted as 0. `postsPerDay` is the number of rows divided by the days between the first and the last post, a period under one day counting as one day. `languages` lists the first language each post declares. `sentiment` is filled when **AI sentiment label** is on: the share of positive, neutral and negative posts among those labelled.
- A keyword needs at least 5 posts (replies included) in the run; at most 50 keywords are given, the biggest first, and the keywords left out are named in `notDelivered`. With **Only new results**, only the posts delivered in this run are counted (`onlyNew: true` in the record).

#### Contacts from the author's website

With **Contacts from the author's website** (and **Author follower counts**, where the profile comes from), the Actor opens the website of each author: the `website` of its profile, the links written in its bio, and its handle when that is a domain of its own (`nytimes.com`; never `name.bsky.social`). It reads the home page and up to two pages of the same site that the home page links as contact, about or legal notice (a link-in-bio page such as Linktree is one page). The row gets `authorWebsiteRead` (the site opened), `authorWebsiteEmails` and `authorWebsitePhones` (`+` and digits for an international number), and `authorSocialLinks` (Instagram, Facebook, LinkedIn, X, YouTube, TikTok, WhatsApp and Telegram profiles, from the bio and from the website). Each website is read once per run: every post of the author carries the same values.

An author is charged once per run, and only when at least one e-mail address or phone number is found on its website; the social links are free. Links to Instagram, Facebook, YouTube, TikTok, X, LinkedIn, WhatsApp, Telegram and Threads are never opened, and the Actor reads only the website the author itself cites. A website that cannot be opened, is protected or gives nothing costs nothing, and the log counts them.

#### All 125 fields

| Fields                                                                                                                                                    | What you get                                                                                                                                                                                                                                                                                                                                           |
| --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `type`, `id`, `url`                                                                                                                                       | **Result**: `post`, `profile`, `trend` or `list` (a list or a starter pack); the post's AT-URI, the account's DID, `trend:<topic>` or the AT-URI of the list; its bsky.app page                                                                                                                                                                                                                                   |
| `source`, `sourceInput`, `scrapedAt`                                                                                                                      | what found it (`search`, `stream`, `account-posts`, `followers`, `likes`, `post`, `post-replies`, `quotes`, `trend-posts`, `account-lists`…), the keyword / account / URL, ISO timestamp                                                                                                                                                                                                |
| `uri`, `cid`, `text`, `createdAt`, `indexedAt`, `langs`                                                                                                   | **Post**: AT-URI, content hash, full text, creation and indexing dates, declared languages                                                                                                                                                                                                                                                             |
| `likeCount`, `repostCount`, `replyCount`, `quoteCount`, `bookmarkCount`, `engagementTotal`                                                                | **Engagement** at scrape time; the total = likes + reposts + replies + quotes                                                                                                                                                                                                                                                                          |
| `engagementRate`, `engagementBase`                                                                                                                        | **Engagement rate** (computed for you, free): the total divided by the author's follower count (`followers`; needs **Author follower counts**), 4 decimals — `0.0249`. Bluesky shows no views. `null` when the followers are not known, and on accounts and topics                                                                                     |
| `sentiment`, `sentimentScore`, `aiLabelMatches`                                                                                                           | **AI** (options): `positive`, `neutral` or `negative` for the text of the post or reply, and the confidence in it from `0` to `1` (**AI sentiment label**); the labels you wrote that apply to the text, each as `{ "label", "score" }`, `[]` when none applies (**AI labels**). `null` when the option is off or skipped, or when the row has no text |
| `hashtags`, `mentions`, `links`, `facets`                                                                                                                 | hashtags without `#`, mentioned accounts (DID and handle), every link, rich-text facets (byte ranges of links, mentions and tags)                                                                                                                                                                                                                      |
| `images`, `video`, `externalLink`, `quotedPost`, `embedType`, `hasMedia`                                                                                  | **Media**: images (full size, thumbnail, description, size), video (playlist, thumbnail), link card, quoted post, kind of embed                                                                                                                                                                                                                        |
| `isReply`, `replyParentUri`, `replyRootUri`, `replyToHandle`, `replyToUrl`, `replyRootUrl`, `threadDepth`, `replyDisabled` | **Thread**: reply or not, parent and first post (their bsky.app pages, and the handle of the account answered where the page shows it: an account's posts, a feed, a list, a reply thread — empty for a post found by a search), depth in a reply thread (0 = the post, 1 = direct reply, -1 = its parent), replies restricted |
| `isRepost`, `repostedByHandle`, `repostedAt`, `isPinned`, `labels`                                                                                        | repost in an account's timeline (by whom, when), pinned post, moderation labels                                                                                                                                                                                                                                                                        |
| `feedName`, `feedDescription`, `feedCreatorHandle`, `feedCreatorDisplayName`                                                                              | **Feed** a post was read from (a feed URL, a preset, or a feed an account created): its name, description, the handle and name of its creator; empty for any other source                                                                                                                                                                              |
| `authorDid`, `authorHandle`, `authorDisplayName`, `authorAvatar`, `authorCreatedAt`, `authorVerified`, `authorPronouns`, `authorLabels`, `authorUrl`      | **Author** of the post (the pronouns they wrote, as typed)                                                                                                                                                                                                                                                                                             |
| `authorFollowersCount`, `authorFollowsCount`, `authorPostsCount`, `authorDescription`, `authorEmails`, `authorPhones`, `authorWebsite`, `authorBanner`, `authorIndexedAt` | the author's counts, bio, the e-mail addresses and phone numbers written in the bio, website, banner and profile indexing date (with `includeAuthorProfiles`)                                                                                                                                                                                                            |
| `authorWebsiteRead`, `authorWebsiteEmails`, `authorWebsitePhones`, `authorSocialLinks`                                                                    | **Author's website** (**Contacts from the author's website**): the website opened, the e-mails and phone numbers found on it, the social profiles of the bio and of the website. `null` and `[]` when the option is off                                                                                                                                |
| `did`, `handle`, `displayName`, `description`, `emails`, `phones`, `pronouns`, `website`, `avatar`, `banner`                                                        | **Account**: DID, handle, name, bio (or trending topic description), the e-mail addresses and the phone numbers written in the bio, pronouns, website (a profile row or a list that includes the author profiles), pictures                                                                                                                                                  |
| `followersCount`, `followsCount`, `postsCount`, `isVerified`, `verification`, `pinnedPostUri`                                                             | the account's counts, verified check and its details, pinned post                                                                                                                                                                                                                                                                                      |
| `latestPostAt`, `latestPostText`, `latestPostUrl` | **Latest post** (**Latest post of each account**, profile rows): when it was written, its text and its bsky.app page; `null` when the option is off or the account has no post of its own among its last entries |
| `postsSampled`, `postsPerWeek`, `avgLikes`, `avgReplies`, `avgReposts`, `medianEngagement`, `medianLikes`, `medianReplies`, `medianReposts`, `topPostLikes`, `topPostUrl` | **Statistics** (**Statistics of each account**, profile rows): computed on the account's last own posts (100 at most; no repost, no reply) — how many were read, posts per week (their number over the time between the oldest and the newest, at least one day), means and medians of likes, replies and reposts (2 decimals), the median of likes + replies + reposts + quotes, the most liked post (likes and page). `null` when the option is off or the account has no post |
| `listsCount`, `feedsCount`, `starterPacksCount`, `isLabeler`, `chatAllowIncoming`, `associated`                                                           | lists, feeds and starter packs it created, moderation service or not, who can message it, raw details                                                                                                                                                                                                                                                  |
| `joinedViaStarterPack`, `hidesFromLoggedOut`                                                                                                              | the starter pack it joined by; the account asked apps not to show it to logged-out visitors                                                                                                                                                                                                                                                            |
| `relatedTo`, `likedAt`                                                                                                                                    | the account / post / list / topic the result relates to (followers of…, quotes of…), when the account liked or reposted the post                                                                                                                                                                                                                       |
| `topic`, `category`, `status`, `postCount`, `startedAt`, `rank`, `feedUri`, `topAccounts`                                                                 | **Trending topic**: id, category, status, post count, start time, rank (1 = first), its feed, the accounts driving it                                                                                                                                                                                                                                  |
| `purpose`, `listItemCount`, `updatedAt`, `creatorHandle`, `creatorDid` | **List or starter pack** (`type` = `list`; the name, description and picture are in `displayName`, `description` and `avatar`, the creation date of a starter pack in `createdAt`): `curatelist`, `modlist`, `referencelist` or `starterpack`, how many accounts it holds, when it was last updated, and who made it |

### 💡 Tips

#### How to get more results

Leave `sort` on `latest` and raise `maxItems`: the search goes back in time page after page, with no cap of 100 posts. Combine keywords, accounts and URLs in one run, and set `maxItemsPerQuery` so that one big source does not use up the whole budget.

#### How to reduce costs

The price is per result, so the levers are `maxItems`, `maxItemsPerQuery`, the filters (a filtered-out post costs only its small filter check) and `onlyNew` for recurring runs (you never pay twice for the same result). **Author follower counts** is charged per row it completes: leave it off (the default) when you do not need follower counts. The AI options are charged per post (and per label): leave them off, or keep the number of labels low, when you only need the text. **Keyword statistics** is charged per keyword and **Contacts from the author's website** per author with a contact: leave them off when the dataset is enough. Search filters (`author`, `mentions`, `domain`, `hashtags`…) are applied by Bluesky itself: they cost nothing and make each page count; dates and `language` are sent to Bluesky too, then checked on each post.

#### Several searches in one run

Fill `searchQueries`, `handles` and `startUrls`: each keyword, each account × each kind of account data, each URL is a source of its own. A result found by several sources is saved — and charged — once. Set `maxItemsPerQuery` to give every source its own cap: without it the first sources can use up the whole `maxItems` budget.

#### Monitoring: only the new results

Tick **Only new results** (`onlyNew`) and schedule the Actor. The first run returns everything; each later run skips the results already delivered: they are not saved and not charged. The memory lives in a named key-value store of your account (`bluesky-posts-scraper-seen`, up to 150,000 results per key) and is only updated with results that really reached the dataset, so a failed run never hides anything. Give each schedule its own `stateKey` (two schedules sharing a key would hide each other's results), and tick `resetState` once to start over. A search sorted by `latest`, an account's timeline, followers and follows stop once they meet a run of results you already have — half your cap, 20 at most (the pinned post and reposts are not counted) — so the older results your cap left out are never delivered later.

#### Filter by creation date

`postedAfter` and `postedBefore` take a date (`2026-09-01`, the whole day is included, UTC) or a period before now (`7 days`, `2 weeks`, `1 month`; via the API also `24 hours` or a full ISO date-time). The filter reads a post's `createdAt`; accounts and trending topics are not filtered by date. Filtered-out posts are not saved, not charged as results and do not count in `maxItems`; each post the date filter checks is charged a small filter check. Searches send the dates to Bluesky, and an account's timeline stops at the first page that is entirely too old.

#### Search or network stream?

The search finds posts by word, hashtag, image description and link, ranked by date or engagement, as far back as Bluesky keeps them. The **Network stream** (`searchEngine: stream`) reads the whole network for the last `streamHours` hours instead: every post whose TEXT contains the keyword, none left out, at $0.002 per hour read.

### 🔌 Integrations and API

Call the Actor via the Apify API, the JavaScript or Python clients, or connect it with integrations and webhooks (Make, Zapier, n8n, Google Sheets, Slack, Airtable…). The dataset can be fetched as JSON or CSV from any tool.

### 🤖 Use with AI agents (MCP)

AI agents (Claude, ChatGPT, Cursor…) can find and run this Actor through the [Apify MCP server](https://mcp.apify.com), billed to their Apify account like any run. It returns one item per Bluesky result: a post, an account or a trending topic (`type` says which). Actor id: `nice_dev/bluesky-posts-scraper`; MCP server with this Actor only: `https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/bluesky-posts-scraper`.

Smallest input, for a cheap first call:

```json
{
    "query": "climate",
    "maxItems": 10
}
```

Key output fields: `type`, `url`, `text`, `createdAt`, `likeCount`, `repostCount`, `replyCount`, `authorHandle`.

Cost: $0.89 per 1,000 results plus $0.0006 per run start ($0.36 per 1,000 on the Gold plan); the Network stream, the Actor's own filters and the options (author profiles, AI sentiment label, AI labels, keyword statistics, author websites; all off by default) cost extra, see the pricing section above. Cap each call with `maxItems` and, through the API, with the run option `maxTotalChargeUsd`.

### ❓ FAQ

#### Is it legal to scrape Bluesky?

The Actor only reads what Bluesky shows publicly to anyone, without an account. It logs in to nothing. With **Contacts from the author's website** it also opens the public website an author itself cites in its profile, and nothing else. Results contain personal data (handles, names, bios, posts, and the e-mails or phone numbers people wrote in their bio or published on their website), which is protected by GDPR: do not store it without a legitimate reason, and delete what an author has deleted. You are responsible for using the data in compliance with Bluesky's Terms of Service and applicable law. This Actor is not affiliated with Bluesky.

#### Does it need a Bluesky account, an app password or a proxy?

No account and no app password. The proxy is included in the price: leave the default setting (the residential proxy is not available). With `searchEngine: auto`, a keyword whose search Bluesky refuses is read from the network stream instead.

#### Is the data safe to open in Excel or to show on a web page?

Posts and bios are their authors' own words, copied as they are. A text can begin with `-`, `+`, `=` or `@` (a mention, `-20% today`): Excel and Google Sheets may read such a cell of a CSV file as a formula. The Actor leaves the text as it is, so that the JSON and the API give the real value: when you open a CSV, import these columns as text. Every URL field holds an http(s) URL or null. On a web page, escape every field like any text written by a stranger.

#### Known limitations

- `top` searches return 100 posts at most per search (Bluesky does not page them); `latest` has no such cap.
- Trending topics: 25 at most, as Bluesky lists them.
- The network stream reaches 36 hours back at most, matches the post's text only (not image descriptions nor link cards), and reads the period from its start: with a cap, the earliest posts of the period come first. It applies `from:` and `lang:`; a keyword with `to:`, `mentions:`, `domain:`, `since:` or `until:` is skipped (use the `mentions`, `domain` and date fields), and so is a keyword made of operators only.
- An account's likes are read on its own server when it is a Bluesky server; an account hosted elsewhere is listed in `FAILED_REQUESTS` instead.
- `replyToHandle` is given where the page shows the post answered (an account's posts, a feed, a list, a reply thread); a post found by a search has it empty, its `replyToUrl` and `replyRootUrl` are still given.
- **Latest post of each account** and **Statistics of each account** read the last entries of the account's own timeline (20, or 100 for the statistics); an account whose last 20 entries are all reposts has no latest post. Followers, follows and likers get neither.
- A pasted list or starter pack URL, and `lists` / `starter-packs` of `accountData`, give one card row for each list or pack (a result like any other, counted in `maxItems`), before the posts and the members.
- `onlyNew` remembers result ids, not their content: a post whose likes changed is not returned again.

**A run the platform stops without warning** (out of memory, run timeout)

- Resurrect it: it goes on from where it stood at most a minute before the stop. The results already saved are skipped: none is delivered or charged twice, and `maxItems` still counts them.
- With `onlyNew`, the memory is saved after each write (at most once every 2 seconds): resurrect the stopped run and the results it had saved meanwhile join the memory; leave it stopped for good, and the next run may return the results of its last 2 seconds once more.

#### Something doesn't work?

The last line of the log counts the results saved, filtered out, not found on Bluesky (an account, post or list that does not exist or was deleted), and the requests that failed after every retry. Those requests and the targets not found are listed, with the reason, in the `FAILED_REQUESTS` record of the run's key-value store. A run that saved nothing and had failed requests fails, and its last message gives the cause. A run that saved some results fails too when at least as many requests failed for good as were read (page 1 read, the next pages refused): a green run with a short dataset would hide the outage. One failed request among many is only a warning, and a search Bluesky refuses that the network stream reads instead (**Search source** Auto) is not counted as lost.

If Bluesky changes its answers, you are told instead of paying for blank rows: if the first 20 posts read all lack their creation date, text or author handle — or the first 20 accounts their handle —, the run saves nothing more, stops and fails, and its last message names the missing field.

### 🛟 Support

Open an issue in the **Issues** tab with a link to your run: the run log and the `FAILED_REQUESTS` record of the key-value store show exactly what failed and why.

# Actor input Schema

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

Keyword, hashtag or phrase, exactly as typed in the Bluesky search box (e.g. `climate`, `#ai`, `"open source"`).

## `searchQueries` (type: `array`):

Several searches in one run, added to **Search keyword**. Posts found by several searches are saved once.

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

**Latest** goes back in time with no 100-post cap (as deep as Max results). **Top** = Bluesky's most engaged posts, 100 per search at most (Bluesky does not page top results).

## `searchEngine` (type: `string`):

**Auto** = Bluesky search; if Bluesky refuses the search for good, falls back to the network stream. **Network stream** = read EVERY post published on Bluesky in the last **Stream hours** (1-36) and keep those whose text contains the keyword: full coverage of recent posts, no ranking, text match only (no hashtag-only or image-text match).

## `streamHours` (type: `integer`):

With **Network stream**: how many hours back to read (1-36). 24 hours ≈ 3 million posts read, charged per hour read.

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

Accounts to scrape. What is collected for each one is set in **Account data**.

## `accountData` (type: `array`):

For each account: its profile, its posts, its followers, the accounts it follows, the posts it liked, the posts it reposted, the posts of the feeds it created, the members of the starter packs it created (each pack with its own card row), the lists it made (one card row each: name, purpose, members, last update). Followers / follows / likes can be long: they share **Max per source**; each feed and each starter pack is a source of its own with its own cap.

## `authorFeedFilter` (type: `string`):

Which posts of the account: all (with its replies), without replies, only posts with media, only with video, or posts plus the account's own threads.

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

Keep the posts the account reposted in its timeline (marked `isRepost`, original author kept).

## `profileSearchQueries` (type: `array`):

Find accounts by name or bio keyword (one profile per result).

## `includeLatestPost` (type: `boolean`):

Add the date, text and URL of the account's latest own post (not a repost, not a reply) to its profile row, in `latestPostAt`, `latestPostText` and `latestPostUrl`. One extra request per account, included in the price of the row. Only the profile rows of **Accounts** (Profile) and **Search accounts** get it, not the followers or follows of an account. Unticked (default): those fields stay empty.

## `includeAccountStats` (type: `boolean`):

Add posting rate and engagement to the profile row of each account, computed on its last 100 own posts (not reposts, not replies): `postsSampled`, `postsPerWeek`, `avgLikes`, `avgReplies`, `avgReposts`, `medianEngagement`, `medianLikes`, `medianReplies`, `medianReposts`, `topPostLikes` and `topPostUrl`. One extra request per account, included in the price of the row. Only the profile rows of **Accounts** (Profile) and **Search accounts** get it. Unticked (default): those fields stay empty.

## `startUrls` (type: `array`):

Any bsky.app URL (or at:// URI): a post (plus **Post data**), a profile (like **Accounts**), a followers or follows page, a search or hashtag page, a custom feed, a list (its posts and members), a starter pack (its members). Example: `https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l`. Max 1 000 URLs.

## `postData` (type: `array`):

For each post URL: its reply thread, the posts that quote it, the accounts that liked it, the accounts that reposted it.

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

Levels of replies read under each post (1 = direct replies only). Parent posts above a reply are always included.

## `repliesPerPost` (type: `integer`):

Also read the replies under each post found by a search, an account's timeline, a feed or a list: up to this many per post, each reply is a result of its own (`source` = `post-replies`, `relatedTo` = the post), counted in **Max results** and charged like any result: a post that has replies keeps room for them in **Max results** (up to this number), and the room its replies do not use goes back to the next posts. Reposts and posts nobody answered open nothing. 0 (default) = off. The depth of the replies follows **Reply depth**.

## `feedPresets` (type: `array`):

Public Bluesky feeds to scrape (their current posts).

## `includeTrends` (type: `boolean`):

Save the current Bluesky trending topics (up to 25: title, category, post count, start time, top accounts).

## `maxPostsPerTrend` (type: `integer`):

With **Trending topics**: also save up to N posts of each topic (read from the topic's own feed). 0 = topics only.

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

Maximum number of results (posts, profiles, topics) saved for the whole run, after deduplication and filters. 0 = no limit.

## `maxItemsPerQuery` (type: `integer`):

Cap for EACH source (a search, an account's posts, an account's followers, a post's replies, a feed…), so the first source cannot use up **Max results**. 0 = no per-source cap.

## `includeAuthorProfiles` (type: `boolean`):

Add the author's followers, follows, posts count, bio (with the e-mail addresses written in it), website, banner and profile indexing date to each post, and the counts and website to each follower, follow, liker or list member (1 extra request per 25 new accounts). Charged per row it completes as **Author profile**, on top of the row (see the pricing). Off by default = the rows alone.

## `postedAfter` (type: `string`):

Only posts created on or after this date: `2026-09-01`, or a period before now such as `7 days`, `24 hours`, `2 weeks`. Reads the post's creation date. Profiles and topics are not filtered.

## `postedBefore` (type: `string`):

Only posts created on or before this date (the whole day is included), or older than a period such as `30 days`.

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

Two-letter language code (`en`, `fr`, `ja`…) as declared by the author. Posts without a declared language are dropped.

## `author` (type: `string`):

Search only the posts of this account (handle or DID).

## `mentions` (type: `string`):

Search only posts that mention this account (handle or DID).

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

Search only posts that link to this website (e.g. `nytimes.com`).

## `exactUrl` (type: `string`):

Search only posts that link to this exact page URL.

## `hashtags` (type: `array`):

Search only posts carrying these hashtags (written with or without #; several = all of them).

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

Keep posts that are replies to another post (search, feeds, account posts). Untick for top-level posts only.

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

Only posts with at least this many likes.

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

Only posts with at least this many reposts.

## `minReplies` (type: `integer`):

Only posts with at least this many replies.

## `minEngagement` (type: `integer`):

Only posts whose likes + reposts + replies + quotes reach this number.

## `minFollowers` (type: `integer`):

Only posts whose author has at least this many followers, and only profiles with at least this many followers (for posts, it reads the author counts by itself even when Author follower counts is off; those counts are not charged as **Author profile**).

## `mediaOnly` (type: `boolean`):

Only posts with images or a video.

## `withLinksOnly` (type: `boolean`):

Only posts that contain a link or a link card.

## `includeKeywords` (type: `array`):

Keep only the posts whose text, image descriptions or link card contains at least one of these words (case and accents ignored); the others are dropped. Like the other filters, each post checked is charged a small filter fee, kept or not (see Pricing). Empty (default): no such filter.

## `excludeKeywords` (type: `array`):

Drop the posts whose text, image descriptions or link card contains one of these words (case and accents ignored).

## `includeSentiment` (type: `boolean`):

Add an AI sentiment label to the text of each post and reply: positive, neutral or negative, with a score from 0 to 1, in two extra fields. Charged once per post or reply that gets a label (an extra event, see Pricing); a post without text costs nothing. Requires 2 GB of memory (Run options → Memory): with less, the option is skipped, the log says so and nothing is charged. Unticked (default): those fields stay empty.

## `aiLabels` (type: `array`):

Your own labels, judged on the text of each post and reply: a name such as `pricing`, or a name and a sentence that is true when the label applies, after a colon, such as `competitor: The author compares tools`. Up to 20. Each post and reply gets the labels that apply, with a score from 0 to 1, in `aiLabelMatches`. Charged per post and per label judged, whether it applies or not (an extra event, see Pricing); a post without text costs nothing. Requires 2 GB of memory (Run options → Memory): with less, the option is skipped, the log says so and nothing is charged. Empty (default): off.

## `includeKeywordStats` (type: `boolean`):

Add a summary of each searched keyword to the run's key-value store, in the `KEYWORD_STATS` record (never in the dataset): number of posts and replies, first and last date, posts per day, average and median likes, replies, reposts and quotes, median engagement rate, share of posts with media, share of verified authors, languages, top 10 hashtags, top 10 authors, top 5 posts by likes, and the share of positive, neutral and negative posts when **AI sentiment label** is on. Only the keywords of **Search keyword** / **More search keywords** (and search or hashtag URLs, or the network stream) count: a run with no keyword gives nothing and charges nothing. A post found by several keywords counts under the first one only. Charged once per keyword given (an extra event, see Pricing); a keyword needs at least 5 posts in the run and at most 50 keywords are given, the biggest first. With **Only new results**, only the posts delivered in this run are counted. Unticked (default): nothing is added.

## `includeWebsiteContacts` (type: `boolean`):

Open the website of each author (the website of its profile, the links of its bio, or its handle when that is a domain of its own; its home page and up to two of its contact, about or legal pages; one page for a link-in-bio page such as Linktree) and add the e-mail addresses, phone numbers and social links found there, in `authorWebsiteRead`, `authorWebsiteEmails`, `authorWebsitePhones` and `authorSocialLinks`. Needs **Author follower counts** (the links come from the profile): without it the option does nothing. Charged once per author for whom at least one e-mail address or phone number is found (an extra event, see Pricing); a website that cannot be opened or gives nothing costs nothing. Links to Instagram, Facebook, YouTube, TikTok, X, LinkedIn, WhatsApp and Telegram are never opened, they are listed as they are. Unticked (default): those fields stay empty.

## `onlyNew` (type: `boolean`):

Skip the posts and profiles that a previous run (same **Memory key**) already delivered: they are not saved and not charged. First run = everything is new.

## `stateKey` (type: `string`):

Name of the memory used by **Only new results**. Give each schedule / task its own key (e.g. `brand-watch`). Letters, digits, `-` and `_`.

## `resetState` (type: `boolean`):

Forget everything remembered under this **Memory key** before the run: this run returns (and charges) every result again. Untick it afterwards.

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

Keep the default Apify proxy: it is included in the price. The residential Apify proxy is not available in this Actor.

## `maxConcurrency` (type: `integer`):

Maximum number of requests processed in parallel.

## `maxRequestsPerMinute` (type: `integer`):

Global request rate. Bluesky allows a handful of parallel requests; lower it if the log shows HTTP 429.

## `maxRequestRetries` (type: `integer`):

Retries per request before it is marked as failed (search pages get extra retries, whatever this setting).

## `debugLog` (type: `boolean`):

Include debug messages in the run log.

## Actor input object example

```json
{
  "query": "climate",
  "searchQueries": [],
  "sort": "latest",
  "searchEngine": "auto",
  "streamHours": 6,
  "handles": [],
  "accountData": [
    "profile",
    "posts"
  ],
  "authorFeedFilter": "posts_with_replies",
  "includeReposts": true,
  "profileSearchQueries": [],
  "includeLatestPost": false,
  "includeAccountStats": false,
  "startUrls": [],
  "postData": [
    "replies",
    "quotes"
  ],
  "threadDepth": 10,
  "repliesPerPost": 0,
  "feedPresets": [],
  "includeTrends": false,
  "maxPostsPerTrend": 50,
  "maxItems": 100,
  "maxItemsPerQuery": 0,
  "includeAuthorProfiles": false,
  "hashtags": [],
  "includeReplies": true,
  "minLikes": 0,
  "minReposts": 0,
  "minReplies": 0,
  "minEngagement": 0,
  "minFollowers": 0,
  "mediaOnly": false,
  "withLinksOnly": false,
  "includeKeywords": [],
  "excludeKeywords": [],
  "includeSentiment": false,
  "includeKeywordStats": false,
  "includeWebsiteContacts": false,
  "onlyNew": false,
  "stateKey": "default",
  "resetState": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  },
  "maxConcurrency": 5,
  "maxRequestsPerMinute": 300,
  "maxRequestRetries": 5,
  "debugLog": false
}
```

# Actor output Schema

## `results` (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 = {
    "query": "climate",
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("nice_dev/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 = {
    "query": "climate",
    "proxyConfiguration": { "useApifyProxy": True },
}

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

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,nice_dev/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/L8BfRnWd4w9jQLeSI/builds/2ButqptjAK0iaMl4S/openapi.json
