Nimbryxo Studio

Bluesky Posts, Profiles, Feeds & Threads Scraper

Search Bluesky posts by keyword, hashtag, author, mention, domain or URL; read profiles, threads, lists, starter packs, feeds and followers; export likes, reposts, follows, quotes and relationships.

Input schema

Input fields, types, required flags, descriptions, defaults, and prefills come from the published definition. Prefill examples are distinct from defaults.

FieldTypeRequiredDescription
modestringrequiredWhat to fetch.
searchQuerystringoptionalKeyword, hashtag, phrase, or Lucene-style query. Used by search, actorSearch, starterPackSearch, and feedGeneratorsDiscovery.
searchSortstringoptionalSearch ranking. `latest` returns newest first; `top` returns engagement-ranked posts. Both use time-window pagination to collect beyond one page.
Show all input fields
FieldTypeRequiredDescription
modestringrequiredWhat to fetch.
searchQuerystringoptionalKeyword, hashtag, phrase, or Lucene-style query. Used by search, actorSearch, starterPackSearch, and feedGeneratorsDiscovery.
searchSortstringoptionalSearch ranking. `latest` returns newest first; `top` returns engagement-ranked posts. Both use time-window pagination to collect beyond one page.
searchTagsarrayoptionalOnly posts with these hashtags (without `#`). Multiple tags are AND-matched. (mode=search)
searchDomainstringoptionalOnly posts linking to this domain, e.g. `github.com`. (mode=search)
searchUrlstringoptionalOnly posts linking to this exact URL. (mode=search)
mentionsUserstringoptionalOnly posts mentioning this handle or DID. (mode=search)
fromUserstringoptionalOnly posts authored by this handle or DID. (mode=search)
sincestringoptionalEarliest post date as `YYYY-MM-DD` or an ISO datetime. (mode=search)
untilstringoptionalLatest post date as `YYYY-MM-DD` or an ISO datetime. (mode=search)
languagestringoptionalISO 639-1 language filter for post search and post records. Empty means no filter.
authorFeedFilterstringoptionalWhich posts to include in the author feed. (mode=profile)
includePinsbooleanoptionalInclude the pinned post at the top of the author feed. (mode=profile)
includeParentsbooleanoptionalInclude ancestor posts above the requested post. (mode=postThread)
threadDepthintegeroptionalHow many reply levels and ancestor levels to walk. Depths beyond about 10 reply levels are reached by walking reply branches across requests. 0 returns only the requested post. (mode=postThread)
maxRepliesPerPostintegeroptionalMaximum direct replies followed under each post while walking a thread. Larger values reach more branches but cost more requests. (mode=postThread)
actorstringoptionalBluesky handle or DID. Used by profile, follows, followers, lists, actorLikes, actorFeeds, relationships, and discoveryType=suggestedFollows.
actorsarrayoptionalHandles, DIDs, or profile URLs for batch lookup. Used by profiles and by relationships as the accounts to check against `actor`.
postUristringoptionalAT URI of a post. Used by postThread, getLikes, repostedBy, and quotes.
postUrisarrayoptionalAT URIs of posts to hydrate. Used by getPosts and as a fallback for single-post modes.
postUrlsarrayoptionalbsky.app post, profile, list, feed, or starter-pack URLs. Used by urlFetch, getPosts, and as a fallback for single-post modes.
listUristringoptionalAT URI of a Bluesky list. Used by getList and listFeed.
listUrisarrayoptionalAT URIs or bsky.app list URLs for batch list processing. (mode=getList)
starterPackUristringoptionalAT URI of a starter pack. (mode=getStarterPack)
starterPackUrisarrayoptionalAT URIs or bsky.app starter-pack URLs for batch processing. (mode=getStarterPack)
feedPresetstringoptionalBuilt-in feed preset. Live presets are listed first, followed by legacy aliases mapped to What's Hot. An explicit `feedUri` always takes precedence; if neither is set, What's Hot is used for mode=feed.
feedUristringoptionalAT URI or bsky.app feed URL of a custom feed generator. (mode=feed / feedGenerator)
feedUrisarrayoptionalAT URIs or bsky.app feed URLs for batch feed-generator lookup. (mode=feedGenerator)
discoveryTypestringoptionalWhich discovery surface to fetch. (mode=discovery)
excludeRepliesbooleanoptionalDrop posts that are replies to another post.
excludeRepostsbooleanoptionalDrop posts surfaced as reposts.
mediaOnlybooleanoptionalOnly emit posts with at least one image, video, or external embed.
excludeLabeledbooleanoptionalDrop posts and accounts that carry moderation or self-labels, including labels on a post's author.
respectNoUnauthenticatedbooleanoptionalSkip records whose author carries the `!no-unauthenticated` label. The run status reports how many records were skipped.
verifiedOnlybooleanoptionalOnly emit accounts with a valid Bluesky verification, or posts whose author is verified. Records with no verification object are excluded. Post modes hydrate author profiles so verification can be checked.
minLikesintegeroptionalDrop posts with fewer likes.
minRepostsintegeroptionalDrop posts with fewer reposts.
minRepliesintegeroptionalDrop posts with fewer replies.
minQuotesintegeroptionalDrop posts with fewer quote posts.
minFollowersintegeroptionalKeep accounts with at least this many followers.
maxFollowersintegeroptionalKeep accounts with at most this many followers.
includeListMetadatabooleanoptionalEmit a list record before its members. (mode=getList)
includeStarterPackMembersbooleanoptionalEmit the accounts in the starter pack's list after the pack record. (mode=getStarterPack)
hydrateAuthorsbooleanoptionalFetch full author profiles for post records. Adds one batched profile request per 25 unique authors and flat author follower, following, post and verification fields. Enabled by default; the daily profile prefill leaves it off to stay cheap.
maxItemsintegeroptionalHard cap on emitted records. For batch modes the cap applies across the whole run.

Download the published input schema

View complete JSON
{
  "description": "Search Bluesky posts with keyword, hashtag, author, mention, domain and URL filters; read profiles, author feeds, full reply branches, custom feeds, lists, starter packs, likes, reposts, quotes, actor liked posts and public relationships; and discover trending topics, feeds and starter packs. All data is public and needs no login, cookies or API key.",
  "properties": {
    "actor": {
      "description": "Bluesky handle or DID. Used by profile, follows, followers, lists, actorLikes, actorFeeds, relationships, and discoveryType=suggestedFollows.",
      "editor": "textfield",
      "prefill": "bsky.app",
      "title": "Handle or DID",
      "type": "string"
    },
    "actors": {
      "default": [],
      "description": "Handles, DIDs, or profile URLs for batch lookup. Used by profiles and by relationships as the accounts to check against `actor`.",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [],
      "title": "Handles or DIDs",
      "type": "array"
    },
    "authorFeedFilter": {
      "default": "posts_with_replies",
      "description": "Which posts to include in the author feed. (mode=profile)",
      "editor": "select",
      "enum": [
        "posts_with_replies",
        "posts_no_replies",
        "posts_with_media",
        "posts_and_author_threads"
      ],
      "enumTitles": [
        "Posts with replies",
        "Original posts only",
        "Posts with media",
        "Posts and author threads"
      ],
      "prefill": "posts_with_replies",
      "title": "Author feed filter",
      "type": "string"
    },
    "discoveryType": {
      "default": "trendingTopics",
      "description": "Which discovery surface to fetch. (mode=discovery)",
      "editor": "select",
      "enum": [
        "trendingTopics",
        "suggestedFeeds",
        "suggestedStarterPacks",
        "taggedSuggestions",
        "suggestedFollows"
      ],
      "enumTitles": [
        "Trending topics",
        "Suggested feeds",
        "Suggested starter packs",
        "Tagged suggestions",
        "Suggested follows"
      ],
      "prefill": "trendingTopics",
      "title": "Discovery type",
      "type": "string"
    },
    "excludeLabeled": {
      "default": false,
      "description": "Drop posts and accounts that carry moderation or self-labels, including labels on a post's author.",
      "prefill": false,
      "title": "Exclude labeled",
      "type": "boolean"
    },
    "excludeReplies": {
      "default": false,
      "description": "Drop posts that are replies to another post.",
      "prefill": false,
      "title": "Exclude replies",
      "type": "boolean"
    },
    "excludeReposts": {
      "default": false,
      "description": "Drop posts surfaced as reposts.",
      "prefill": false,
      "title": "Exclude reposts",
      "type": "boolean"
    },
    "feedPreset": {
      "description": "Built-in feed preset. Live presets are listed first, followed by legacy aliases mapped to What's Hot. An explicit `feedUri` always takes precedence; if neither is set, What's Hot is used for mode=feed.",
      "editor": "select",
      "enum": [
        "whats-hot",
        "bsky-team",
        "hot-classic",
        "discover",
        "mutuals",
        "popular-with-friends",
        "for-you",
        "news",
        "trending-videos",
        "quiet-posters"
      ],
      "enumTitles": [
        "What's Hot",
        "Bluesky Team",
        "Hot Classic",
        "Legacy: Discover (uses What's Hot)",
        "Legacy: Mutuals (uses What's Hot)",
        "Legacy: Popular With Friends (uses What's Hot)",
        "Legacy: For You (uses What's Hot)",
        "Legacy: News (uses What's Hot)",
        "Legacy: Trending Videos (uses What's Hot)",
        "Legacy: Quiet Posters (uses What's Hot)"
      ],
      "prefill": "whats-hot",
      "title": "Feed preset",
      "type": "string"
    },
    "feedUri": {
      "description": "AT URI or bsky.app feed URL of a custom feed generator. (mode=feed / feedGenerator)",
      "editor": "textfield",
      "title": "Feed AT URI",
      "type": "string"
    },
    "feedUris": {
      "default": [],
      "description": "AT URIs or bsky.app feed URLs for batch feed-generator lookup. (mode=feedGenerator)",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [],
      "title": "Feed AT URIs",
      "type": "array"
    },
    "fromUser": {
      "description": "Only posts authored by this handle or DID. (mode=search)",
      "editor": "textfield",
      "title": "From user",
      "type": "string"
    },
    "hydrateAuthors": {
      "default": true,
      "description": "Fetch full author profiles for post records. Adds one batched profile request per 25 unique authors and flat author follower, following, post and verification fields. Enabled by default; the daily profile prefill leaves it off to stay cheap.",
      "prefill": false,
      "title": "Hydrate post authors",
      "type": "boolean"
    },
    "includeListMetadata": {
      "default": false,
      "description": "Emit a list record before its members. (mode=getList)",
      "prefill": false,
      "title": "Include list metadata",
      "type": "boolean"
    },
    "includeParents": {
      "default": false,
      "description": "Include ancestor posts above the requested post. (mode=postThread)",
      "prefill": false,
      "title": "Include parent posts",
      "type": "boolean"
    },
    "includePins": {
      "default": false,
      "description": "Include the pinned post at the top of the author feed. (mode=profile)",
      "prefill": false,
      "title": "Include pinned post",
      "type": "boolean"
    },
    "includeStarterPackMembers": {
      "default": true,
      "description": "Emit the accounts in the starter pack's list after the pack record. (mode=getStarterPack)",
      "prefill": true,
      "title": "Include starter-pack members",
      "type": "boolean"
    },
    "language": {
      "default": "",
      "description": "ISO 639-1 language filter for post search and post records. Empty means no filter.",
      "editor": "select",
      "enum": [
        "",
        "ab",
        "aa",
        "af",
        "ak",
        "sq",
        "am",
        "ar",
        "an",
        "hy",
        "as",
        "av",
        "ae",
        "ay",
        "az",
        "bm",
        "ba",
        "eu",
        "be",
        "bn",
        "bi",
        "bs",
        "br",
        "bg",
        "my",
        "ca",
        "ch",
        "ce",
        "ny",
        "zh",
        "cu",
        "cv",
        "kw",
        "co",
        "cr",
        "hr",
        "cs",
        "da",
        "dv",
        "nl",
        "dz",
        "en",
        "eo",
        "et",
        "ee",
        "fo",
        "fj",
        "fi",
        "fr",
        "ff",
        "gl",
        "lg",
        "ka",
        "de",
        "gn",
        "gu",
        "ht",
        "ha",
        "he",
        "hz",
        "hi",
        "ho",
        "hu",
        "is",
        "io",
        "ig",
        "id",
        "ia",
        "ie",
        "iu",
        "ik",
        "ga",
        "it",
        "ja",
        "jv",
        "kl",
        "kn",
        "kr",
        "ks",
        "kk",
        "km",
        "ki",
        "rw",
        "ky",
        "kv",
        "kg",
        "ko",
        "kj",
        "ku",
        "lo",
        "la",
        "lv",
        "li",
        "ln",
        "lt",
        "lu",
        "lb",
        "mk",
        "mg",
        "ms",
        "ml",
        "mt",
        "gv",
        "mi",
        "mr",
        "mh",
        "el",
        "mn",
        "na",
        "nv",
        "ng",
        "ne",
        "nd",
        "se",
        "no",
        "nb",
        "nn",
        "oc",
        "oj",
        "or",
        "om",
        "os",
        "pi",
        "pa",
        "fa",
        "pl",
        "pt",
        "ps",
        "qu",
        "ro",
        "rm",
        "rn",
        "ru",
        "sm",
        "sg",
        "sa",
        "sc",
        "gd",
        "sr",
        "sh",
        "sn",
        "ii",
        "sd",
        "si",
        "sk",
        "sl",
        "so",
        "nr",
        "st",
        "es",
        "su",
        "sw",
        "ss",
        "sv",
        "tl",
        "ty",
        "tg",
        "ta",
        "tt",
        "te",
        "th",
        "bo",
        "ti",
        "to",
        "ts",
        "tn",
        "tr",
        "tk",
        "tw",
        "ug",
        "uk",
        "ur",
        "uz",
        "ve",
        "vi",
        "vo",
        "wa",
        "cy",
        "fy",
        "wo",
        "xh",
        "yi",
        "yo",
        "za",
        "zu"
      ],
      "enumTitles": [
        "(no filter)",
        "Abkhazian",
        "Afar",
        "Afrikaans",
        "Akan",
        "Albanian",
        "Amharic",
        "Arabic",
        "Aragonese",
        "Armenian",
        "Assamese",
        "Avaric",
        "Avestan",
        "Aymara",
        "Azerbaijani",
        "Bambara",
        "Bashkir",
        "Basque",
        "Belarusian",
        "Bengali",
        "Bislama",
        "Bosnian",
        "Breton",
        "Bulgarian",
        "Burmese",
        "Catalan",
        "Chamorro",
        "Chechen",
        "Chichewa",
        "Chinese",
        "Church Slavic",
        "Chuvash",
        "Cornish",
        "Corsican",
        "Cree",
        "Croatian",
        "Czech",
        "Danish",
        "Divehi",
        "Dutch",
        "Dzongkha",
        "English",
        "Esperanto",
        "Estonian",
        "Ewe",
        "Faroese",
        "Fijian",
        "Finnish",
        "French",
        "Fulah",
        "Galician",
        "Ganda",
        "Georgian",
        "German",
        "Guarani",
        "Gujarati",
        "Haitian",
        "Hausa",
        "Hebrew",
        "Herero",
        "Hindi",
        "Hiri Motu",
        "Hungarian",
        "Icelandic",
        "Ido",
        "Igbo",
        "Indonesian",
        "Interlingua (International Auxiliary Language Association)",
        "Interlingue",
        "Inuktitut",
        "Inupiaq",
        "Irish",
        "Italian",
        "Japanese",
        "Javanese",
        "Kalaallisut",
        "Kannada",
        "Kanuri",
        "Kashmiri",
        "Kazakh",
        "Khmer",
        "Kikuyu",
        "Kinyarwanda",
        "Kirghiz",
        "Komi",
        "Kongo",
        "Korean",
        "Kuanyama",
        "Kurdish",
        "Lao",
        "Latin",
        "Latvian",
        "Limburgan",
        "Lingala",
        "Lithuanian",
        "Luba-Katanga",
        "Luxembourgish",
        "Macedonian",
        "Malagasy",
        "Malay (macrolanguage)",
        "Malayalam",
        "Maltese",
        "Manx",
        "Maori",
        "Marathi",
        "Marshallese",
        "Modern Greek (1453-)",
        "Mongolian",
        "Nauru",
        "Navajo",
        "Ndonga",
        "Nepali (macrolanguage)",
        "North Ndebele",
        "Northern Sami",
        "Norwegian",
        "Norwegian Bokmål",
        "Norwegian Nynorsk",
        "Occitan (post 1500)",
        "Ojibwa",
        "Oriya (macrolanguage)",
        "Oromo",
        "Ossetian",
        "Pali",
        "Panjabi",
        "Persian",
        "Polish",
        "Portuguese",
        "Pushto",
        "Quechua",
        "Romanian",
        "Romansh",
        "Rundi",
        "Russian",
        "Samoan",
        "Sango",
        "Sanskrit",
        "Sardinian",
        "Scottish Gaelic",
        "Serbian",
        "Serbo-Croatian",
        "Shona",
        "Sichuan Yi",
        "Sindhi",
        "Sinhala",
        "Slovak",
        "Slovenian",
        "Somali",
        "South Ndebele",
        "Southern Sotho",
        "Spanish",
        "Sundanese",
        "Swahili (macrolanguage)",
        "Swati",
        "Swedish",
        "Tagalog",
        "Tahitian",
        "Tajik",
        "Tamil",
        "Tatar",
        "Telugu",
        "Thai",
        "Tibetan",
        "Tigrinya",
        "Tonga (Tonga Islands)",
        "Tsonga",
        "Tswana",
        "Turkish",
        "Turkmen",
        "Twi",
        "Uighur",
        "Ukrainian",
        "Urdu",
        "Uzbek",
        "Venda",
        "Vietnamese",
        "Volapük",
        "Walloon",
        "Welsh",
        "Western Frisian",
        "Wolof",
        "Xhosa",
        "Yiddish",
        "Yoruba",
        "Zhuang",
        "Zulu"
      ],
      "prefill": "",
      "title": "Language",
      "type": "string"
    },
    "listUri": {
      "description": "AT URI of a Bluesky list. Used by getList and listFeed.",
      "editor": "textfield",
      "title": "List AT URI",
      "type": "string"
    },
    "listUris": {
      "default": [],
      "description": "AT URIs or bsky.app list URLs for batch list processing. (mode=getList)",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [],
      "title": "List AT URIs",
      "type": "array"
    },
    "maxFollowers": {
      "description": "Keep accounts with at most this many followers.",
      "maximum": 1000000000,
      "minimum": 0,
      "title": "Maximum followers",
      "type": "integer"
    },
    "maxItems": {
      "default": 40,
      "description": "Hard cap on emitted records. For batch modes the cap applies across the whole run.",
      "maximum": 5000,
      "minimum": 1,
      "prefill": 3,
      "title": "Max items",
      "type": "integer"
    },
    "maxRepliesPerPost": {
      "default": 100,
      "description": "Maximum direct replies followed under each post while walking a thread. Larger values reach more branches but cost more requests. (mode=postThread)",
      "maximum": 1000,
      "minimum": 1,
      "prefill": 100,
      "title": "Max replies per post",
      "type": "integer"
    },
    "mediaOnly": {
      "default": false,
      "description": "Only emit posts with at least one image, video, or external embed.",
      "prefill": false,
      "title": "Media only",
      "type": "boolean"
    },
    "mentionsUser": {
      "description": "Only posts mentioning this handle or DID. (mode=search)",
      "editor": "textfield",
      "title": "Mentioning user",
      "type": "string"
    },
    "minFollowers": {
      "description": "Keep accounts with at least this many followers.",
      "maximum": 1000000000,
      "minimum": 0,
      "title": "Minimum followers",
      "type": "integer"
    },
    "minLikes": {
      "description": "Drop posts with fewer likes.",
      "maximum": 10000000,
      "minimum": 0,
      "title": "Minimum likes",
      "type": "integer"
    },
    "minQuotes": {
      "description": "Drop posts with fewer quote posts.",
      "maximum": 10000000,
      "minimum": 0,
      "title": "Minimum quotes",
      "type": "integer"
    },
    "minReplies": {
      "description": "Drop posts with fewer replies.",
      "maximum": 10000000,
      "minimum": 0,
      "title": "Minimum replies",
      "type": "integer"
    },
    "minReposts": {
      "description": "Drop posts with fewer reposts.",
      "maximum": 10000000,
      "minimum": 0,
      "title": "Minimum reposts",
      "type": "integer"
    },
    "mode": {
      "default": "search",
      "description": "What to fetch.",
      "editor": "select",
      "enum": [
        "search",
        "profile",
        "profiles",
        "actorSearch",
        "feed",
        "postThread",
        "urlFetch",
        "getPosts",
        "follows",
        "followers",
        "getLikes",
        "repostedBy",
        "quotes",
        "actorLikes",
        "getList",
        "listFeed",
        "lists",
        "actorFeeds",
        "getStarterPack",
        "starterPackSearch",
        "feedGenerator",
        "feedGeneratorsDiscovery",
        "relationships",
        "discovery"
      ],
      "enumTitles": [
        "Search posts - keyword, hashtag, author, mention, domain or URL",
        "Profile - metadata plus recent posts",
        "Profiles - batch lookup by handle or DID",
        "Account search - find users by keyword",
        "Feed - custom feed or built-in preset",
        "Post thread - post, full reply branches, optional parents",
        "URL fetch - expand bsky.app post, profile, list, feed or starter-pack URLs",
        "Get posts - batch-hydrate AT URIs or post URLs",
        "Follows - accounts a user follows",
        "Followers - accounts following a user",
        "Likes - accounts that liked a post",
        "Reposts - accounts that reposted a post",
        "Quotes - posts quoting a post",
        "Actor likes - posts an account liked, via its public PDS",
        "List members - one or more lists, optional list metadata",
        "List feed - posts in a list",
        "Lists - lists created by an account",
        "Actor feeds - feed generators created by an account",
        "Starter packs - pack details and members",
        "Starter-pack search - find starter packs by keyword",
        "Feed generator - details for one or more feeds",
        "Feed discovery - popular feed generators",
        "Relationships - public follow/block checks for supplied accounts",
        "Discovery - trending topics, suggested feeds, starter packs, tags, follows"
      ],
      "prefill": "profile",
      "title": "Mode",
      "type": "string"
    },
    "postUri": {
      "description": "AT URI of a post. Used by postThread, getLikes, repostedBy, and quotes.",
      "editor": "textfield",
      "title": "Post AT URI",
      "type": "string"
    },
    "postUris": {
      "default": [],
      "description": "AT URIs of posts to hydrate. Used by getPosts and as a fallback for single-post modes.",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [],
      "title": "Post AT URIs",
      "type": "array"
    },
    "postUrls": {
      "default": [],
      "description": "bsky.app post, profile, list, feed, or starter-pack URLs. Used by urlFetch, getPosts, and as a fallback for single-post modes.",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [],
      "title": "Bluesky URLs",
      "type": "array"
    },
    "respectNoUnauthenticated": {
      "default": true,
      "description": "Skip records whose author carries the `!no-unauthenticated` label. The run status reports how many records were skipped.",
      "prefill": true,
      "title": "Respect no-unauthenticated accounts",
      "type": "boolean"
    },
    "searchDomain": {
      "description": "Only posts linking to this domain, e.g. `github.com`. (mode=search)",
      "editor": "textfield",
      "title": "Search domain",
      "type": "string"
    },
    "searchQuery": {
      "default": "bluesky",
      "description": "Keyword, hashtag, phrase, or Lucene-style query. Used by search, actorSearch, starterPackSearch, and feedGeneratorsDiscovery.",
      "editor": "textfield",
      "prefill": "bluesky",
      "title": "Search query",
      "type": "string"
    },
    "searchSort": {
      "default": "latest",
      "description": "Search ranking. `latest` returns newest first; `top` returns engagement-ranked posts. Both use time-window pagination to collect beyond one page.",
      "editor": "select",
      "enum": [
        "top",
        "latest"
      ],
      "enumTitles": [
        "Top - engagement-ranked",
        "Latest - newest first (supports deeper collection)"
      ],
      "prefill": "latest",
      "title": "Search sort",
      "type": "string"
    },
    "searchTags": {
      "default": [],
      "description": "Only posts with these hashtags (without `#`). Multiple tags are AND-matched. (mode=search)",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [],
      "title": "Search hashtags",
      "type": "array"
    },
    "searchUrl": {
      "description": "Only posts linking to this exact URL. (mode=search)",
      "editor": "textfield",
      "title": "Search URL",
      "type": "string"
    },
    "since": {
      "description": "Earliest post date as `YYYY-MM-DD` or an ISO datetime. (mode=search)",
      "editor": "textfield",
      "title": "Since",
      "type": "string"
    },
    "starterPackUri": {
      "description": "AT URI of a starter pack. (mode=getStarterPack)",
      "editor": "textfield",
      "title": "Starter pack AT URI",
      "type": "string"
    },
    "starterPackUris": {
      "default": [],
      "description": "AT URIs or bsky.app starter-pack URLs for batch processing. (mode=getStarterPack)",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [],
      "title": "Starter pack AT URIs",
      "type": "array"
    },
    "threadDepth": {
      "default": 6,
      "description": "How many reply levels and ancestor levels to walk. Depths beyond about 10 reply levels are reached by walking reply branches across requests. 0 returns only the requested post. (mode=postThread)",
      "maximum": 1000,
      "minimum": 0,
      "prefill": 6,
      "title": "Thread depth",
      "type": "integer"
    },
    "until": {
      "description": "Latest post date as `YYYY-MM-DD` or an ISO datetime. (mode=search)",
      "editor": "textfield",
      "title": "Until",
      "type": "string"
    },
    "verifiedOnly": {
      "default": false,
      "description": "Only emit accounts with a valid Bluesky verification, or posts whose author is verified. Records with no verification object are excluded. Post modes hydrate author profiles so verification can be checked.",
      "prefill": false,
      "title": "Verified only",
      "type": "boolean"
    }
  },
  "required": [
    "mode"
  ],
  "schemaVersion": 1,
  "title": "Bluesky Posts, Profiles, Feeds & Threads Scraper Input",
  "type": "object"
}

Output schema

Published result links and storage locations. This schema is not an exhaustive contract for every field in a dataset record.

FieldTypeRequiredDescription
recordsstringoptionalDataset containing all scraped posts, accounts, lists, starter packs, feed generators and discovery records.

Download the published output schema

View complete JSON
{
  "actorOutputSchemaVersion": 1,
  "description": "Bluesky posts, accounts, lists, starter packs, feed generators, trending topics and tag suggestions from the public read API.",
  "properties": {
    "records": {
      "description": "Dataset containing all scraped posts, accounts, lists, starter packs, feed generators and discovery records.",
      "template": "{{links.apiDefaultDatasetUrl}}/items",
      "title": "Bluesky records",
      "type": "string"
    }
  },
  "title": "Bluesky Posts, Profiles, Feeds & Threads Scraper Output"
}

Dataset schema

Published dataset views and any declared field definitions. A view can select only a subset of the returned record fields.

Download the published dataset schema

View complete JSON
{
  "actorSpecification": 1,
  "views": {
    "overview": {
      "display": {
        "component": "table",
        "properties": {}
      },
      "title": "Bluesky",
      "transformation": {
        "fields": [
          "recordType",
          "url",
          "createdAt",
          "authorHandle",
          "displayName",
          "text",
          "likeCount",
          "repostCount"
        ]
      }
    }
  }
}

Key-value schema

Published key-value store definitions, when provided by this build.

This definition is not present in the default published build. See the published README for available documentation.

Published README

Read the full published documentation

Bluesky Posts, Profiles, Feeds & Threads Scraper

Scrape Bluesky public data without a login, cookies or an API key. Search posts by keyword, hashtag, author, mention, domain or URL; read profiles, author feeds, full thread reply branches, lists, starter packs, custom feeds, likes, reposts, quotes, actor liked posts and public relationships; and discover trending topics and suggested communities. Every record has flat top-level fields with a few natural nested objects, absolute URLs, ISO dates and omit-empty output.

What this actor does

  • 24 modes across posts, accounts, threads, lists, starter packs, feed generators, relationships and discovery.
  • Post search with the full public filter surface: keyword, hashtag, author, mention, domain, URL, date range, language and top/latest ranking.
  • Search beyond the first page: both searchSort=latest and searchSort=top walk backwards through time windows. Latest is newest-first; Top preserves engagement ranking within each window. Cursor paging is not used because Bluesky rejects anonymous cursors.
  • Full thread reply trees: threadDepth walks deeper than the ~10-level per-request limit by fetching truncated reply branches separately. maxRepliesPerPost bounds fan-out and threadTruncated marks records whose children were cut short.
  • Actor likes without credentials: mode=actorLikes reads the account's public like records from its personal data server and hydrates the liked posts, with likedAt and like-record fields.
  • More public surfaces: mode=actorFeeds lists an account's feed generators, mode=starterPackSearch searches starter packs, and mode=relationships checks public follow/block relationships for supplied accounts.
  • Rich records: engagement counts, languages, mentions, hashtags, links, domains, images, video, external embeds, quoted posts, reposts, reply roots, labels, self-labels, verification, live status, pinned posts, profile counts and flat author follower counts.
  • Privacy-aware: accounts marked !no-unauthenticated are skipped by default, and the run status reports how many records were skipped.
  • Batch-friendly: multiple profiles, posts, lists, starter packs, feeds and URLs per run, with automatic de-duplication.
  • No credentials required. Every mode reads public data. If Bluesky temporarily blocks a search request from the actor's network, the actor retries it automatically and reports a clear status if it still fails.

Output per record

Every record carries recordType, sourceUrl and scrapedAt. Empty values are omitted at every depth, so the dataset never contains nulls or empty placeholders.

Post records (recordType=post)

  • uri - canonical AT URI
  • cid - content identifier
  • id - same as uri
  • url - public bsky.app post URL
  • sourceUrl - same as url
  • text - post text
  • createdAt, indexedAt - ISO 8601 timestamps
  • language - first declared language
  • languages[] - all declared languages
  • replyCount, repostCount, likeCount, quoteCount, bookmarkCount
  • isReply - true when the post replies to another post
  • inReplyToUri, inReplyToCid - parent post
  • rootUri, rootCid - thread root
  • isRepost - true when surfaced as a repost
  • repostedBy - handle that reposted it
  • repostUri, repostCid, repostedAt - repost metadata
  • isQuote - true when the post quotes another post
  • threadTruncated - true on a thread record whose direct replies were cut by maxRepliesPerPost, maxItems or a public-API gap (mode=postThread)
  • likedAt, likedBy, likedByDid, likeUri, likeCid - like-record metadata added by mode=actorLikes
  • quotedPost - {uri, cid, text, createdAt, indexedAt, authorHandle, authorDid, authorDisplayName, authorAvatar, url, likeCount, repostCount, replyCount, quoteCount, labels, labelValues, mediaAttachments}
  • mentions[] - mentioned DIDs
  • tags[] - hashtags, lowercase
  • urls[] - external links
  • domains[] - hostnames from urls[]
  • mediaAttachments[] - {type, url, previewUrl, description, width, height, presentation, title} for images, video and external embeds
  • hasMedia, mediaTypes[]
  • labels[] - {val, src, uri, cid, cts, ver}
  • labelValues[] - label values only
  • selfLabels[] - author-applied labels
  • author - {did, handle, displayName, avatar, createdAt, profileUrl, labels, labelValues, verification, status}; with hydrateAuthors=true (the default) it also includes description, banner, followersCount, followsCount, postsCount, indexedAt, pinnedPostUri, pinnedPostCid. The hydrated profile's handle and did replace stale values, and url, sourceUrl and authorHandle are recomputed
  • authorFollowersCount, authorFollowsCount, authorPostsCount, authorVerified - flat author stats added when hydrateAuthors=true
  • authorHandle - convenience field
  • hitsTotal, searchHitsTotal - search-result totals when Bluesky returns them (the value is capped/rounded by the source, so treat it as an estimate)

Account records (recordType=account, like, listMember, repost or starterPackMember)

  • did, id, handle, displayName, description, pronouns
  • avatar, banner
  • followersCount, followsCount, postsCount
  • createdAt, indexedAt
  • url, sourceUrl - public profile URL
  • labels[], labelValues[]
  • verification - {verifiedStatus, trustedVerifierStatus, verifications[]}
  • associated - {listsCount, feedGeneratorsCount, starterPacksCount, isLabeler, chatAllowIncoming, chatAllowGroupInvites, activitySubscription}
  • status - {type, createdAt, durationMinutes, expiresAt, isActive, embed}
  • pinnedPostUri, pinnedPostCid
  • relation - profile, searchMatch, follower, following, liked, reposted, listMember, starterPackMember, suggestedFollow or relationship
  • likedAt, likedPostUri - for mode=getLikes
  • repostedPostUri - for mode=repostedBy
  • listUri, listName - for list members
  • starterPackUri - for starter-pack members
  • relationshipActor, isFollowing, isFollowedBy, isMutualFollow - for mode=relationships
  • following, followedBy, blocking, blockedBy - public relationship record URIs when present

List records (recordType=list)

  • uri, cid, id, name, purpose, description
  • listItemCount
  • creator - account summary
  • creatorHandle, creatorDid
  • labels[], labelValues[], indexedAt
  • url, sourceUrl - public list URL

Starter-pack records (recordType=starterPack)

  • uri, cid, id, name, description
  • creator - account summary
  • creatorHandle, creatorDid
  • listUri, listName, listItemCount
  • joinedAllTimeCount, joinedWeekCount
  • createdAt, updatedAt
  • feeds[] - {uri, displayName, description, avatar, creatorHandle}
  • listItemsSample[] - sample account summaries
  • labels[], labelValues[], indexedAt
  • url, sourceUrl - public starter-pack URL

Feed-generator records (recordType=feedGenerator)

  • uri, cid, id, did
  • displayName, description, avatar
  • likeCount, acceptsInteractions
  • creator - account summary
  • creatorHandle, creatorDid
  • labels[], labelValues[], indexedAt
  • isOnline, isValid - when fetched with mode=feedGenerator
  • url, sourceUrl - public feed URL

Discovery records

  • recordType=trendingTopic: topic, displayName, description, link, url, sourceUrl, rank
  • recordType=taggedSuggestion: tag, subjectType, subject, url, sourceUrl

When a discovery item has no public target URL, url and sourceUrl fall back to the Bluesky home page so every record still has a source link.

Input

Field Type Default Description
mode Enum search search / profile / profiles / actorSearch / feed / postThread / urlFetch / getPosts / follows / followers / getLikes / repostedBy / quotes / actorLikes / getList / listFeed / lists / actorFeeds / getStarterPack / starterPackSearch / feedGenerator / feedGeneratorsDiscovery / relationships / discovery
searchQuery String bluesky Keyword, hashtag, phrase or Lucene-style query. Used by search, actorSearch, starterPackSearch and feedGeneratorsDiscovery
searchSort Enum latest latest (newest first; supports deeper collection) or top (engagement-ranked, capped at about 100 posts)
searchTags Array [] Hashtags without #; multiple tags are AND-matched (mode=search)
searchDomain String – Only posts linking to this domain (mode=search)
searchUrl String – Only posts linking to this exact URL (mode=search)
mentionsUser String – Only posts mentioning this handle or DID (mode=search)
fromUser String – Only posts authored by this handle or DID (mode=search)
since String – Earliest post date (YYYY-MM-DD or ISO datetime); a bare date starts at 00:00 UTC (mode=search)
until String – Latest post date (YYYY-MM-DD or ISO datetime); a bare date includes the whole day through 23:59:59.999999 UTC (mode=search)
language Enum – ISO 639-1 language filter; empty means no filter
authorFeedFilter Enum posts_with_replies posts_with_replies / posts_no_replies / posts_with_media / posts_and_author_threads (mode=profile)
includePins Boolean false Include the pinned post at the top of the author feed (mode=profile)
includeParents Boolean false Include ancestor posts above the requested post (mode=postThread)
threadDepth Integer 6 Reply and ancestor levels to walk, 0-1000. Depths beyond about 10 reply levels are reached by walking branches across requests (mode=postThread)
maxRepliesPerPost Integer 100 Maximum direct replies followed under each post while walking a thread, 1-1000 (mode=postThread)
actor String – Handle or DID. Used by profile, follows, followers, lists, actorLikes, actorFeeds, relationships and discoveryType=suggestedFollows
actors Array [] Handles, DIDs or profile URLs for mode=profiles; the accounts to check against actor for mode=relationships
postUri String – AT URI of a post. Used by postThread, getLikes, repostedBy and quotes
postUris Array [] AT URIs to hydrate (mode=getPosts; fallback for single-post modes)
postUrls Array [] bsky.app post URLs for getPosts; post, profile, list, feed or starter-pack URLs for urlFetch; fallback for single-post modes
listUri String – AT URI of a list (mode=getList, mode=listFeed)
listUris Array [] AT URIs or list URLs for batch list processing (mode=getList)
starterPackUri String – AT URI of a starter pack (mode=getStarterPack)
starterPackUris Array [] AT URIs or starter-pack URLs for batch processing (mode=getStarterPack)
feedPreset Enum - whats-hot / bsky-team / hot-classic; an explicit feedUri always wins. Legacy names (discover, mutuals, popular-with-friends, for-you, news, trending-videos, quiet-posters) are accepted and mapped to What's Hot. If neither is set, mode=feed uses What's Hot
feedUri String – AT URI or bsky.app feed URL (mode=feed, mode=feedGenerator)
feedUris Array [] AT URIs or feed URLs for batch lookup (mode=feedGenerator)
discoveryType Enum trendingTopics trendingTopics / suggestedFeeds / suggestedStarterPacks / taggedSuggestions / suggestedFollows (mode=discovery)
excludeReplies Boolean false Drop posts that are replies
excludeReposts Boolean false Drop reposts
mediaOnly Boolean false Only posts with at least one image, video or external embed
excludeLabeled Boolean false Drop posts and accounts that carry moderation or self-labels, including labels on a post's author
respectNoUnauthenticated Boolean true Skip records whose author carries !no-unauthenticated; the run status reports the skipped count
verifiedOnly Boolean false Only verified accounts, or posts whose author is verified. Records with no verification object are excluded; post modes hydrate author profiles to check
minLikes Integer – Drop posts below this like count, 0-10,000,000
minReposts Integer – Drop posts below this repost count, 0-10,000,000
minReplies Integer – Drop posts below this reply count, 0-10,000,000
minQuotes Integer – Drop posts below this quote count, 0-10,000,000
minFollowers Integer – Keep accounts with at least this many followers, 0-1,000,000,000
maxFollowers Integer – Keep accounts with at most this many followers, 0-1,000,000,000
includeListMetadata Boolean false Emit a list record before its members (mode=getList)
includeStarterPackMembers Boolean true Emit the pack's member accounts (mode=getStarterPack)
hydrateAuthors Boolean true Fetch full author profiles for post records in batches of 25 and add flat author follower, following, post and verification fields. Automatically enabled when verifiedOnly=true; the daily profile prefill leaves it off to stay cheap
maxItems Integer 40 Hard cap on emitted records, 1-5000. Source exhaustion or Bluesky caps may return fewer; the run status reports a shortfall

Legacy saved tasks that specify mode=getActorLikes are mapped to actorLikes with a status message. That mode reads the account's public like records from its personal data server and hydrates the liked posts; no login or app password is used.

Example: brand monitoring with filters

{
  "mode": "search",
  "searchQuery": "bluesky",
  "searchSort": "latest",
  "searchTags": ["opensource"],
  "language": "en",
  "minLikes": 10,
  "maxItems": 300
}

Example: a user's profile and recent media posts

{
  "mode": "profile",
  "actor": "bsky.app",
  "authorFeedFilter": "posts_with_media",
  "includePins": true,
  "maxItems": 50
}

Example: a thread with parents and replies

{
  "mode": "postThread",
  "postUri": "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l",
  "includeParents": true,
  "threadDepth": 30,
  "maxRepliesPerPost": 100,
  "maxItems": 200
}

Example: posts an account liked

{
  "mode": "actorLikes",
  "actor": "bsky.app",
  "maxItems": 100
}

Example: audience export with follower counts

{
  "mode": "followers",
  "actor": "jay.bsky.team",
  "minFollowers": 100,
  "maxItems": 500
}
{
  "mode": "discovery",
  "discoveryType": "trendingTopics",
  "maxItems": 20
}

Use cases

  • Social listening and brand monitoring - track keywords, hashtags, mentions, domains and authors with date and engagement filters.
  • Influencer and KOL research - combine account search with follower ranges, verification and profile counts.
  • Audience and lead export - export followers, follows, likers, reposters, list members and starter-pack members with handles, bios and counts.
  • Conversation analysis - capture a post, its ancestors and replies up to threadDepth for sentiment or narrative research.
  • Content and LLM datasets - collect post text, languages, hashtags, links, media metadata and engagement counts.
  • Community mapping - explore lists, list feeds, starter packs, custom feeds and trending topics.

FAQ

Do I need a Bluesky account or login? No. Every mode reads public data. No cookies or API keys are needed. If Bluesky temporarily blocks a search request from the actor's network, the actor retries it automatically through an Apify connection and reports a clear status if it still fails. No proxy setup is required.

How far back can a keyword search go? searchSort=latest walks backwards through time windows and can return far more than the 100-post relevance cap. searchSort=top is relevance-ranked and limited to about 100 posts per query. Time-window search is approximate: pages can overlap, so results are de-duplicated by post URI, and a narrow or wide date range changes how predictable the volume is. When Bluesky returns a search hit total it is exposed as hitsTotal/searchHitsTotal, but the source caps and rounds that number.

Why do some posts have no text? Bluesky allows media-only posts. The actor omits empty text and keeps the media metadata.

Why are some fields missing from an account? Basic account views do not always include a bio, banner, follower counts or a pinned post. The actor hydrates accounts in batches so those fields are present whenever Bluesky publishes them. Labels, verification and live status are conditional by nature.

Why are some accounts missing from results? Some accounts opt out of unauthenticated access and carry the !no-unauthenticated label. They are skipped by default and counted in the run status. Set respectNoUnauthenticated=false to include them when Bluesky returns them.

Why does a follower export contain fewer rows than the profile's follower count? Profile counts are cached totals; deactivated or unindexed accounts can make them larger than the returned list. !no-unauthenticated accounts are filtered by this actor by default. The export is complete for what the public API exposes after that policy.

How are reposts and quote posts handled? A repost is one record with isRepost=true, repostedBy and the original post's content. A quote post is one record with the quoter's text and a nested quotedPost object containing the quoted post's text, author, URL, counts and media.

What is the difference between mode=search and mode=actorSearch? search finds posts. actorSearch finds accounts by handle, display name or bio.

What is a feed, and which presets are available? A feed is a curated post stream produced by a feed generator. The built-in presets are What's Hot, Bluesky Team and Hot Classic. Paste any other generator's AT URI or bsky.app feed URL into feedUri. An explicit feedUri always takes precedence over feedPreset; legacy preset names are mapped to What's Hot.

Does feedPreset override my custom feedUri? No. feedUri/feedUris win whenever they are supplied. feedPreset is only used when no feed URI is given, and mode=feedGenerator never adds an unrequested feed.

How does verifiedOnly work? It keeps only accounts with a valid Bluesky verification and posts whose author is verified. Records with no verification object are excluded. Post modes hydrate author profiles so verification can be checked, which adds batched profile requests and may return fewer posts than an unfiltered search.

How do actor likes work without a login? mode=actorLikes resolves the account's personal data server from its public DID document, lists the public app.bsky.feed.like records stored there, and hydrates each liked post. No credentials are used. Likes whose posts were deleted, or accounts whose DID document does not expose a public data server, return no rows for that part. mode=getLikes is the opposite direction: it lists the accounts that liked a given post.

How deep can a thread go? threadDepth can be set up to 1000. The public thread endpoint returns about 10 reply levels per request, so the actor detects reply branches that still have children and fetches those branches separately. maxRepliesPerPost caps how many direct replies are followed under each post; when a branch is cut, the affected post carries threadTruncated=true and the run status explains why.

What is mode=relationships? It checks public follow and block relationships between actor and each account in actors (up to batches of 30). Each account record gets isFollowing, isFollowedBy, isMutualFollow and the public relationship record URIs. It is not a replacement for a logged-in viewer's personalised "known followers" list, which needs an account context.

Why did I get fewer records than maxItems? Filters can exclude many candidates, Bluesky can exhaust the source, and some search modes have source caps. The run status message reports the shortfall; it does not silently pretend the result is complete.

Can I export followers of a very large account? Yes, up to maxItems. Bluesky returns followers in cursor-paged batches; the actor keeps walking short pages until the cap or the end of the list.

How current is the data? Live. Every run reads Bluesky at request time, so schedule the actor hourly or daily for ongoing refreshes.

Is this affiliated with Bluesky? No. This is an independent actor that reads public Bluesky data.

Limitations

  • Top search uses time windows. searchSort=top is engagement-ranked; the actor walks older time windows to collect more than one page, preserving ranking within each window. Results are deduplicated by post URI.
  • Time-window search is approximate. The latest walk can return posts outside the exact window, can overlap between windows, and is de-duplicated by post URI. The until boundary uses the newer of a post's createdAt and indexedAt, and a date-only until includes the whole UTC day.
  • Search hit totals are estimates. When Bluesky returns hitsTotal/searchHitsTotal, the source caps and rounds the number; it is not an exact result count.
  • Search can be temporarily blocked. If Bluesky returns HTTP 403 even after the automatic Apify retry, the run stops with a clear status message. Try again later or use mode=profile, mode=feed or a direct post/list feed.
  • Search coverage is not exhaustive. Bluesky's search index is recency-weighted and does not include every post.
  • Thread walking is bounded on purpose. Each request returns about 10 reply levels, so deeper replies are fetched branch by branch. The walk stops at threadDepth, maxRepliesPerPost, maxItems or the per-run branch budget; affected records carry threadTruncated=true. Deleted, blocked, hidden or rate-limited branches still create gaps.
  • Actor likes depend on the public data server. The like records are read from the account's personal data server rather than the public feed service. If that server is unreachable, does not appear in the DID document, or no longer stores the like record, those likes cannot be returned. Deleted posts are skipped even when their like record remains.
  • Personalised known followers need a login. The public relationship check in mode=relationships can tell you whether supplied accounts follow or block a target, but a viewer-specific "followers you know" list requires an authenticated account context, which this actor does not use.
  • Starter-pack typeahead is not a separate mode. mode=starterPackSearch uses the public starter-pack search endpoint, which covers keyword search and paging; a viewer-boosted typeahead ordering is not exposed without an account context.
  • Hidden accounts are skipped by default. Accounts that carry !no-unauthenticated are filtered out unless respectNoUnauthenticated=false, and the status message reports how many records were skipped.
  • Follower counts can exceed exported rows. Profile totals are cached by Bluesky and include accounts that are deactivated or no longer indexed. !no-unauthenticated accounts are returned by the API and then filtered by this actor by default, so followersCount can exceed the exported rows. Set respectNoUnauthenticated=false to include them.
  • Private data is out of scope. Direct messages, private accounts, notifications and muted/blocked relationships are not available.
  • Some fields are conditional. Labels, verification, live status, pinned posts, banners and media are present only when the source has them.
  • Custom feeds depend on third-party generators. If a generator is offline, its feed returns no posts.
  • Follower lists can be very large. Use maxItems to bound a run.
  • maxItems is capped at 5,000 per run. Larger requests are clamped by the input schema.
  • Filtered account modes keep walking cursor pages until the cap or source exhaustion. If Bluesky has no more matches, the run reports a shortfall in its status message.
  • verifiedOnly can return far fewer records. Most post authors do not publish a verification object, so verified-only post searches are intentionally narrow.
  • mode=feedGenerator returns only the feeds you request. It does not append a default What's Hot record.

Python quickstart

Use a schema-derived input and the Python standard library to start a run. An Apify account and token are required for execution.

Open the step-by-step Python guide →

Source build QVca54L51kgdV5Lsb. Documentation is regenerated from the default published build; private drafts are not included.