Bluesky Scraper
Pricing
from $0.40 / 1,000 useful results
Bluesky Scraper
Extract public Bluesky profiles, posts, search results, feeds, followers, and following through official AT Protocol APIs.
Pricing
from $0.40 / 1,000 useful results
Rating
0.0
(0)
Developer
Aung Kyaw Khant
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
8 days ago
Last modified
Categories
Share
Extract public Bluesky profiles, posts, search results, feeds, followers, and following lists through the official AT Protocol APIs.
The Actor returns normalized JSON records in the default Apify dataset. It does not scrape the Bluesky website, run a browser, download media files, or access private content.
Billing
The configured public price is:
$0.0004 per saved useful result$0.40 per 1,000 saved useful results
A billing event is attempted only when one of these useful records is saved:
profilepostsearch_postfeed_postfollowerfollowing
These records are never billed:
feed_metadatarun_summaryerror
The Actor also does not bill for:
- AT Protocol requests or pagination requests
- retries
- filtered records
- duplicate records skipped during the run
- records rejected as malformed
- requested results that were not saved
Every dataset row includes:
{"data": {"isBillable": true,"billingCategory": "billable_useful_result"}}
Control rows use isBillable=false and billingCategory="non_billable_control_record".
To prevent accidental overcharging, an Apify cloud run refuses to start unless all of the following are true:
- the pricing model is Pay Per Event
- the
useful-resultevent price is exactly$0.0004 - the synthetic default dataset-item event is absent or exactly
$0
This prevents useful rows from being charged at an unintended rate, prevents double charging, and prevents summary or error rows from being charged.
Run scale and safety caps
runMode controls only result and page safety caps. It does not make a run free and it does not change the per-result price.
| Run mode | Maximum useful results | Maximum pages | Billing |
|---|---|---|---|
evaluation | 100 | 3 | Per saved useful result |
scale | 10,000 | 100 | Per saved useful result |
Requests above the selected cap are clamped and reported in run_summary.warnings.
limit is a maximum, not a guaranteed delivery count. Output can be lower when the upstream result set ends, filters remove records, maxPages is reached, a failure occurs, or the Apify run charge limit is reached.
Operation-aware input contract
The Actor never switches operations or infers intent from unrelated fields. A meaningful operation-specific field supplied with the wrong operation fails validation before Bluesky client creation, route dispatch, useful-result dataset writes, or billing. For example, {"operation":"posts","query":"Bitcoin"} fails clearly because query belongs to search; it does not fetch the default bsky.app posts and produces zero useful-result charge attempts.
Operation-specific fields are enforced as follows:
| Field | Accepted operation(s) |
|---|---|
handle | profile, posts, connections |
query, language, sort | search |
feedUrl, feedAlias | feed |
connectionType | connections |
includeReplies, includeReposts, includeQuotes | posts |
cursor | posts, search, feed, connections |
since, until | posts, search, feed |
The Apify form can automatically include harmless defaults such as handle="bsky.app", feedAlias="whats-hot", connectionType="followers", includeReplies=false, includeReposts=false, and includeQuotes=true. Those defaults are accepted when irrelevant. Changing an irrelevant field to a meaningful non-default value is rejected instead of ignored. When feedUrl is provided, leave feedAlias omitted or at its harmless default.
Supported operations
Profile
Fetch one public profile.
{"operation": "profile","handle": "bsky.app"}
A profile run always applies a useful-result limit of one.
User posts
Fetch posts from one author feed.
{"operation": "posts","handle": "bsky.app","limit": 100,"maxPages": 3,"runMode": "evaluation","includeReplies": false,"includeReposts": false,"includeQuotes": true}
Search posts
Search currently requires Bluesky authentication.
{"operation": "search","query": "atproto","sort": "latest","limit": 100,"language": "en","blueskyIdentifier": "your-handle.bsky.social","blueskyAppPassword": "your-dedicated-app-password"}
Use a dedicated Bluesky app password, not your account password. Both credential fields must be supplied together.
Search ordering is explicit:
sort="latest"is the default and requests the newest matching posts first.sort="top"requests Bluesky's relevance-ranked results. Bluesky controls that ranking, sotopmust not be described as simply the most-liked posts.
limit=10 means the Actor saves up to the first 10 qualifying posts in the selected upstream ordering. It does not mean the oldest 10 posts or every historical match.
Feed
Fetch the built-in What's Hot feed:
{"operation": "feed","feedAlias": "whats-hot","limit": 100}
Fetch a specific feed using an AT URI or Bluesky feed URL:
{"operation": "feed","feedUrl": "https://bsky.app/profile/example.bsky.social/feed/news","limit": 100}
A feed run can include one non-billable feed_metadata row in addition to billable feed_post rows and the non-billable run_summary.
Followers or following
{"operation": "connections","handle": "bsky.app","connectionType": "followers","limit": 100}
Set connectionType to following to fetch accounts followed by the target.
Filters
since and until apply to post-shaped records from posts, search, and feed.
Timestamps must include a date, time, and explicit timezone:
{"since": "2026-07-01T00:00:00Z","until": "2026-07-07T23:59:59Z"}
Accepted timestamps are normalized to UTC before use. Date-only and timezone-less values are rejected to avoid silent timezone assumptions. Upstream post timestamps are held to the same rule for filtering: malformed, timezone-less, or implausibly future timestamps are not used as sortAt; the Actor falls back to a valid indexedAt when available.
language is optional for search. Leave it blank when results should not be restricted by language.
sort applies only to search and accepts latest or top. The default is latest. The Apify form may include that default for other operations harmlessly, but sort="top" with a non-search operation is rejected before scraping or billing.
Output format
Every row uses a common envelope:
{"recordType": "post","operation": "posts","schemaVersion": "1.0","scrapedAt": "2026-07-11T00:00:00Z","sourceUrl": "https://bsky.app/profile/example.bsky.social/post/abc","input": {"operation": "posts","handle": "example.bsky.social","limit": 100,"runMode": "evaluation"},"data": {"uri": "at://did:plc:example/app.bsky.feed.post/abc","authorHandle": "example.bsky.social","text": "Example post","isBillable": true,"billingCategory": "billable_useful_result"}}
Input metadata is allowlist-based. Credential fields and unknown custom fields are not copied into dataset rows.
Run summary
The Actor attempts to store one non-billable run_summary row containing:
- requested and applied limits
- useful records saved
- pages fetched
- duplicates and filtered records skipped
- authentication mode
- run scale
- retry count
- billing attempts, confirmed charges, denials, and unconfigured events
- charge-limit status
- continuation cursor and resume safety status
- warnings and final status
billingEventsCharged is null when the platform does not provide a trustworthy confirmed charge count. A local run therefore does not pretend that zero is a verified platform charge.
Pagination and resume behavior
Paginated operations can return run_summary.data.nextCursor.
AT Protocol cursors are page-level rather than item-level. If a run stops after saving only part of a page, resuming from the preserved page-start cursor can repeat rows already saved in the previous run. Check:
resumeCursorStatusresumeCursorNotewarnings
When no safe continuation cursor exists, the summary says so instead of presenting an unsafe cursor as exact.
Authentication and privacy
Anonymous mode is used for supported public reads when credentials are omitted. Search requires authenticated Bluesky access.
Is it safe to provide Bluesky credentials?
It is reasonably safe when you follow the precautions below, but no credential handoff to a third-party Actor is risk-free. Use a dedicated, revocable Bluesky app password created specifically for this Actor. Never provide your main Bluesky account password.
Both blueskyIdentifier and blueskyAppPassword are declared as Apify secret inputs. Apify encrypts secret input fields before saving them to the run's default key-value store, including when a run is started through the API. Apify decrypts them only inside the Actor run so the Actor can authenticate with Bluesky.
The Actor's credential data flow is:
- Apify receives the two secret input fields and stores encrypted values.
- The running Actor receives the decrypted values in memory.
- The Actor sends them to Bluesky through the AT Protocol client to create an authenticated session.
- The Actor does not write the credentials to its dataset, run summary, error records, or status messages.
- The plaintext values are discarded when the Actor process ends. The encrypted run input remains subject to the user's Apify storage retention settings.
The important trust boundary is step 2: the Actor code necessarily receives plaintext credentials during the run. The current implementation uses them only for Bluesky authentication and has automated and live leakage checks, but users should still limit the impact of any unexpected platform, dependency, or account compromise by using a dedicated app password.
Credential safety checklist
- Create a dedicated app password in Bluesky under Settings → Privacy and security → App passwords. Do not reuse it for another application.
- Provide both credential fields through the generated Apify input form or as secret fields in the JSON request body. Never place credentials in URLs, query strings, task names, dataset fields, source code, or ordinary log messages.
- If an automation platform, proxy, shell command, or API client starts the run, make sure it also protects request bodies and command history. Apify can encrypt the stored Actor input, but it cannot prevent another system from logging the request before it reaches Apify.
- Restrict access to the Apify account and API token that can start or inspect runs.
- Revoke the dedicated Bluesky app password after one-time use, when it is no longer needed, or immediately if you suspect exposure. Revocation stops future logins; do not assume it cancels a session that is already running.
- Delete the Apify run/default key-value store sooner if your retention requirements demand it. Apify documents the retention behavior for key-value stores; until deletion or expiry, these two fields remain encrypted at rest.
What the Actor guarantees
- credential fields and unknown custom fields are excluded from dataset input metadata
- credential values are redacted from Actor-generated status and error output
- secret-bearing exception chains are suppressed before they reach the Actor boundary
- credentials are not stored in Actor source, result datasets, summaries, or control records
- search request parameters contain the query and filters, not credential fields; authentication is handled by the AT Protocol session
These guarantees cover this Actor's code and output. They do not cover a user's local machine, browser extensions, external automation tools, network proxies, compromised Apify or Bluesky accounts, or Bluesky's own authentication service.
Validation behavior
The Actor rejects malformed input instead of silently changing the request. Examples include:
- unknown field names
- explicit
nullor empty integer and boolean values - unsupported enum values
- non-object input
- incomplete credentials
- invalid timestamps
- malformed feed URLs or AT URIs
Useful records must contain stable identity fields before they can be saved and billed. Malformed upstream records fail closed rather than becoming blank billable rows.
Scope and limitations
The Actor extracts public data exposed by Bluesky's AT Protocol services. Search ordering is requested with sort="latest" or sort="top", but the exact ranking, result availability, feed contents, rate limits, and historical coverage are controlled by the upstream service and can change over time.
The Actor does not provide:
private or blocked content extractionbrowser or HTML scrapingfirehose streamingmedia downloadspersistent monitoring or change trackingmulti-account bulk jobsraw SDK response outputsentiment or content classification
Use the extracted data in accordance with applicable law, Bluesky's terms, Apify's terms, and the privacy rights of the people represented in the data.