# Bluesky Scraper Enterprise Grade (`data_wiki/bluesky-scraper-enterprise-grade`) Actor

Collect public Bluesky posts, comments, profiles, followers, following and people who liked or reposted, by keyword, hashtag, handle or link. No Bluesky account or API key needed. Great for social listening, trend tracking, brand monitoring and finding influencers. Export to Excel or CSV.

- **URL**: https://apify.com/data_wiki/bluesky-scraper-enterprise-grade.md
- **Developed by:** [Data WiKi](https://apify.com/data_wiki) (community)
- **Features:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Enterprise Grade?

Bluesky Scraper Enterprise Grade is an Apify Actor that collects public Bluesky data: posts with their comments, profiles, followers, followed accounts and the people who liked, reposted or quoted a post. Add keywords, hashtags, handles or links, press Start and download the rows as JSON, CSV or Excel. No Bluesky account is needed.

- **Five collection modes:** run it as a Bluesky post scraper, or switch to profiles, followers, following or engagers.
- **One list for everything:** keywords, hashtags, handles, DIDs and Bluesky links can be mixed in a single run.
- **Live results:** every row is saved as soon as it is read, so the Output tab fills while the run is going.
- **Separate tables:** posts, comments, profiles, followers, following, engagers and failed inputs each get their own table.
- **No API key:** the Actor reads data that any visitor can see, so you do not need a Bluesky API key.

Click **Try for free**, add a target and press **Start**.

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

Every row has a `kind`: `post`, `quote`, `comment`, `profile`, `follower`, `following` or `engager`. Post and comment rows carry like, repost, reply and quote counts. Fields that Bluesky does not publish for an item stay `null`. The example values below are made up and only show the shape of the data.

| Field | Description | Example |
|---|---|---|
| `kind`, `query`, `id`, `uri`, `cid`, `url` | Row type, the target that produced it, post key or account DID, post address, content hash and public link | `post` |
| `authorHandle`, `authorDid`, `authorName`, `authorAvatar` | Who wrote the post | `example-user.bsky.social` |
| `authorFollowersCount`, `authorFollowsCount`, `authorPostsCount`, `authorVerified`, `authorCreatedAt`, `authorBio` | Reach and profile data of the post author | `1200` |
| `text`, `createdAt`, `indexedAt`, `languages` | Post text, dates and language codes | `Golden hour at the harbour` |
| `likeCount`, `repostCount`, `replyCount`, `quoteCount`, `bookmarkCount` | Counts for the post | `42` |
| `engagementTotal`, `engagementRate` | Likes, reposts, replies and quotes added up, and that total divided by the author's followers | `0.0425` |
| `hashtags`, `mentions`, `links`, `linkDomains` | Hashtags, mentioned accounts, full link URLs and their domains | `["photography"]` |
| `mediaType`, `images`, `video`, `externalLink`, `quotedPost`, `embeddedRecord` | Attached media, link card, quoted post and embedded feed, list or starter pack | `image` |
| `isReply`, `replyParentUri`, `replyRootUri`, `isRepost`, `repostedBy`, `repostedAt`, `isPinned`, `isQuote`, `replyRestriction`, `labels`, `selfLabels`, `threadgate` | Thread position, repost and pin flags, reply rules and moderation labels | `everyone` |
| `sourcePostId`, `sourcePostUri`, `sourcePostUrl`, `sourcePostAuthorHandle`, `commentDepth`, `commentParentUri` | Comment rows: the post a comment belongs to and its reply level (1 is a direct reply) | `1` |
| `avatar`, `banner`, `followersCount`, `followsCount`, `postsCount`, `followerFollowingRatio`, `createdAt`, `accountAgeDays` | People rows: account counts, ratio and age | `36` |
| `verified`, `trustedVerifier`, `verifiedBy`, `isLabeler`, `isBridged` | Verification and account type flags | `false` |
| `bioEmails`, `bioLinks`, `bioMentions`, `profileLinks`, `pronouns`, `website` | Contacts and links found in the bio or listed on the profile | `["hello@example.com"]` |
| `listsCount`, `feedsCount`, `starterPacksCount`, `dmsOpenTo`, `pinnedPostUrl`, `joinedViaStarterPack`, `liveStatus` | Lists, feeds and starter packs created, who may send messages, pinned post and live status | `none` |
| `lastPostAt`, `postsPerWeek`, `avgLikesPerPost`, `avgRepostsPerPost`, `avgRepliesPerPost`, `avgEngagementRate`, `topHashtags`, `topLinkDomains`, `activitySampleSize` | Profile activity numbers worked out from the account's latest original posts | `0.7` |
| `relation`, `relationTo`, `engagedPostUrl`, `engagedAt`, `quoteText`, `quoteUrl`, `bridgyOriginalUrl` | How a person relates to a target (follower, following, like, repost, quote, member, feed creator) and the post involved | `like` |

Compare `engagementRate` across posts to get a Bluesky engagement rate for each author. The Output tab also offers the views Overview, Posts and comments, Media and links, People and Profile details.

### 💡 Use cases for Bluesky data

- **Bluesky social listening:** run the keywords and hashtags of your market, read `text`, `hashtags` and `links`, and keep only the language you need with `language`.
- **Bluesky brand monitoring:** search your brand name with a short `date_range` such as `7d` and repeat the run on a schedule to see new posts. Set `mentionsAuthor` to an account for Bluesky mentions monitoring of that account only.
- **Bluesky influencer discovery:** collect profiles for a topic and sort them by `followersCount`, `postsPerWeek` and `avgEngagementRate`. This is how you find influencers on Bluesky who post often and get replies.
- **Bluesky audience research:** list the followers of an account and compare `followersCount`, `accountAgeDays` and `bioLinks`. For Bluesky community mapping, combine the followers, following and engagers tables of key accounts to see who connects them.
- **Bluesky competitor analysis:** compare `postsPerWeek`, `avgLikesPerPost` and `topHashtags` of the accounts in your niche. Add `engagementTotal` per post for Bluesky engagement analytics by author.
- **Bluesky trend tracking:** run a hashtag with `sortOrder` set to `top` on a schedule and compare `likeCount` between runs. The rows show Bluesky engagement over time. A saved run like this works as a Bluesky hashtag tracker.
- **Bluesky research data:** save posts and comments with dates, languages and counts in one table. Use the rows as a Bluesky posts dataset for your own analysis.

### 🛠️ How to scrape Bluesky posts, profiles and followers

1. Create an Apify account and open **Bluesky Scraper Enterprise Grade** in the Apify Store.
2. Add targets to **Targets to scrape**, one per line: a keyword or search phrase, a `#hashtag`, an `@handle` or DID, or a Bluesky link.
3. Choose **What to collect**: Posts, Profiles, Followers, Following or Engagers.
4. Set **Max rows per target**. The form default is 10, and 0 means everything available.
5. Add optional filters such as date range, language or minimum likes.
6. Click **Start** and watch the log; each saved row is counted as it arrives.
7. Open the **Output** tab and download the rows as JSON, CSV or Excel.

The Actor works as a Bluesky data extractor inside Apify Console, so there is nothing to install. For a first test keep **Max rows per target** small.

#### Posts and comments

To scrape Bluesky posts, choose **Posts** to collect the posts of a profile, a keyword search, a hashtag, a custom feed or a list, including starter packs. Use **Comments per post** to add replies: 0 means none, a number means up to that many replies per post, and -1 means every reply. Each comment is saved as its own row with its reply depth. A Bluesky comments scraper run needs only a post or profile link and a comment limit. Enter a hashtag for a Bluesky hashtag search, or a keyword for a text search.

#### Profiles

Choose **Profiles** to get account details for handles, search results or members of a list. As a Bluesky profile scraper it writes one row per account. Each row holds counts, verification, links and emails found in the bio, and activity numbers from the latest posts. These activity fields give you Bluesky account analytics for one account. For Bluesky contact emails from bios, read `bioEmails` and `bioLinks`. Bluesky profile stats such as `followersCount` and `postsCount` sit in the same row.

#### Followers and following

Choose **Followers** for the accounts that follow a profile and **Following** for the accounts a profile follows. Paste a handle or a profile link. A link ending in followers or follows switches the mode for that target. This Bluesky followers scraper mode returns one row per account. The result is a Bluesky followers list you can sort and filter. To export Bluesky followers for one account, run it with a high **Max rows per target**.

#### Engagers

Choose **Engagers** to see who liked, reposted or quoted a post. Paste a post link to see who liked a Bluesky post. The same mode lets you see who reposted on Bluesky. To export Bluesky likes as a list of accounts, run it on the post link. A profile, keyword or hashtag reads the engagers of every post it returns. Quote rows add `quoteText` and `quoteUrl`, and each row's `relation` tells you whether the person liked, reposted or quoted.

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

Bluesky Scraper Enterprise Grade uses pay per event pricing. Every saved row in the main dataset is one charged result, and a small fee is charged when the Actor starts. Rows in the failed inputs table are not charged.

- **Result** (`main_result`): charged once for every post, quote, comment, profile, follower, following or engager row that is saved. Comments are rows too, so they are charged.
- **Actor start** (`apify-actor-start`): $0.00005 per run. The Actor is set to 1024 MB of memory, which is one start event.

Apify platform usage (compute) is billed on top of the events above.

| Plan tier | Price per 1,000 results (`main_result`) |
|---|---|
| Free | $1.50 (1,000 x $0.0015) |
| Bronze | $1.35 (1,000 x $0.00135) |
| Silver | $1.20 (1,000 x $0.0012) |
| Gold and above | $1.00 (1,000 x $0.001) |

Example: one hashtag with `max_items` 25 and `max_comments_per_post` 2 gives up to 25 posts and 50 comments, so up to 75 rows. On the Free tier that is 75 x $0.0015 = $0.1125, and on Gold 75 x $0.001 = $0.075, plus the start fee of $0.00005 and platform usage.

You can set a maximum cost per run in Apify. When it is reached the run stops cleanly and keeps every row already saved. See the Pricing tab for current rates.

### ⬇️ Input

The only required field is **Targets to scrape** (`urls`). Open the Input tab for every option.

> 💡 Keep `max_items` low for a first test run.

This example collects the latest English posts for a hashtag from the last 7 days, with up to 2 comments per post:

```json
{
  "urls": ["#photography"],
  "scrape": "posts",
  "max_items": 25,
  "max_comments_per_post": 2,
  "date_range": "7d",
  "sortOrder": "latest",
  "language": "en"
}
```

- `urls`: keywords, hashtags, handles, DIDs or Bluesky links, one per line. Search operators such as `from:` work, and `sort:top` in a keyword sets the order for that keyword. A name such as npr.org is tried as a handle first and searched as a keyword if no such account exists. Duplicates are removed.
- `scrape`: `posts`, `profiles`, `followers`, `following` or `engagers`. The default is `posts`.
- `max_items`: rows to collect for each target. The form default is 10, and 0 means everything available.
- `max_comments_per_post`: posts mode only. The form default is 2, 0 means no comments and -1 means every reply.
- `date_range`: type it as text, for example `7d`, `24h`, `2w`, `3m` (months) or `1y` for the last period, one date such as `2026-01-01` for everything since then, or two dates joined by two dots such as `2026-01-01..2026-03-31`.
- `sortOrder`: `latest` or `top`, for keyword searches.
- `language`: a language code such as `en`, or `any`.
- `fromAuthor`, `mentionsAuthor`: keep posts written by, or mentioning, one handle or DID.
- `hashtags`, `domain`, `exactUrl`: keep posts with these hashtags, linking to a domain or sharing an exact link.
- `minLikes`, `minReposts`, `minReplies`: skip posts below these counts.
- `includeReplies`, `includeReposts`: turn off to skip reply posts or reposts. Both are on by default.
- `proxyConfiguration`: optional and off by default. If Bluesky refuses requests, the Actor switches to a proxy by itself. You can also set your own.

> ⚠️ A filter that rejects most rows can end the run early, because the Actor stops looking after about 50,000 rows examined for one target.

### ⬆️ Output

The scraped rows are shown as a Bluesky dataset in the **Storage** tab, and the Output tab groups them into tables: all rows, people, posts, comments, profiles, followers, following, engagers and failed inputs. The table view doesn't show **all the fields**. Use the download options to export Bluesky posts and the other rows as JSON, CSV, Excel, XML or HTML.

One post row for the input above (example values, not real data):

```json
{
  "kind": "post",
  "query": "#photography",
  "id": "3kexamplepost1",
  "url": "https://bsky.app/profile/did:plc:exampleexampleexample01/post/3kexamplepost1",
  "authorHandle": "example-user.bsky.social",
  "authorName": "Example User",
  "authorFollowersCount": 1200,
  "text": "Golden hour at the harbour #photography",
  "createdAt": "2026-11-03T17:30:00.000Z",
  "languages": ["en"],
  "likeCount": 42,
  "repostCount": 5,
  "replyCount": 3,
  "quoteCount": 1,
  "engagementTotal": 51,
  "engagementRate": 0.0425,
  "hashtags": ["photography"],
  "mediaType": "image",
  "isReply": false,
  "replyRestriction": "everyone"
}
```

A comment on that post is a separate row that points back to it:

```json
{
  "kind": "comment",
  "query": "#photography",
  "id": "3kexamplereply1",
  "authorHandle": "sample-fan.bsky.social",
  "text": "Great light!",
  "likeCount": 2,
  "isReply": true,
  "commentDepth": 1,
  "sourcePostId": "3kexamplepost1",
  "sourcePostUrl": "https://bsky.app/profile/did:plc:exampleexampleexample01/post/3kexamplepost1",
  "sourcePostAuthorHandle": "example-user.bsky.social"
}
```

#### Profiles output

With `"scrape": "profiles"` and `"urls": ["@example-user.bsky.social"]` each row is an account:

```json
{
  "kind": "profile",
  "query": "@example-user.bsky.social",
  "id": "did:plc:exampleexampleexample01",
  "url": "https://bsky.app/profile/example-user.bsky.social",
  "authorHandle": "example-user.bsky.social",
  "authorName": "Example User",
  "followersCount": 1200,
  "followsCount": 300,
  "postsCount": 450,
  "followerFollowingRatio": 4.0,
  "verified": false,
  "bioEmails": [],
  "bioLinks": ["example.com"],
  "postsPerWeek": 3.5,
  "avgLikesPerPost": 38.2,
  "activitySampleSize": 30
}
```

#### Failed inputs output

A target that could not be read gets a row in the failed inputs table with two columns, `input` and `error`. These rows are not charged.

### ⚠️ Limitations and error handling

- The Actor reads only public data that any visitor can see. Private accounts, direct messages and anything behind a login are not returned.
- The Profiles mode works as a Bluesky user scraper for public accounts only.
- It does not score sentiment and does not list Bluesky trending topics. For a topic, search a hashtag with `sortOrder` set to `top`.
- The number of rows depends on what Bluesky returns for a target, so a run can end with fewer rows than `max_items`. The log then says how many were found.
- A search made only of operators such as `from:` or `domain:`, with no plain word, cannot be date filtered. It returns one page of up to 100 rows, and dates are filtered afterwards. Add a word to go deeper.
- Activity numbers such as `postsPerWeek` come from the latest posts of an account, not its full history.
- In followers, following and engagers runs, the activity fields are filled only for accounts that have posts.
- Repeated targets in one run are skipped.
- If the connection to Bluesky fails 8 times in a row, the run stops and keeps every row already saved.

| Run ends with | Meaning | What to do |
|---|---|---|
| `Done: N rows saved` | The run finished; some targets may have problems | Check the failed inputs table |
| `Spend limit reached` | Your maximum cost per run was hit | Raise the limit to collect more rows |
| `Bluesky could not be reached` | The connection stopped | Check proxy settings, then run again |
| `No rows collected` | Nothing matched or every target failed | Check the targets and the failed inputs table |
| `Input problem` | The input could not be used, for example an empty `urls` list, an unknown `scrape` value or an unreadable `date_range` | Fix the field named in the message |

In the failed inputs table the `error` column shows a short code and message, for example `NotFound` for a deleted or missing post or `Unsupported` for a link the Actor cannot read.

### 🔌 Integrating Bluesky Scraper Enterprise Grade with other apps

As a Bluesky data scraper on the Apify platform, the Actor lets you start runs from code, schedule them and trigger webhooks when a run finishes. The API tab shows ready-made JavaScript, Python and CLI snippets, and the run URL is `https://api.apify.com/v2/actors/data_wiki~bluesky-scraper-enterprise-grade/runs`.

- **Schedules:** repeat Bluesky data collection daily or weekly with [Apify schedules](https://docs.apify.com/actors/running/schedules) and compare `likeCount` and `replyCount` between runs.
- **Apps:** send rows to Google Sheets, Make, Zapier, Slack or Airbyte through the [Apify integrations](https://docs.apify.com/integrations).
- **API reference:** the [Apify API documentation](https://docs.apify.com/api/v2) covers starting runs and reading datasets from code.
- **AI agents:** the hosted [Apify MCP server](https://docs.apify.com/mcp) lets an agent find the Actor, check its input and start it.

### 🔗 Other social media scrapers by data_wiki

None of the other Actors by data_wiki covers Bluesky. These four cover related platforms and a follow-up step.

| Actor | What it extracts | When to use it |
|---|---|---|
| [Threads posts and profiles scraper](https://apify.com/data_wiki/threads-scraper) | Public Threads posts, profiles, replies and keyword or hashtag search results | You follow the same topics on Threads as well as Bluesky |
| [Instagram post comments extractor](https://apify.com/data_wiki/instagram-comment-scraper) | Comments from public Instagram posts and reels | Your audience also comments on Instagram |
| [TikTok hashtag and keyword data](https://apify.com/data_wiki/tiktok-data-extractor) | TikTok videos from links, profiles, hashtags or keywords | Your hashtag research also covers short videos |
| [Website contact details extractor](https://apify.com/data_wiki/contact-details-scraper) | Emails, phone numbers and social links from a list of websites | You collected website links from Bluesky bios and want contact details |
| [Threads profile and post scraper](https://apify.com/data_wiki/meta-threads-profile-scraper) | Public Threads profile details with posts, replies, reposts or media | Your creators or competitors are also on Threads |
| [Threads posts and profiles search scraper](https://apify.com/data_wiki/threads-scraper-posts-profiles-search) | Public Threads posts, profiles, reposts and replies by keyword or hashtag | Your topic listening also covers Threads |

For the source of the data see [Bluesky](https://bsky.app).

### ⚖️ Is it legal to scrape Bluesky?

Bluesky Scraper Enterprise Grade only extracts data that people have made publicly available on Bluesky and does not extract private data. Results can still contain personal data such as handles, names and bio emails, so collect it only with a legitimate reason and consider GDPR and CCPA. Check Bluesky's terms and consult a lawyer if you are unsure. Read more about [the legality of web scraping](https://blog.apify.com/is-web-scraping-legal/) and [ethical web scraping](https://blog.apify.com/what-is-ethical-web-scraping-and-how-do-you-do-it/).

### ❓ FAQ

#### Do I need a Bluesky account or API key?

No. The Actor reads public data the way a logged-out visitor sees it, so it needs no account, login or Bluesky API key.

#### Is there an API for this Bluesky scraper?

Yes, the Apify API. Start the Actor with an API call and read the run's dataset, using the `apify-client` packages for Node.js or Python. It is not an official Bluesky API.

#### How much does a run cost?

You pay $0.00005 per run start plus a price per saved row: $1.50 per 1,000 on the Free tier down to $1.00 per 1,000 on Gold and above. Platform usage is billed on top.

#### How do I get comments on posts?

Set `max_comments_per_post` above 0, or to -1 for every reply, in posts mode. Comments are saved as their own `comment` rows and are charged like any other row.

#### How many posts can I collect?

Set `max_items` for each target. The form default is 10, and 0 collects everything available. The count is per target, not shared across targets.

#### How do I download all Bluesky posts of one account?

Paste the profile handle or link, choose Posts and set `max_items` to 0. Add a `date_range` if you only need a period. This is the simplest way to download all Bluesky posts of an account.

#### Can I use it as a Bluesky followers exporter?

Yes. Choose Followers, paste the profile, set `max_items` high and download the rows as CSV or Excel.

#### Can I scrape private accounts?

No. Only public data is read.

#### Do I need proxies?

No. The Actor starts without a proxy and switches to a proxy by itself if Bluesky refuses requests. You can also set your own in `proxyConfiguration`.

#### Can I use Bluesky Scraper Enterprise Grade through MCP?

Yes. Add the Actor to an AI agent through the Apify MCP server and let the agent call it with your targets.

### 💬 Your feedback

Found a bug or need another field? Open an issue on the Actor's Issues tab. Need a custom solution? Contact hello.datawiki@gmail.com.

# Actor input Schema

## `urls` (type: `array`):

One per line. Accepts a keyword or search phrase (operators like from:npr.org and sort:top work), a #hashtag, an @handle or DID, or any bsky.app link: profile, post, followers, follows, custom feed, list, starter pack or search. Duplicates are removed. Add as many as you like.

## `scrape` (type: `string`):

Posts: posts of a profile, search, hashtag, feed or list, plus replies if you ask for them. Profiles: account details with bio emails and links. Followers and following: the people connected to a profile. Engagers: who liked, reposted or quoted a post (or the posts of a profile or search).

## `max_items` (type: `integer`):

How many main rows (posts or people) to collect for EACH target. Every keyword, handle or link gets its own full amount. 0 = everything available.

## `max_comments_per_post` (type: `integer`):

Posts mode only: replies to collect for every post. 0 = no comments, a number = up to that many replies per post, -1 = every reply. Comments are saved as their own rows.

## `date_range` (type: `string`):

Only keep items from this period. Type it as text: 7d, 24h, 2w, 3m (months) or 1y for the last period, a single date like 2026-01-01 for everything since then, or two dates joined by two dots like 2026-01-01..2026-03-31. Empty = any time.

## `sortOrder` (type: `string`):

Keyword searches only: newest posts first or the most popular posts first.

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

Keeps only posts written in this language. Any language = no language filter.

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

Handle or DID. Keeps only posts written by this account.

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

Handle or DID. Keeps only posts that mention this account.

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

Keep posts that carry these hashtags, with or without the # sign.

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

Keep posts that link to this domain, for example nytimes.com.

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

Keep posts that share this exact link.

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

Skip posts with fewer likes than this.

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

Skip posts with fewer reposts than this.

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

Skip posts with fewer replies than this.

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

Turn off to skip posts that are replies to other posts.

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

Turn off to skip posts that appear because someone reposted them.

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

Optional. By default requests go out without a proxy. If Bluesky refuses them, the Actor switches to a datacenter proxy and then a residential proxy on its own and stays on it.

## Actor input object example

```json
{
  "urls": [
    "@bsky.app",
    "#photography"
  ],
  "scrape": "posts",
  "max_items": 10,
  "max_comments_per_post": 2,
  "sortOrder": "latest",
  "language": "any",
  "includeReplies": true,
  "includeReposts": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (type: `string`):

Every saved row, whatever its type.

## `people` (type: `string`):

Profiles, followers, followed accounts and engagers with their counts.

## `posts` (type: `string`):

One row per post.

## `comments` (type: `string`):

One row per reply.

## `profiles` (type: `string`):

One row per profile with bio contacts and posting activity.

## `followers` (type: `string`):

One row per follower.

## `following` (type: `string`):

One row per followed account.

## `engagers` (type: `string`):

People who liked, reposted or quoted.

## `failedInputs` (type: `string`):

Inputs that could not be scraped.

## `summary` (type: `string`):

Counts and timing of the run.

# 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 = {
    "urls": [
        "@bsky.app",
        "#photography"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("data_wiki/bluesky-scraper-enterprise-grade").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 = {
    "urls": [
        "@bsky.app",
        "#photography",
    ],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("data_wiki/bluesky-scraper-enterprise-grade").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 '{
  "urls": [
    "@bsky.app",
    "#photography"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call data_wiki/bluesky-scraper-enterprise-grade --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,data_wiki/bluesky-scraper-enterprise-grade"
        }
    }
}
```

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/EpANAQ3DseyT4cvsc/builds/8DaJxPLzdZFS5G1Rd/openapi.json
