# Bluesky Post Search (Posts Only, Official API) (`inn_corp/bluesky-post-search`) Actor

Search Bluesky posts by keyword or hashtag, or fetch posts by URL, via Bluesky's official public API. Posts only by design: no follower harvesting, no profile scraping. Deleted posts are never returned.

- **URL**: https://apify.com/inn\_corp/bluesky-post-search.md
- **Developed by:** [Inn Corp](https://apify.com/inn_corp) (community)
- **Categories:** Social media, Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 post retrieveds

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/actors/running/actors-in-store.md#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 Post Search (Posts Only, Official API)

Search Bluesky posts by keyword or hashtag, or fetch specific posts by URL,
through Bluesky's official public API. **Posts only, by design**: this Actor
never harvests follower graphs, never enumerates profiles, and returns no
author data beyond what each post itself carries. If you need a compliant
source of Bluesky post data for monitoring, research, or AI pipelines, that
constraint is the point.

### What it does

- Give it search queries (`open source`, `#photography`), each searched
  separately with Bluesky's own search.
- Or give it direct post URLs (`https://bsky.app/profile/handle/post/id`,
  `at://` URIs also accepted) to fetch specific posts.
- Filter by date window (`YYYY-MM-DD`), language, and sort (`latest` or `top`).
- Get back one clean record per unique post: text, author handle and display
  name, timestamps, like/repost/reply/quote/bookmark counts, language tags,
  embed type, and working web URLs.
- A post matching several of your queries appears once, with `queriedBy`
  listing every query that matched it, and is charged once.

### What it deliberately does not do

- **No follower or following lists.** Ever. There is no input that produces
  them, and none will be added.
- **No profile scraping.** No bios, no follower counts, no account
  enumeration. Author fields are limited to the handle and display name that
  Bluesky attaches to each post result.
- **No guessing.** Every field comes from Bluesky's API response. Missing
  data is `null`, never invented.

### Deletion and privacy

This Actor reads Bluesky's live public API at run time and returns only
post-level data. Datasets reflect the moment of fetch: if an author deletes
a post, rerunning the same input will no longer return it, and post URLs
pointing at deleted posts come back empty rather than resurrected from a
cache. If you persist datasets, honor deletion on your side too: refresh
before you republish, and drop records the API no longer returns.

Posts on Bluesky are public by the platform's design, and Bluesky documents
these AppView endpoints as intentionally public and usable without
authentication. Use the results responsibly: respect people's context,
comply with applicable data-protection law (posts can contain personal
data), and do not use this Actor to build profiles of individuals. That last
use case is exactly what it refuses to support by construction.

### Output example

A real record from a test run (`queries: ["apify"]`):

```json
{
  "uri": "at://did:plc:svkeafnra23hxnsg7vaogq64/app.bsky.feed.post/3mtm364ds7v22",
  "url": "https://bsky.app/profile/dubaipropertyleadf.bsky.social/post/3mtm364ds7v22",
  "authorHandle": "dubaipropertyleadf.bsky.social",
  "authorDisplayName": "Dubai Property Lead Finder",
  "text": "## Dubai Property Lead Finder\n\nFind Dubai property leads faster with the Dubai Property Lead Finder**. It helps real estate professionals discover property listings, agent contacts, phone numbers, agencies, and useful property details\n**Explore Dubai Property Lead Finder:** apify.com/skyline_scra...",
  "createdAt": "2026-08-21T15:28:00.803Z",
  "likeCount": 3,
  "repostCount": 0,
  "replyCount": 0,
  "quoteCount": 0,
  "bookmarkCount": 0,
  "langs": ["en"],
  "embedType": "external",
  "indexedAt": "2026-08-21T15:28:04.768Z",
  "queriedBy": ["apify"],
  "fetchedAt": "2026-08-24T20:26:18+00:00"
}
```

`embedType` is one of `image`, `video`, `external`, `record` (quote post),
`recordWithMedia`, or `null` for plain text posts. `langs` is the language
tag list the author's client attached, when present.

### Typical uses

- Monitor mentions of a brand, product, or topic on a schedule.
- Collect hashtag activity for research or reporting.
- Feed an AI agent real, current posts so its answers cite live sources.
- Re-fetch a known list of posts to get current engagement counts.

### Input

| Field | Meaning |
| --- | --- |
| `queries` | Keywords or hashtags, one per line. Each is searched separately. |
| `postUrls` | Specific posts as `bsky.app` URLs or `at://` URIs. Optional. |
| `sort` | `latest` (default) or `top`. |
| `sinceDate` / `untilDate` | Posted-date window, `YYYY-MM-DD`, inclusive. |
| `lang` | Two-letter language code, for example `en`. |
| `maxPostsPerQuery` | Upper bound per query, default 100, max 1000. |
| `proxyConfiguration` | Defaults to Apify Proxy. Bluesky refuses anonymous search from datacenter IPs, so keep it on for cloud runs. |

At least one query or one post URL is required. A malformed post URL is
logged and skipped without killing the run.

### Honest limits

- Bluesky search matches whole words and is not a firehose; a query with no
  matches returns zero records and says so in the log.
- The date window is enforced client-side: Bluesky's own `since`/`until`
  filter works on server timestamps while `createdAt` is author-supplied, so
  posts with heavily future-dated or back-dated `createdAt` values are
  excluded from your results when a window is set.
- Bluesky restricts deep result pagination for anonymous clients in some
  environments. The Actor detects this and automatically falls back to
  date-window pagination for `latest`-sorted queries; `top`-sorted queries
  may then be capped at 100 posts, and the log tells you when that happens.
- Engagement counts are a snapshot at fetch time; they change as people
  interact with the post.

### Fair pricing

Pay per post record returned and per query processed, once pay-per-event
pricing is enabled. Duplicates across queries are charged once. A search
that ran successfully but matched nothing still counts as a processed query,
because the search itself is the work; failed queries are not charged. No
subscription.

# Actor input Schema

## `queries` (type: `array`):

Keywords or hashtags to search for, one per line. Each query is searched separately; a post matching several queries is returned (and charged) once.

## `postUrls` (type: `array`):

Specific posts to fetch, as bsky.app URLs (https://bsky.app/profile/handle/post/id) or at:// URIs. Optional; combine freely with queries.

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

"latest" returns newest posts first; "top" returns Bluesky's most relevant posts.

## `sinceDate` (type: `string`):

YYYY-MM-DD. Leave empty for no lower bound.

## `untilDate` (type: `string`):

YYYY-MM-DD, inclusive. Leave empty for no upper bound.

## `lang` (type: `string`):

Two-letter language code, for example "en" or "pt". Leave empty for all languages.

## `maxPostsPerQuery` (type: `integer`):

Upper bound of posts returned per search query. Duplicates across queries are removed and charged once.

## `proxyConfiguration` (type: `object`):

Bluesky refuses anonymous search requests from datacenter IP ranges, so cloud runs use Apify Proxy by default. Leave as is unless you know you need something else.

## Actor input object example

```json
{
  "queries": [
    "open source",
    "#photography"
  ],
  "postUrls": [
    "https://bsky.app/profile/bsky.app/post/3l6oveex3ii2l"
  ],
  "sort": "latest",
  "sinceDate": "2026-08-01",
  "untilDate": "2026-08-31",
  "lang": "en",
  "maxPostsPerQuery": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `posts` (type: `string`):

No description

# 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 = {
    "queries": [
        "apify"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("inn_corp/bluesky-post-search").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 = {
    "queries": ["apify"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("inn_corp/bluesky-post-search").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 '{
  "queries": [
    "apify"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call inn_corp/bluesky-post-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,inn_corp/bluesky-post-search"
        }
    }
}

```

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/lmKQ8Pm14purCS66K/builds/AiIGHi4GudxWR790F/openapi.json
