Bluesky Scraper — Posts, Profiles & Search
Pricing
$1.00 / 1,000 results
Bluesky Scraper — Posts, Profiles & Search
Scrape Bluesky without a login: posts, profiles, threads, hashtags and full-text search over the decentralized AT Protocol. Built for social listening and research. Multiple relays with deduplication, incremental mode returns only new posts. Empty runs cost nothing.
Pricing
$1.00 / 1,000 results
Rating
0.0
(0)
Developer
Radosław Szal
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
11 hours ago
Last modified
Categories
Share
Bluesky Scraper — Posts, Profiles, Hashtags & Search (AT Protocol)
🔗 Part of the Apify actors collection — actors that chain: scrape → clean → use.
Scrape Bluesky without a login: posts, profiles, threads, hashtags, follower graphs and full-text search, exported as clean JSON, CSV or Excel. Built directly on the public AT Protocol — the decentralized protocol Bluesky itself runs on — so there is no browser, no proxy and no fragile HTML parsing to break when the site changes.
Built for social listening, brand monitoring and research. $0.001 per record — $1.00 per 1 000, and an empty run costs nothing.
What you get back, and how fast
Every record is flat and typed — engagement counts, hashtags, mentions, links and media pulled
up to top-level fields, with a real clickable https://bsky.app/... URL. Post records carry
uri, url, cid, text, createdAt, indexedAt, langs, author{did,handle,displayName,avatar}, likeCount, repostCount, replyCount, quoteCount, hashtags, mentions, links, media[{url,alt,type}], quotedPost, isReply, isRepost, labelsdid, handle, url, displayName, description, avatar, banner, followersCount, followsCount, postsCount, createdAt, labelsA typical run finishes in about 6 seconds (25 records, measured), against Apify's 5-minute limit for automated checks. There is no browser and no proxy in the path — this reads the AT Protocol directly — which is why it is both fast and cheap to run.
Full samples are in Output below.
What can this Bluesky scraper do?
Seven jobs in one Actor. Pick a mode:
| Mode | What it does | Login? |
|---|---|---|
author_posts | Every post from one or more accounts, with reply and media filters | No |
search_posts | Full-text keyword search across Bluesky — date, language, author and hashtag filters | App password |
profiles | Full profile details for given accounts | No |
search_profiles | Find accounts by keyword | No |
post_thread | The complete reply tree under a post | No |
followers | An account's followers | No |
follows | Who an account follows | No |
Only keyword post search needs an app password — Bluesky does not serve that one endpoint anonymously. Everything else runs on the public AppView out of the box.
Why use this one rather than another Bluesky scraper?
- Image alt-text.
media[].altcarries the author's own description of each image. Most scrapers drop it; it is the single most useful field for AI, search and accessibility work. - The quoted post, in full. When a post quotes another, you get the quoted text, author and URL — not just an opaque reference.
handleResolved. You can tell a verified handle from an unresolved one (handle.invalid), and you get a working profile URL either way.- A flat, stable schema — engagement counts, hashtags, mentions, links and media pulled up to
top-level fields, and a real clickable
https://bsky.app/...URL on every post. Not a raw API dump. - Incremental monitoring built in. Set
onlyNewand a scheduled run returns only what it has not seen before — so a daily brand-alert costs you the new posts, not the same ones again. - It fails loudly. A run that fetches data and delivers nothing does not report success. See What happens when something fails?
How do I use it?
Get an account's latest posts (no login):
{ "mode": "author_posts", "handles": ["nytimes.com", "bsky.app"], "maxItems": 100 }
Search posts by keyword (needs an app password):
{"mode": "search_posts","searchQuery": "electric vehicles","lang": "en","since": "2026-07-01","sort": "latest","maxItems": 500,"blueskyIdentifier": "you.bsky.social","blueskyAppPassword": "<your-app-password>"}
Monitor mentions of your brand — schedule it hourly and pay only for new posts:
{"mode": "search_posts","searchQuery": "\"YourBrand\"","onlyNew": true,"stateLabel": "yourbrand-mentions","blueskyIdentifier": "you.bsky.social","blueskyAppPassword": "<your-app-password>"}
Get the full thread under a post (no login):
{ "mode": "post_thread", "postUrls": ["https://bsky.app/profile/bsky.app/post/3l..."], "threadDepth": 6 }
How do I scrape a Bluesky hashtag?
Two ways, depending on what you want:
{ "mode": "search_posts", "hashtags": ["climate"], "since": "2026-07-01","blueskyIdentifier": "you.bsky.social", "blueskyAppPassword": "<your-app-password>" }
That searches all of Bluesky for the tag. If instead you want a specific account's tagged posts,
use author_posts and filter on the hashtags field in the output — every post record carries
its hashtags as a top-level array.
How do I narrow what I get back — and pay less?
Billing is per delivered record, so every filter below is also a discount.
| Input | What it does |
|---|---|
maxItems | Hard stop on records delivered. The cheapest way to try the Actor. |
authorFeedFilter | Which slice of an author's feed: posts_and_author_threads keeps their posts and own threads, posts_no_replies drops replies to other people, posts_with_media keeps only posts with images or video. |
since / until | ISO date bounds. Use both to pull a fixed window — one calendar month — rather than "everything newer than X". |
fromAuthor | In search_posts, restricts the search to one author. "What did this account say about Y" in a single run instead of two. |
lang | Restricts search to one language. |
onlyNew + stateLabel | Returns only records not seen in previous runs under the same key. Turns any scrape into a monitor. |
How do I get a Bluesky app password?
- Open Bluesky → Settings → Privacy and Security → App Passwords.
- Add App Password, name it (e.g. "Apify"), copy the value (format
xxxx-xxxx-xxxx-xxxx). - Paste your handle into Bluesky handle and the value into Bluesky app password.
An app password is revocable and scoped — it is not your main password. It is sent only to
Bluesky's own createSession endpoint to sign in, and is never written to the dataset or the logs.
⬆️ Output — what you get back
📝 Posts (author_posts, search_posts, post_thread)
{"uri": "at://did:plc:.../app.bsky.feed.post/3l...","url": "https://bsky.app/profile/handle/post/3l...","cid": "bafy...","text": "the post text","createdAt": "2026-07-20T10:00:00.000Z","indexedAt": "2026-07-20T10:00:01.000Z","langs": ["en"],"author": {"did": "did:plc:...", "handle": "handle", "handleResolved": true,"displayName": "Name", "avatar": "https://..."},"likeCount": 6512, "repostCount": 539, "replyCount": 88, "quoteCount": 12, "bookmarkCount": 4,"hashtags": ["climate"], "mentions": ["did:plc:..."], "links": ["https://..."],"embedType": "images","media": [{ "url": "https://...", "alt": "a solar farm at sunset", "type": "image" }],"quotedPost": {"uri": "at://...", "url": "https://bsky.app/profile/.../post/...","author": "quoted.handle", "text": "the quoted post"},"external": null,"isReply": false, "isRepost": false, "replyParent": null, "replyRoot": null,"labels": []}
👤 Profiles (profiles, search_profiles, followers, follows)
{"did": "did:plc:...", "handle": "handle", "handleResolved": true,"url": "https://bsky.app/profile/handle","displayName": "Name", "description": "bio text","avatar": "https://...", "banner": "https://...","followersCount": 12043, "followsCount": 311, "postsCount": 2894,"createdAt": "2023-05-01T09:12:00.000Z", "indexedAt": "2026-07-20T10:00:01.000Z","labels": []}
Download from the run's Dataset tab as JSON, CSV or Excel, or pull it through the Apify API.
What happens when something fails?
Failures are never written into your dataset as records, and you are never charged for one.
| Situation | What the Actor does |
|---|---|
| Bad or missing input for the chosen mode | Fails immediately with a message naming the problem. |
| App password rejected | Fails with Authentication failed, and still bills only what was already delivered — a mid-run auth failure never re-delivers or double-charges next run. |
| One target account errors, others work | Continues, delivers what worked, and counts the failure. |
| Data fetched but zero records delivered | The run fails with the reason — every record dropped in normalisation, every target errored, or pagination hit a safety backstop. A broken run never reports success. |
onlyNew finds nothing new | Succeeds with zero records. That is a legitimate quiet poll, not a failure, and it costs nothing. |
| Pagination stops at a safety backstop | Reported as truncated — a partial result is never passed off as a complete one. |
| Billing calls keep failing | Delivery stops rather than giving data away unpaid, and the run says how many records it delivered first. |
The two rows that matter most are the fourth and the fifth. Distinguishing "nothing broke, there is simply nothing new" from "everything broke and you got nothing" is the difference between a monitor you can trust on a schedule and one you have to check by hand.
How much does it cost?
- $0.001 per record delivered (
result-item), flat — $1.00 per 1 000. - An empty run costs nothing. No record written, no charge.
- Nothing is charged for compute time, pagination, retries or bandwidth. A slow run costs the same as a fast one.
- To try it cheaply, set
maxItemsto 10. That is three cents.
What can I do with the data?
- Social listening and brand monitoring on the fastest-growing X alternative — schedule
search_postswithonlyNewand get only what is new since the last check. - Research datasets for AI and academia: public data, open protocol, alt-text included.
- Topic and hashtag tracking as Bluesky adoption grows.
- Community and lead research — find accounts around a topic, then profile them.
- Clean it first: pipe the dataset straight into Dataset Deduplicator & Cleaner to merge duplicates across runs before analysis.
FAQ
Can I use it with the Apify API?
Yes. POST /v2/acts/eszetael_lab~bluesky-scraper/runs with your input as the JSON body, then read
the run's dataset. Standard API, CLI and client libraries all work.
Can I use it through an MCP server?
Yes. It is exposed through Apify's Actors MCP server like any public Actor, so an AI agent can call it as a tool. It is also enabled for agentic payments — an agent can run and pay for it without a human in the loop.
Can I schedule it to run automatically?
Yes — use Apify Schedules, and set onlyNew: true with a stateLabel. Each run then returns only
posts it has not seen before, so a daily monitor costs you the new posts rather than the whole feed
again.
Do I need a proxy?
No. The AT Protocol AppView serves public data directly. There is no anti-bot layer to defeat, which is also why this Actor is cheap to run and does not break when a page layout changes.
Does it scrape private posts or DMs?
No. It reads only public data through the official public AppView. No private posts, no logged-in-only content, no fake accounts.
Is it legal, and what about GDPR?
Reading public posts from an open protocol is broadly lawful, but profile and follower data is personal data under GDPR. You need your own lawful basis for processing it, and you are responsible for how you store and use what you export. This Actor gives you the data; it does not give you the basis.
Your feedback
Found a bug, or a case where a mode returns something odd? Open an issue on the Actor's Issues tab. Real failure reports are worth more to us than feature requests.
Related actors
Three tools built to chain into each other — scrape, then clean, then use.
- Dataset Deduplicator & Cleaner — pass this Actor's dataset ID straight in to merge duplicates across runs before analysis. Six times cheaper than a scraper, because it processes data you already paid to collect.
- Python Web Scraper — when your target is an ordinary website rather than Bluesky, write your own Python page function and get exactly the fields you want, with no template to fight.
All three are on pay-per-result pricing, and an empty run costs nothing in every one of them.
Built on the AT Protocol (app.bsky.*). Keywords: bluesky scraper, bluesky api, at protocol
scraper, scrape bluesky posts, bluesky profile scraper, bluesky hashtag, bluesky search, social
listening, decentralized social, social media scraper, bluesky data export.