Web and domains

Bluesky Monitor: Posts, Hashtags and Followers as JSON

Bluesky runs on the open AT Protocol, and its public API answers without a login. This Actor reads it in six modes (post search, profiles, author feeds, followers, following and account search) and writes every result as a flat record, so you can follow keywords, hashtags or accounts on a schedule.

Open the Actor on Apify Store

Bluesky Monitor & Scraper — Posts, Keywords, Followers. Pay per result; see the Store page for current pricing.

The source and its limits

The data comes from Bluesky's public, unauthenticated AT Protocol API: the public.api.bsky.app AppView, with its origin api.bsky.app as a fallback for post search. These are the same public endpoints the Bluesky app uses. No login, API key, proxies or browser.

ModeQueries areReturns
searchPostsKeywords, hashtags, phrases and search operatorsMatching posts
authorFeedHandles, DIDs or profile URLsThe accounts' posts
profilesHandles, DIDs or profile URLsProfiles with follower, following and post counts
followers, followingHandles, DIDs or profile URLsFollower or following lists
searchActorsSearch termsMatching accounts

Limits worth knowing

  • Post search returns at most 100 posts per query per run. From datacenter networks the public host refuses post search, and the origin host serves only the first page of results without a login. Use since, narrower queries, several queries, or the new-since-last-run mode on a schedule to keep up.
  • Requests are limited to about two per second. One request returns up to 100 posts or followers, so 10,000 followers take about a minute.
  • Follower records do not include per-follower counts; run profiles on the handles you care about.
  • Posts and profiles whose authors opted out of logged-out visibility may be missing, as they are on the public web.

Fields you get

FieldWhat it holds
type, querypost, profile, follower or following, and the query that found it
text, createdAt, langsPost content and time
likeCount, repostCount, replyCount, quoteCountEngagement counts
authorHandle, authorDisplayName, authorDidPost author
hasImages, hasVideo, embedUrls, externalUrlMedia and links
isReply, isRepost, quotedPostUrlThread context
postUrl, uriLink to the post on bsky.app and its AT URI
handle, displayName, description, followersCount, followsCount, postsCountOn profile records
subjectHandleOn follower records: the account you asked about

Example output

One post record from searchPosts (from the Actor's README; shortened):

{
  "type": "post",
  "query": "apify",
  "uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l",
  "authorHandle": "bsky.app",
  "authorDisplayName": "Bluesky",
  "text": "We shipped a new Apify integration today! Try the open API: https://docs.bsky.app",
  "createdAt": "2026-10-15T18:02:11.482Z",
  "likeCount": 310,
  "repostCount": 40,
  "replyCount": 12,
  "quoteCount": 5,
  "langs": [
    "en"
  ],
  "hasImages": true,
  "hasVideo": false,
  "isReply": false,
  "isRepost": false,
  "postUrl": "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l",
  "fetchedAt": "2026-10-16T12:40:32.064Z"
}

Use cases

Brand and keyword mentions

Run searchPosts with sort: "latest" and onlyNewSinceLastRun on a schedule, and send each run's new posts to a webhook.

Follower growth

Run followers with the new-since-last-run mode to get only new followers of an account on each run.

Account research

Run profiles on a list of handles for follower, following and post counts in one table.

How to run it

You need an Apify account and its API token (Console → Settings → API & Integrations). Each run is billed per result to your account; set a maximum total charge for the run to cap spend.

With curl

The sync endpoint starts a run, waits up to 300 seconds and returns the dataset items. New Bluesky posts mentioning a keyword since the last run, newest first:

export APIFY_TOKEN=<your Apify API token>

curl -sS -X POST \
  "https://api.apify.com/v2/acts/owlabee~bluesky-monitor/run-sync-get-dataset-items" \
  -H "Authorization: Bearer ${APIFY_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "searchPosts",
  "queries": [
    "apify"
  ],
  "maxResults": 50,
  "sort": "latest",
  "onlyNewSinceLastRun": true,
  "stateStoreName": "bluesky-keyword-brand-mention-monitor"
}'

From an AI agent (MCP)

Apify hosts an MCP server. This config exposes only this Actor to the agent:

{
  "mcpServers": {
    "owlabee-bluesky-monitor": {
      "url": "https://mcp.apify.com/?tools=owlabee/bluesky-monitor",
      "headers": {
        "Authorization": "Bearer ${APIFY_TOKEN}"
      }
    }
  }
}

Then ask, for example: Find the latest Bluesky posts with the hashtag #opensource and list the authors, text and like counts.

Python, Node.js and more examples

Runnable curl.sh, python.py, node.mjs and mcp.json files for this Actor are in examples/bluesky-monitor on GitHub.

FAQ

Does it need a Bluesky login or API key?

No. It uses Bluesky's public, unauthenticated API endpoints.

Can I search hashtags or exact phrases?

Yes. #opensource, "exact phrase" and operators such as from:handle, lang:en or domain:example.com are passed to Bluesky's search.

How does new-since-last-run work?

Per mode and query, the Actor stores the keys of records it already emitted (the most recent 10,000) and stops paging when it reaches known records. Profiles are re-emitted only when something changed, listed in changedFields.

Why do I get at most 100 posts for a search?

Post search from datacenter networks returns only the first page of results without a login. Split broad topics into several queries or narrow them with since.

What happens with a bad handle?

It produces an error item such as PROFILE_NOT_FOUND and the rest of the run continues.