# Bluesky Profile Details Scraper (`khadinakbar/bluesky-profile-details-scraper`) Actor

Fetch public Bluesky profile details from handles, DIDs, or bsky.app URLs for influencer research and identity resolution. Not for posts, follower lists, or private data. Returns DID, handle, bio, counts, verification, media, labels, and timestamps. $0.006/profile + $0.00005 start; usage extra.

- **URL**: https://apify.com/khadinakbar/bluesky-profile-details-scraper.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, Lead generation, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.00 / 1,000 bluesky profile scrapeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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 Profile Details Scraper

Fetch public Bluesky profile details from handles, AT Protocol DIDs, or `bsky.app` profile URLs. This Actor is built for influencer research, identity reconciliation, audience sizing, community analysis, and AI-agent enrichment workflows that need one stable, typed record per account.

Use it when you already know which Bluesky profiles you want to enrich. Do not use it for keyword search, posts, replies, follower/following lists, private data, or authenticated actions.

### What data can you extract?

| Field | What it means |
|---|---|
| `did` | Permanent AT Protocol decentralized identifier |
| `handle`, `displayName`, `description` | Current public identity and bio |
| `followersCount`, `followsCount`, `postsCount` | Public audience and activity counts at collection time |
| `verificationStatus`, `trustedVerifierStatus` | Bluesky verification signals |
| `verificationCount`, `isVerified`, `isTrustedVerifier` | Normalized verification fields |
| `listsCount`, `feedGeneratorsCount`, `starterPacksCount` | Associated public Bluesky resources |
| `avatarUrl`, `bannerUrl`, `pinnedPostUri` | Profile media and pinned post reference |
| `labels` | Public moderation label values |
| `createdAt`, `indexedAt`, `scrapedAt` | Account, indexing, and collection timestamps |
| `source` | `bluesky-public-api` or `scrapecreators` fallback |

Every row uses the same field set. Missing optional values are explicit `null` values, so JSON, CSV, spreadsheet, database, and MCP consumers receive a predictable schema.

### Pricing

This Actor uses **Pay per event + usage**:

| Event | Price |
|---|---:|
| Actor start | $0.00005 per run (memory-scaled, one-event minimum) |
| Validated profile saved | $0.006 per profile |
| Apify platform usage | Additional compute usage reported separately by Apify |

Examples: 10 profiles cost up to **$0.06005** in event charges; 100 profiles cost up to **$0.60005**, plus platform usage. Missing, malformed, duplicate, or rejected profile values are not charged as profile records. The run status shows the maximum event charge before the first billable row is written.

### Input

```json
{
  "profiles": [
    "bsky.app",
    "@apify.com",
    "did:plc:z72i7hdynmk6r22z27h6tvur",
    "https://bsky.app/profile/npr.org"
  ],
  "maxConcurrency": 8,
  "deduplicate": true,
  "ignoreInvalidProfiles": true
}
````

`profiles` accepts 1–500 handles, DIDs, or direct profile URLs. Post URLs and non-Bluesky URLs are rejected. `deduplicate` removes repeated normalized handles or DIDs. `ignoreInvalidProfiles` lets a mixed batch preserve valid results while recording skipped values in `RUN_SUMMARY`.

### Output

```json
{
  "requestedProfile": "bsky.app",
  "did": "did:plc:z72i7hdynmk6r22z27h6tvur",
  "handle": "bsky.app",
  "displayName": "Bluesky",
  "description": "see what's next",
  "profileUrl": "https://bsky.app/profile/bsky.app",
  "avatarUrl": "https://cdn.bsky.app/img/avatar/plain/did:plc:...@jpeg",
  "bannerUrl": "https://cdn.bsky.app/img/banner/plain/did:plc:...@jpeg",
  "followersCount": 34110804,
  "followsCount": 11,
  "postsCount": 802,
  "listsCount": 16,
  "feedGeneratorsCount": 7,
  "starterPacksCount": 13,
  "isLabeler": false,
  "verificationStatus": "none",
  "trustedVerifierStatus": "valid",
  "verificationCount": 0,
  "isVerified": false,
  "isTrustedVerifier": true,
  "labels": [],
  "pinnedPostUri": "at://did:plc:.../app.bsky.feed.post/3abc",
  "createdAt": "2023-04-12T04:53:57.057Z",
  "indexedAt": "2025-10-27T21:05:26.152Z",
  "source": "bluesky-public-api",
  "scrapedAt": "2026-07-15T12:00:00.000Z"
}
```

The dataset contains profile rows only. `OUTPUT` provides the stable terminal outcome and billing totals; `RUN_SUMMARY` includes input normalization, provider attempts, fallback reasons, validation counts, warnings, errors, storage IDs, and charge-cap state. Control and error records never pollute the dataset.

### Reliability and data sources

The primary route is Bluesky's cached public AppView endpoint at `public.api.bsky.app`, which Bluesky recommends for public-web use cases. The Actor retries transient timeouts, rate limits, and server errors with bounded backoff. If those attempts fail and the owner-managed ScrapeCreators secret is available, it uses the probed Bluesky profile endpoint as a field-compatible fallback.

Profile-not-found responses are treated as valid empty inputs rather than fabricated rows. A batch with some useful profiles and some failures ends `PARTIAL` while preserving the valid data. When all required routes fail and no useful data exists, the run ends honestly as `UPSTREAM_FAILED` with actionable diagnostics.

Counts and profile fields can change after collection. Use `scrapedAt` for freshness and `did` rather than `handle` when you need a persistent identity key.

### API example

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('khadinakbar/bluesky-profile-details-scraper').call({
    profiles: ['bsky.app', 'apify.com'],
    maxConcurrency: 8,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Use with AI agents through MCP

Connect the public Actor through the [Apify MCP Server](https://apify.com/apify/actors-mcp-server). The tool accepts a small list of explicit profiles and returns flat, typed records suitable for enrichment, comparison, and identity resolution. Paginate larger datasets with the dataset ID returned by the Actor run.

Example agent requests:

- “Get the DIDs, bios, follower counts, and verification status for these Bluesky handles.”
- “Resolve these `bsky.app` profile URLs into stable account records.”
- “Compare the audience sizes and account ages of these public Bluesky profiles.”

### Limitations and responsible use

- Public profile data only; no login, cookies, app password, DMs, or private records.
- No post content, keyword search, follower/following lists, or hidden contact data.
- Bluesky and fallback-provider response fields can evolve; schema drift is reported rather than hidden.
- Profiles that are deleted, invalid, unavailable, or not visible to the public API produce no dataset row.
- Use public data in accordance with applicable laws, privacy rules, and Bluesky's terms. This Actor is not affiliated with or endorsed by Bluesky PBC.

### Support

For a reproducible issue, include the Actor run ID and a non-sensitive example handle. Do not post API tokens, cookies, or private data in an issue.

# Actor input Schema

## `profiles` (type: `array`):

Use this when you need public details for specific Bluesky accounts. Accepts handles, DIDs, or full profile URLs, such as 'bsky.app', 'did:plc:z72i7hdynmk6r22z27h6tvur', or 'https://bsky.app/profile/apify.com'. Provide 1 to 500 values. This is not a post URL, keyword-search, or follower-list field.

## `maxConcurrency` (type: `integer`):

Use this to control how many Bluesky profile lookups run at once. Accepts an integer from 1 to 20, for example 8. Defaults to 8 for fast runs without aggressive request bursts. This does not change the number of profile records or their per-record price.

## `deduplicate` (type: `boolean`):

Use this to return only one row when the same normalized handle or DID appears more than once. Duplicate matching happens after URL and @handle normalization. Defaults to true. This does not merge two different handles that resolve to the same DID.

## `ignoreInvalidProfiles` (type: `boolean`):

Use this to keep processing valid values when a batch also contains malformed handles or non-profile URLs. Defaults to true and reports skipped values in RUN\_SUMMARY. Set false to stop the whole run as INVALID\_INPUT when any value is malformed. This does not turn missing or deleted accounts into profile rows.

## Actor input object example

```json
{
  "profiles": [
    "bsky.app",
    "https://bsky.app/profile/apify.com"
  ],
  "maxConcurrency": 8,
  "deduplicate": true,
  "ignoreInvalidProfiles": true
}
```

# Actor output Schema

## `profiles` (type: `string`):

Dataset containing normalized public Bluesky profile records with identity, bio, audience counts, verification, media, labels, and timestamps.

## `output` (type: `string`):

Compact run outcome, persisted profile count, warnings, and charged profile events.

## `runSummary` (type: `string`):

Detailed profile processing, fallback, validation, source-route, cost-cap, and billing diagnostics.

# 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 = {
    "profiles": [
        "bsky.app",
        "apify.com"
    ],
    "maxConcurrency": 8,
    "deduplicate": true,
    "ignoreInvalidProfiles": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/bluesky-profile-details-scraper").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 = {
    "profiles": [
        "bsky.app",
        "apify.com",
    ],
    "maxConcurrency": 8,
    "deduplicate": True,
    "ignoreInvalidProfiles": True,
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/bluesky-profile-details-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "profiles": [
    "bsky.app",
    "apify.com"
  ],
  "maxConcurrency": 8,
  "deduplicate": true,
  "ignoreInvalidProfiles": true
}' |
apify call khadinakbar/bluesky-profile-details-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=khadinakbar/bluesky-profile-details-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Bluesky Profile Details Scraper",
        "description": "Fetch public Bluesky profile details from handles, DIDs, or bsky.app URLs for influencer research and identity resolution. Not for posts, follower lists, or private data. Returns DID, handle, bio, counts, verification, media, labels, and timestamps. $0.006/profile + $0.00005 start; usage extra.",
        "version": "1.0",
        "x-build-id": "oxSsBBnuXB99GUDOa"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/khadinakbar~bluesky-profile-details-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-khadinakbar-bluesky-profile-details-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/khadinakbar~bluesky-profile-details-scraper/runs": {
            "post": {
                "operationId": "runs-sync-khadinakbar-bluesky-profile-details-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/khadinakbar~bluesky-profile-details-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-khadinakbar-bluesky-profile-details-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "profiles"
                ],
                "properties": {
                    "profiles": {
                        "title": "Bluesky profiles",
                        "minItems": 1,
                        "maxItems": 500,
                        "type": "array",
                        "description": "Use this when you need public details for specific Bluesky accounts. Accepts handles, DIDs, or full profile URLs, such as 'bsky.app', 'did:plc:z72i7hdynmk6r22z27h6tvur', or 'https://bsky.app/profile/apify.com'. Provide 1 to 500 values. This is not a post URL, keyword-search, or follower-list field.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxConcurrency": {
                        "title": "Maximum concurrent lookups",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Use this to control how many Bluesky profile lookups run at once. Accepts an integer from 1 to 20, for example 8. Defaults to 8 for fast runs without aggressive request bursts. This does not change the number of profile records or their per-record price.",
                        "default": 8
                    },
                    "deduplicate": {
                        "title": "Remove duplicate profiles",
                        "type": "boolean",
                        "description": "Use this to return only one row when the same normalized handle or DID appears more than once. Duplicate matching happens after URL and @handle normalization. Defaults to true. This does not merge two different handles that resolve to the same DID.",
                        "default": true
                    },
                    "ignoreInvalidProfiles": {
                        "title": "Continue past invalid profiles",
                        "type": "boolean",
                        "description": "Use this to keep processing valid values when a batch also contains malformed handles or non-profile URLs. Defaults to true and reports skipped values in RUN_SUMMARY. Set false to stop the whole run as INVALID_INPUT when any value is malformed. This does not turn missing or deleted accounts into profile rows.",
                        "default": true
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
