# Bluesky Brand Monitoring & Social Listening Scraper (`angaba92/bluesky-brand-mention-monitor`) Actor

Brand monitoring and social listening for Bluesky: track brand mentions, competitors and keywords with sentiment analysis, question and complaint detection, priority flag and engagement score. For reputation monitoring and support triage. No login. CSV, JSON or API.

- **URL**: https://apify.com/angaba92/bluesky-brand-mention-monitor.md
- **Developed by:** [Andres Garcia-Baquero Leon](https://apify.com/angaba92) (community)
- **Categories:** Social media, Automation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Bluesky Brand Mention Scraper - Social Listening

Find out what people are saying about your brand on Bluesky, and know instantly which mentions actually need a reply.

This Actor does not just dump posts. Every mention comes back enriched with sentiment, question and complaint detection, a priority flag, and an engagement score, so a human (or an automation) can triage in seconds instead of reading everything.

A single test run with empty input `{}` returned 98 mentions, 13 of which were flagged high-priority.

### Generic scraper vs this Actor

| Generic Bluesky scraper gives you | This Actor gives you |
|---|---|
| A raw dump of posts | A triaged mention feed |
| No sentiment signal | `sentiment`: positive / negative / neutral (heuristic) |
| You read every post to find questions | `isQuestion` flag for people asking about you |
| Complaints buried in the noise | `isComplaint` flag for bugs, outages, billing, frustration |
| No sense of what matters | `priority: high` on questions and complaints |
| Raw like/repost counts, if any | `engagement` score: likes + reposts + replies + quotes |
| Hashtags and links left inside the text | `hashtags` and `links` extracted per post |
| The same post repeated across keywords | Deduplication across keywords |
| Pay for everything scraped | Pay only for mentions returned after your filters |

### Example output

```json
{
  "keyword": "apify",
  "text": "Is Apify down? Getting errors on every run",
  "sentiment": "negative",
  "isQuestion": true,
  "isComplaint": true,
  "priority": "high",
  "engagement": 14,
  "likeCount": 9, "repostCount": 2, "replyCount": 3, "quoteCount": 0,
  "hashtags": [], "links": [],
  "authorHandle": "user.bsky.social",
  "createdAt": "2026-07-23T10:00:00.000Z",
  "url": "https://bsky.app/profile/user.bsky.social/post/abc"
}
```

At a glance, in table form:

| keyword | text | sentiment | isQuestion | isComplaint | priority | engagement | authorHandle |
|---|---|---|---|---|---|---:|---|
| apify | Is Apify down? Getting errors on every run | negative | true | true | high | 14 | user.bsky.social |

### Output fields

| Field | Type | Description |
|---|---|---|
| `keyword` | string | The monitored keyword that matched this mention |
| `text` | string | Full text of the Bluesky post |
| `sentiment` | string | `positive`, `negative` or `neutral` (heuristic, keyword-based) |
| `isQuestion` | boolean | True when the post looks like a question about the keyword |
| `isComplaint` | boolean | True when the post looks like a complaint (bug, outage, billing, frustration) |
| `priority` | string | `high` for questions and complaints, otherwise normal |
| `engagement` | integer | Total engagement: likes + reposts + replies + quotes |
| `likeCount` | integer | Number of likes |
| `repostCount` | integer | Number of reposts |
| `replyCount` | integer | Number of replies |
| `quoteCount` | integer | Number of quote posts |
| `hashtags` | array | Hashtags extracted from the post text |
| `links` | array | Links extracted from the post text |
| `authorHandle` | string | Bluesky handle of the author |
| `createdAt` | string | ISO 8601 timestamp of the post |
| `url` | string | Direct link to the post on bsky.app |

### How to use it

1. Click **Try for free** and open the Actor.
2. Run it with empty input `{}` to see it work with zero configuration, or enter your own `keywords`.
3. Optionally filter: set `onlyQuestionsAndComplaints` or raise `minEngagement` to cut noise.
4. Export the results to CSV, JSON, Excel, or pull them through the Apify API or a webhook into your own stack.

### Input

```json
{
  "keywords": ["apify", "my-brand"],
  "sort": "latest",
  "minEngagement": 0,
  "onlyQuestionsAndComplaints": false,
  "maxResultsPerKeyword": 100
}
```

| Field | Type | Default | Description |
|---|---|---:|---|
| `keywords` | array | `["apify"]` | Brands / keywords to monitor (each searched separately) |
| `sort` | string | `latest` | `latest` or `top` |
| `minEngagement` | integer | `0` | Only return mentions with at least this total engagement |
| `onlyQuestionsAndComplaints` | boolean | `false` | Only return high-priority mentions (questions + complaints) |
| `maxResultsPerKeyword` | integer | `100` | Max mentions per keyword (1-1000) |

#### Example: only questions and complaints

```json
{
  "keywords": ["my-brand"],
  "sort": "latest",
  "onlyQuestionsAndComplaints": true,
  "maxResultsPerKeyword": 200
}
```

#### Example: high-engagement mentions only

```json
{
  "keywords": ["my-brand", "competitor-brand"],
  "sort": "top",
  "minEngagement": 10,
  "onlyQuestionsAndComplaints": false,
  "maxResultsPerKeyword": 100
}
```

### Use cases

- **Brand and reputation monitoring** - never miss a complaint or a mention that is taking off.
- **Customer support triage** - route `priority: high` mentions straight into your support queue.
- **Competitor tracking** - watch rival brand names and how sentiment around them moves.
- **Campaign measurement** - track keyword and hashtag engagement across a launch.
- **Lead generation** - catch people publicly asking "which tool does X?" while the question is still open.

### Integrations

Connect the output to Zapier, Make, n8n, Slack, Google Sheets, Airbyte, LangChain, the Apify REST API, or any webhook endpoint. A common setup: schedule the Actor hourly with `onlyQuestionsAndComplaints: true` and push each new high-priority mention into a Slack channel, so your team gets a steady, low-noise feed of only the posts worth replying to.

### Pricing

Pay Per Event:

- `$0.004` per enriched mention returned
- `$0.00005` per Actor start

You only pay for mentions actually returned after your filters are applied. Tightening `minEngagement` or turning on `onlyQuestionsAndComplaints` lowers both the noise and the bill.

### FAQ

**Do I need a Bluesky account?**
No. The Actor reads public Bluesky AT Protocol endpoints (`api.bsky.app`) and requires no login or credentials.

**Is this legal?**
It collects only publicly available posts, without logging in and without accessing private data. As always, use the results in line with your own local regulations and Bluesky's terms.

**How fresh is the data?**
Results come from live public Bluesky search at the moment the run starts. With `sort: latest` you get the most recent matching posts; schedule the Actor hourly for a near-real-time feed.

**Why is the sentiment sometimes wrong?**
Sentiment, question and complaint detection are heuristic and keyword-based, tuned for English. They are designed as a triage signal to help you find what to look at first, not as ground truth. Sarcasm, slang and non-English posts can be misclassified.

**Can I monitor competitors?**
Yes. Put competitor names or product terms into `keywords`; each keyword is searched separately and the results are deduplicated.

**Will it break?**
It uses stable public AT Protocol endpoints rather than fragile page scraping, which keeps it resilient. If Bluesky changes its API, the Actor is maintained and updated.

### Troubleshooting

| Problem | Fix |
|---|---|
| Empty dataset | Broaden your `keywords` and lower `minEngagement` to `0` |
| Too much noise | Set `onlyQuestionsAndComplaints` to `true` and/or raise `minEngagement` |
| Missing recent posts | Increase `maxResultsPerKeyword` and set `sort` to `latest` |
| Same post appears under two keywords | Mentions are deduplicated across keywords; if you still see near-duplicates, they are distinct posts with similar text |

### Notes

- Source: public Bluesky AT Protocol endpoints (`api.bsky.app`). No login required.
- Sentiment, question and complaint detection is heuristic (keyword-based), tuned for English; treat it as a triage signal, not ground truth.

# Actor input Schema

## `keywords` (type: `array`):

Brand names or keywords to monitor on Bluesky (each is searched separately). E.g. apify, my-brand.

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

Sort order for search results.

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

Only return mentions with at least this total engagement (likes + reposts + replies + quotes).

## `onlyQuestionsAndComplaints` (type: `boolean`):

Only return mentions detected as questions or complaints (highest-priority for support / reputation).

## `maxResultsPerKeyword` (type: `integer`):

Maximum mentions to return per keyword (1-1000).

## Actor input object example

```json
{
  "keywords": [
    "apify"
  ],
  "sort": "latest",
  "minEngagement": 0,
  "onlyQuestionsAndComplaints": false,
  "maxResultsPerKeyword": 100
}
```

# 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 = {
    "keywords": [
        "apify"
    ],
    "sort": "latest",
    "minEngagement": 0,
    "onlyQuestionsAndComplaints": false,
    "maxResultsPerKeyword": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("angaba92/bluesky-brand-mention-monitor").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 = {
    "keywords": ["apify"],
    "sort": "latest",
    "minEngagement": 0,
    "onlyQuestionsAndComplaints": False,
    "maxResultsPerKeyword": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("angaba92/bluesky-brand-mention-monitor").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 '{
  "keywords": [
    "apify"
  ],
  "sort": "latest",
  "minEngagement": 0,
  "onlyQuestionsAndComplaints": false,
  "maxResultsPerKeyword": 100
}' |
apify call angaba92/bluesky-brand-mention-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,angaba92/bluesky-brand-mention-monitor"
        }
    }
}

```

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/gfa73ROoiKkfB2hkw/builds/qnq2oNvq5GZ2dBlYp/openapi.json
