Bluesky Scraper: Posts, Profiles, Followers & Mentions avatar

Bluesky Scraper: Posts, Profiles, Followers & Mentions

Pricing

from $0.80 / 1,000 posts

Go to Apify Store
Bluesky Scraper: Posts, Profiles, Followers & Mentions

Bluesky Scraper: Posts, Profiles, Followers & Mentions

Search Bluesky (bsky) posts by keyword, hashtag or account, e.g. product launches or #photography. Get likes, reposts, replies, profiles, author follower counts and new-mention alerts. $0.001 per post: 1,000 posts cost $1; $0.002 per profile. No login.

Pricing

from $0.80 / 1,000 posts

Rating

0.0

(0)

Developer

fortbrand

fortbrand

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

7 days ago

Last modified

Categories

Security

Limited permissions

Share

For brand monitoring teams, researchers, community managers and developers who need public Bluesky posts with author context. Search topics such as product launches, open source software or #photography, follow known accounts, load specific posts and inspect public profiles without a Bluesky login.

About $0.001 per post and $0.002 per requested profile. Twenty posts cost about $0.02; 1,000 delivered posts cost about $1. Author follower counts are included in the post price. A small platform start charge of $0.00005 also applies. Bronze receives 5% off, Silver 10% off and Gold 20% off the row prices. There is no separate charge for the summary, duplicate records, empty results or restricted accounts.

Anonymous search has a source limit: one page of up to 100 candidate posts per query. Replies, language filters and visibility exclusions can reduce the number delivered. Author feeds and public custom feeds support normal pagination. This tool does not promise a complete search archive or the entire social graph.

What you get

RecordIncluded informationUseful for
PostText, original timestamp, stable AT URI, CID, author handle and public follower countTopic monitoring and warehouse joins
EngagementSeparate likes, reposts, replies and quotesComparing current response to content
Rich textStructured links, hashtags and mentioned account DIDsFinding shared domains and linked discussions
MediaImage URLs and alt text, video playlist when supplied, external card metadataContent analysis and editorial review
ConversationReply parent, root URI, quoted-post URI and optional reply sampleReading public discussion context
ProfileDescription, follower/following/post counts, account creation time, avatar and bannerReviewing a known public account
WatchSuppression of records already delivered for a stable watch IDRepeated collection with fewer duplicate charges
SummaryDelivered totals, authors, top hashtags, engagement, exclusions and coverage notesChecking whether the run covered the requested job

Missing source values stay null. No email, telephone, private messaging or identity enrichment service is used.

Start in three steps

  1. Enter one or more searchTerms, or supply handles for an author feed. Optional startUrls accept public post, profile, search or custom-feed links.
  2. Set maxItems, the maximum total number of paid rows across the whole run. Start with 20 and leave reply expansion off for a first look.
  3. Start the Actor and open its dataset. Export JSON, CSV or Excel, and read the free SUMMARY record for exclusions and source limits.

The tested default returned 20 posts in 5.3 seconds on 29 October 2026. Reply expansion, many sources, watch history and source response times affect duration.

{
"searchTerms": ["bluesky"],
"sort": "latest",
"maxItems": 20,
"includeReplies": false
}

Choose the right source

searchTerms discover posts using Bluesky search syntax. Use keywords, hashtags, quoted phrases, from:bsky.app and inline since: / until: dates. Date bounds intersect with date inputs. For dated account searches, include a keyword or use handles. Queries that the public API rejects produce free source notes. Inputs are deduplicated; matchedTerms lists queries that actually returned a record in the inspected pages.

handles collect an account's own posts. The Actor excludes records present solely because the account reposted somebody else. Set includeReplies to include its reply posts as well. Follower enrichment is included, but this input does not create an additional paid profile row.

A profile URL in startUrls returns one profile row only. A post URL returns that post, with optional reply expansion. A custom-feed URL reads the public feed in its supplied order. A search URL uses the query from its q parameter. Plain URL strings and objects containing url are both accepted. AT URIs for posts and feed generators are accepted too.

{
"handles": ["bsky.app", "nature.com"],
"maxItems": 50,
"includeReplies": false
}
{
"startUrls": [
"https://bsky.app/profile/bsky.app",
{"url": "https://bsky.app/profile/nature.com"}
],
"maxItems": 2
}

Input reference

InputDefaultMeaning
searchTermsbluesky in the prefillArray of keywords or native search queries
handlesEmptyArray of account handles or DIDs whose own posts to collect
startUrlsEmptyOptional public post, profile, search or feed links
sortlatestlatest or top, for search results only
sinceUnsetInclusive date or timestamp boundary for posts
untilUnsetExclusive date or timestamp boundary for posts
languageUnsetLanguage code such as en, de or pt-BR
maxItems20Global paid-row cap, from 1 to 10,000
includeRepliesfalseAllow reply posts and expand selected roots
maxRepliesPerPost5Maximum replies inspected per root, from 0 to 100
onlyNewSinceLastRunfalseEnable delivery history for this watch
watchIddefaultStable monitoring name using letters, digits, underscores or hyphens
proxyConfigurationNo proxyOptional supported Apify or custom proxy configuration

Dates without a time mean midnight UTC. For all of 28 October, use since: "2026-10-28" and until: "2026-10-29". Post timestamps are checked locally as well as using available search filters. The source search index can use a sorting timestamp different from the original post timestamp, so a filtered search is not an archival completeness guarantee. Date and language filters apply to posts, not profile rows.

Post fields

Selected fields from a real 29 October 2026 run:

{
"verdict": "2,979 likes, 325 reposts, 193 replies; 35,430,011 author followers.",
"type": "post",
"uri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3myx7vphq3s2j",
"text": "getting our Halloween decorations set up",
"createdAt": "2026-10-28T16:58:02.827Z",
"authorHandle": "bsky.app",
"authorFollowers": 35430011,
"likes": 2979,
"reposts": 325,
"replies": 193,
"quotes": 110,
"isNewSinceLastRun": null,
"url": "https://bsky.app/profile/did:plc:z72i7hdynmk6r22z27h6tvur/post/3myx7vphq3s2j"
}
FieldDescription
typepost
uri, cid, urlStable record identity, content identifier and public link
text, createdAt, indexedAt, observedAtSource text, original time, indexing time and collection time
authorDid, authorHandle, authorDisplayNamePublic author identity supplied by the source
authorFollowers, authorFollowing, authorPostsPublic author counts from profile enrichment
authorCreatedAt, authorAvatar, authorEnrichedExtra author context and enrichment status
likes, reposts, replies, quotesSeparate source counts at collection time
engagementSum of the four counts when all four are available
languageSource language-code array
links, hashtags, mentionsStructured rich-text facets; mentions contain DIDs
images, video, externalAvailable image metadata, video view and external card
isReply, replyTo, replyRootConversation relationships
quoteUri, quoteUrlReferenced quoted record, without copying its content
matchedTerms, sourceInputsObserved query matches and collection provenance
sourcePostUriRoot selected for optional reply expansion, otherwise null
isNewSinceLastRuntrue for newly delivered watch rows; null when watches are off
labelsPublic source labels attached to the post

Profile rows contain type, did, handle, displayName, description, followers, following, posts, createdAt and url, plus available avatar, banner, labels, verification and observation time. A profile lookup is not proof of a person's identity or control of another website.

The dataset includes free note and SUMMARY rows. Filter by type before importing. ## Monitor mentions every day

Save a task with a narrow query, enable onlyNewSinceLastRun and keep the same watchId on each scheduled run. The first run delivers qualifying records and establishes the history. Later runs suppress records that this watch has already delivered. A post found through two inputs is still delivered and charged only once within the run.

{
"searchTerms": ["from:bsky.app"],
"sort": "latest",
"maxItems": 20,
"onlyNewSinceLastRun": true,
"watchId": "official-updates"
}

Run a watch sequentially. Do not overlap scheduled runs using the same watch ID. An unfinished run blocks reuse of that watch so its pending delivery is not silently repeated. Resume the original run or use a different ID for an independent history. History records delivery, rather than every post that existed between schedules. If a query produces more than a public search page between runs, some posts may be missed. Run narrower queries frequently enough for the topic, or monitor known author feeds. Engagement changes on an old post do not make it a new record; switch watches off to take repeated engagement snapshots.

Pricing examples

Delivered recordsStandard row price
20 posts$0.02
100 posts$0.10
1,000 posts across eligible sources$1.00
20 requested profiles$0.04
100 posts and 10 profiles$0.12

Add the small start charge, then apply the relevant row discount. Replies cost the same as posts. maxItems includes replies and requested profiles, so reply expansion does not exceed that global row cap. Your maximum total charge is also respected: the Actor stops cleanly when the remaining budget cannot cover another eligible row. A record is saved before its corresponding row charge is made. Empty results, failures and note rows have no post or profile charge.

Use with AI agents (MCP)

Connect your agent to https://mcp.apify.com. Ask it to inspect the input schema and pricing, then request: “Collect 20 public Bluesky posts about open source software with author follower counts, separate repost and quote counts, links and hashtags.” ## API and integrations

Use an Apify token from your environment; no Bluesky token is needed.

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('vant47/bluesky-posts-profiles-scraper').call({
searchTerms: ['open source'], maxItems: 20, sort: 'latest'
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
const posts = items.filter(row => row.type === 'post');

The REST endpoint is POST https://api.apify.com/v2/acts/vant47~bluesky-posts-profiles-scraper/runs, using an Authorization bearer header and a JSON input body. Poll the returned run ID, then fetch defaultDatasetId. The SUMMARY record is also available in the default key-value store.

Schedules, Make, Zapier and n8n can trigger tasks and consume webhooks. Upsert by type plus uri or did; preserve observedAt for snapshot comparisons.

Limits and FAQ

Does it collect follower lists? No. “Followers” refers to public follower counts in posts and profiles. This Actor does not enumerate follower or following identities.

Does it require login or solve access challenges? No. It uses standard signed-out AppView requests. It does not log in, solve challenges or bypass denied search pagination. Accounts and posts carrying !no-unauthenticated are excluded, including during author enrichment.

Can it collect every reply? No. Reply expansion is a bounded sample of the thread returned by the source, with a maximum depth of six and your per-root cap. Deleted, blocked, restricted and unavailable replies are omitted. The global row limit can stop expansion sooner.

Why did I receive fewer rows? Search boundaries, filters, delivery history, source availability and budget can reduce output. Read the summary before increasing the limit.

Are counts live? They are source snapshots taken during the run. AppView caching and indexing can lag the website, and counters can change between collection and inspection. The website can display combined repost-and-quote totals, while this output keeps them separate.

Does a reboot duplicate data or charges? Saved dataset rows act as the delivery ledger. On restart the Actor reconciles platform charge counts and acknowledged receipts before continuing. Duplicate inputs are free; an ambiguous billing state stops further delivery instead of guessing.

What happens if a source is unavailable? Permitted transient retries are paced, rate-limit advice is honoured, and unavailable data produces free notes. Partial results stay available. Check status, notes, sources and exclusions in the summary before treating a run as complete.