Nimbryxo Studio

Reddit Multi-Mode Scraper for Posts, Comments & Profiles

Pick one of five modes to pull subreddit posts, full comment threads, user profiles, keyword search results or curated community listings from Reddit, each with deep post/comment filters. No account or API key needed.

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 scrape: a subreddit listing, post URLs with comments, a user profile, or keyword search.
sourcestringoptionalauto uses live Reddit first and the Arctic Shift archive for depth/bulk or as a fallback. archive is faster and cheaper but lags live Reddit by several hours; live never uses archive data.
subredditsarrayoptionalSubreddits to scrape (mode=subreddit). Accepts names, r/ names or URLs.
Show all input fields
FieldTypeRequiredDescription
modestringrequiredWhat to scrape: a subreddit listing, post URLs with comments, a user profile, or keyword search.
sourcestringoptionalauto uses live Reddit first and the Arctic Shift archive for depth/bulk or as a fallback. archive is faster and cheaper but lags live Reddit by several hours; live never uses archive data.
subredditsarrayoptionalSubreddits to scrape (mode=subreddit). Accepts names, r/ names or URLs.
postUrlsarrayoptionalPost URLs, comment URLs, share links or bare post IDs (mode=post).
usernamesarrayoptionalReddit usernames to scrape (mode=profile). Accepts names, u/ names or profile URLs.
searchQuerystringoptionalKeyword or phrase to search for (mode=search). Reddit search syntax such as "exact phrase", author:name, subreddit:name and -exclude is supported by live search.
maxItemsintegeroptionalHard cap on all records pushed by the run, across every target.
maxPostsintegeroptionalPosts per subreddit, keyword or profile section.
maxCommentsintegeroptionalComments per post, keyword, or profile comment section. 0 disables comment records.
maxDepthintegeroptionalDeepest reply level to emit (0 = top-level comments only).
includeCommentsbooleanoptionalEmit comment records for each post. Disable to fetch only the parent post.
includePostbooleanoptionalEmit the post record before its comments.
sortstringoptionalPost/listing sort. Search accepts relevance, hot, top, new or comments; other modes use hot, new, top, rising, controversial or best.
timeFilterstringoptionalTime window for top/controversial sorts and search.
commentSortstringoptionalComment ordering for mode=post.
includeNSFWbooleanoptionalInclude over-18 posts and communities.
includeSubredditInfobooleanoptionalEmit one community record per subreddit before its posts.
includeSubredditRulesbooleanoptionalAttach posting rules to the community record. Requires includeSubredditInfo.
includeProfileInfobooleanoptionalEmit a profile record with karma, counts and account metadata.
sectionsarrayoptionalWhich history sections to fetch (mode=profile). Allowed values: overview, posts, comments.
searchPostsbooleanoptionalInclude post results in keyword search.
searchCommentsbooleanoptionalInclude comment results in keyword search when Reddit's comment tab returns them.
searchCommunitiesbooleanoptionalInclude subreddit matches in keyword search.
searchUsersbooleanoptionalInclude matching Reddit accounts in keyword search.
withinCommunitystringoptionalLimit post/comment search to a single subreddit (name, r/name or URL). Required for archive keyword search.
maxCommunitiesintegeroptionalMaximum subreddit matches per search query.
maxUsersintegeroptionalMaximum account matches per search query.
onlyNewbooleanoptionalEmit only records newer than the watermark saved under stateKey by a previous run.
stateKeystringoptionalKey-value store key prefix used by onlyNew watermarks.
failOnEmptybooleanoptionalMark the run FAILED with a clear status message instead of finishing silently with 0 records.
maxProxyBytesMbintegeroptionalSafety ceiling for paid proxy traffic. The run stops when the ceiling is reached. Images, media and fonts are never downloaded.
proxyModestringoptionalDirect (no proxy) is the default. Choose datacenter if Reddit blocks your runs. Residential is an explicit last resort and is capped by maxProxyBytesMb.
minScoreintegeroptionalDrop posts/comments below this score.
maxScoreintegeroptionalDrop posts/comments above this score.
minPostCommentsintegeroptionalDrop posts with fewer comments than this.
maxPostCommentsintegeroptionalDrop posts with more comments than this.
minUpvoteRationumberoptionalDrop posts below this upvote ratio (0-1).
postTypestringoptionalKeep only posts of this type.
titleContainsstringoptionalKeep only posts whose title contains this text.
contentContainsstringoptionalKeep only posts whose body/self-text contains this text.
flairContainsstringoptionalKeep only posts whose link flair contains this text.
authorFlairContainsstringoptionalKeep only posts whose author flair contains this text.
domainstringoptionalKeep only posts whose link domain contains this text.
authorsarrayoptionalKeep posts by these usernames.
excludeAuthorsarrayoptionalDrop posts by these usernames.
excludeKeywordsarrayoptionalDrop posts whose title, body or flair contains any of these terms.
excludeStickiedbooleanoptionalExclude pinned/stickied posts from results.
excludeRemovedbooleanoptionalExclude posts or comments removed by moderators.
excludeCrosspostsbooleanoptionalExclude crossposts.
excludeSpoilersbooleanoptionalExclude posts marked as spoilers.
excludeLockedbooleanoptionalExclude locked posts and comments.
excludeDeletedAuthorbooleanoptionalExclude records whose author account was deleted.
excludeArchivedbooleanoptionalExclude archived posts that no longer accept votes or comments.
onlyWithFlairbooleanoptionalDrop posts without a link flair.
onlyOriginalContentbooleanoptionalKeep only posts tagged as OC.
minAwardsintegeroptionalKeep only posts with at least this many awards.
minContentLengthintegeroptionalKeep only posts whose body is at least this many characters.
maxContentLengthintegeroptionalKeep only posts whose body is at most this many characters.
postedAfterstringoptionalUTC date lower bound (YYYY-MM-DD).
postedBeforestringoptionalUTC date upper bound (YYYY-MM-DD), inclusive.
restrictSubredditsarrayoptionalOnly keep profile posts/comments made in these subreddits.
keywordstringoptionalOnly keep profile posts/comments whose title, body or text contains this phrase.
minCommunitySubscribersintegeroptionalCommunity search only: drop smaller subreddits.
maxCommunitySubscribersintegeroptionalCommunity search only: drop larger subreddits.
minUserKarmaintegeroptionalUser search only: drop accounts with less total karma.
maxUserKarmaintegeroptionalUser search only: drop accounts with more total karma.
distinguishedstringoptionalKeep only moderator/admin/special posts, or only regular posts.

Download the published input schema

View complete JSON
{
  "description": "Pick a mode, then set its targets. Live records come from Reddit's rendered web pages; deep comment trees and bulk history can fall back to the Arctic Shift archive.",
  "properties": {
    "authorFlairContains": {
      "description": "Keep only posts whose author flair contains this text.",
      "editor": "textfield",
      "title": "Author flair contains",
      "type": "string"
    },
    "authors": {
      "default": [],
      "description": "Keep posts by these usernames.",
      "editor": "stringList",
      "prefill": [],
      "title": "Only these authors",
      "type": "array"
    },
    "commentSort": {
      "default": "confidence",
      "description": "Comment ordering for mode=post.",
      "editor": "select",
      "enum": [
        "confidence",
        "top",
        "new",
        "controversial",
        "old",
        "qa"
      ],
      "enumTitles": [
        "Best (confidence)",
        "Top",
        "New",
        "Controversial",
        "Old",
        "Q&A"
      ],
      "prefill": "confidence",
      "title": "Comment sort",
      "type": "string"
    },
    "contentContains": {
      "description": "Keep only posts whose body/self-text contains this text.",
      "editor": "textfield",
      "title": "Body contains",
      "type": "string"
    },
    "distinguished": {
      "description": "Keep only moderator/admin/special posts, or only regular posts.",
      "editor": "select",
      "enum": [
        "moderator",
        "admin",
        "special",
        "none"
      ],
      "enumTitles": [
        "Moderator posts",
        "Admin posts",
        "Special/official posts",
        "Regular posts only"
      ],
      "title": "Distinguished posts",
      "type": "string"
    },
    "domain": {
      "description": "Keep only posts whose link domain contains this text.",
      "editor": "textfield",
      "title": "Link domain contains",
      "type": "string"
    },
    "excludeArchived": {
      "default": false,
      "description": "Exclude archived posts that no longer accept votes or comments.",
      "prefill": false,
      "title": "Exclude archived posts",
      "type": "boolean"
    },
    "excludeAuthors": {
      "default": [],
      "description": "Drop posts by these usernames.",
      "editor": "stringList",
      "prefill": [],
      "title": "Exclude these authors",
      "type": "array"
    },
    "excludeCrossposts": {
      "default": false,
      "description": "Exclude crossposts.",
      "prefill": false,
      "title": "Exclude crossposts",
      "type": "boolean"
    },
    "excludeDeletedAuthor": {
      "default": false,
      "description": "Exclude records whose author account was deleted.",
      "prefill": false,
      "title": "Exclude deleted authors",
      "type": "boolean"
    },
    "excludeKeywords": {
      "default": [],
      "description": "Drop posts whose title, body or flair contains any of these terms.",
      "editor": "stringList",
      "prefill": [],
      "title": "Exclude keywords",
      "type": "array"
    },
    "excludeLocked": {
      "default": false,
      "description": "Exclude locked posts and comments.",
      "prefill": false,
      "title": "Exclude locked posts",
      "type": "boolean"
    },
    "excludeRemoved": {
      "default": false,
      "description": "Exclude posts or comments removed by moderators.",
      "prefill": false,
      "title": "Exclude removed posts",
      "type": "boolean"
    },
    "excludeSpoilers": {
      "default": false,
      "description": "Exclude posts marked as spoilers.",
      "prefill": false,
      "title": "Exclude spoilers",
      "type": "boolean"
    },
    "excludeStickied": {
      "default": false,
      "description": "Exclude pinned/stickied posts from results.",
      "prefill": false,
      "title": "Exclude stickied posts",
      "type": "boolean"
    },
    "failOnEmpty": {
      "default": true,
      "description": "Mark the run FAILED with a clear status message instead of finishing silently with 0 records.",
      "prefill": false,
      "title": "Fail when no records are found",
      "type": "boolean"
    },
    "flairContains": {
      "description": "Keep only posts whose link flair contains this text.",
      "editor": "textfield",
      "title": "Flair contains",
      "type": "string"
    },
    "includeComments": {
      "default": true,
      "description": "Emit comment records for each post. Disable to fetch only the parent post.",
      "prefill": false,
      "title": "Include comments (mode=post)",
      "type": "boolean"
    },
    "includeNSFW": {
      "default": false,
      "description": "Include over-18 posts and communities.",
      "prefill": false,
      "title": "Include NSFW (18+) posts",
      "type": "boolean"
    },
    "includePost": {
      "default": true,
      "description": "Emit the post record before its comments.",
      "prefill": true,
      "title": "Include parent post (mode=post)",
      "type": "boolean"
    },
    "includeProfileInfo": {
      "default": true,
      "description": "Emit a profile record with karma, counts and account metadata.",
      "prefill": true,
      "title": "Include profile record (mode=profile)",
      "type": "boolean"
    },
    "includeSubredditInfo": {
      "default": false,
      "description": "Emit one community record per subreddit before its posts.",
      "prefill": false,
      "title": "Include community info (mode=subreddit)",
      "type": "boolean"
    },
    "includeSubredditRules": {
      "default": false,
      "description": "Attach posting rules to the community record. Requires includeSubredditInfo.",
      "prefill": false,
      "title": "Include community rules (mode=subreddit)",
      "type": "boolean"
    },
    "keyword": {
      "description": "Only keep profile posts/comments whose title, body or text contains this phrase.",
      "editor": "textfield",
      "title": "Profile keyword filter",
      "type": "string"
    },
    "maxComments": {
      "default": 100,
      "description": "Comments per post, keyword, or profile comment section. 0 disables comment records.",
      "maximum": 100000,
      "minimum": 0,
      "prefill": 5,
      "title": "Maximum comments",
      "type": "integer"
    },
    "maxCommunities": {
      "default": 10,
      "description": "Maximum subreddit matches per search query.",
      "maximum": 1000,
      "minimum": 0,
      "prefill": 0,
      "title": "Maximum community results",
      "type": "integer"
    },
    "maxCommunitySubscribers": {
      "description": "Community search only: drop larger subreddits.",
      "maximum": 1000000000,
      "minimum": 0,
      "title": "Maximum community subscribers",
      "type": "integer"
    },
    "maxContentLength": {
      "description": "Keep only posts whose body is at most this many characters.",
      "maximum": 1000000,
      "minimum": 0,
      "title": "Maximum body length",
      "type": "integer"
    },
    "maxDepth": {
      "default": 6,
      "description": "Deepest reply level to emit (0 = top-level comments only).",
      "maximum": 20,
      "minimum": 0,
      "prefill": 6,
      "title": "Maximum comment depth",
      "type": "integer"
    },
    "maxItems": {
      "default": 50,
      "description": "Hard cap on all records pushed by the run, across every target.",
      "maximum": 10000,
      "minimum": 1,
      "prefill": 2,
      "title": "Maximum total records",
      "type": "integer"
    },
    "maxPostComments": {
      "description": "Drop posts with more comments than this.",
      "maximum": 1000000,
      "minimum": 0,
      "title": "Maximum post comment count",
      "type": "integer"
    },
    "maxPosts": {
      "default": 25,
      "description": "Posts per subreddit, keyword or profile section.",
      "maximum": 5000,
      "minimum": 1,
      "prefill": 2,
      "title": "Maximum posts per target",
      "type": "integer"
    },
    "maxProxyBytesMb": {
      "default": 50,
      "description": "Safety ceiling for paid proxy traffic. The run stops when the ceiling is reached. Images, media and fonts are never downloaded.",
      "maximum": 10000,
      "minimum": 0,
      "prefill": 50,
      "title": "Maximum proxy traffic (MB)",
      "type": "integer"
    },
    "maxScore": {
      "description": "Drop posts/comments above this score.",
      "maximum": 1000000,
      "minimum": -1000000,
      "title": "Maximum score",
      "type": "integer"
    },
    "maxUserKarma": {
      "description": "User search only: drop accounts with more total karma.",
      "maximum": 1000000000,
      "minimum": 0,
      "title": "Maximum user karma",
      "type": "integer"
    },
    "maxUsers": {
      "default": 25,
      "description": "Maximum account matches per search query.",
      "maximum": 100,
      "minimum": 0,
      "prefill": 0,
      "title": "Maximum user results",
      "type": "integer"
    },
    "minAwards": {
      "description": "Keep only posts with at least this many awards.",
      "maximum": 1000000,
      "minimum": 0,
      "title": "Minimum awards",
      "type": "integer"
    },
    "minCommunitySubscribers": {
      "description": "Community search only: drop smaller subreddits.",
      "maximum": 1000000000,
      "minimum": 0,
      "title": "Minimum community subscribers",
      "type": "integer"
    },
    "minContentLength": {
      "description": "Keep only posts whose body is at least this many characters.",
      "maximum": 1000000,
      "minimum": 0,
      "title": "Minimum body length",
      "type": "integer"
    },
    "minPostComments": {
      "description": "Drop posts with fewer comments than this.",
      "maximum": 1000000,
      "minimum": 0,
      "title": "Minimum post comment count",
      "type": "integer"
    },
    "minScore": {
      "description": "Drop posts/comments below this score.",
      "maximum": 1000000,
      "minimum": -1000000,
      "title": "Minimum score",
      "type": "integer"
    },
    "minUpvoteRatio": {
      "description": "Drop posts below this upvote ratio (0-1).",
      "maximum": 1,
      "minimum": 0,
      "title": "Minimum upvote ratio",
      "type": "number"
    },
    "minUserKarma": {
      "description": "User search only: drop accounts with less total karma.",
      "maximum": 1000000000,
      "minimum": 0,
      "title": "Minimum user karma",
      "type": "integer"
    },
    "mode": {
      "default": "subreddit",
      "description": "What to scrape: a subreddit listing, post URLs with comments, a user profile, or keyword search.",
      "editor": "select",
      "enum": [
        "subreddit",
        "post",
        "profile",
        "search"
      ],
      "enumTitles": [
        "Subreddit posts",
        "Post URLs + comments",
        "User profile + history",
        "Keyword search"
      ],
      "prefill": "subreddit",
      "title": "Mode",
      "type": "string"
    },
    "onlyNew": {
      "default": false,
      "description": "Emit only records newer than the watermark saved under stateKey by a previous run.",
      "prefill": false,
      "title": "Only new records (incremental runs)",
      "type": "boolean"
    },
    "onlyOriginalContent": {
      "default": false,
      "description": "Keep only posts tagged as OC.",
      "prefill": false,
      "title": "Only original content",
      "type": "boolean"
    },
    "onlyWithFlair": {
      "default": false,
      "description": "Drop posts without a link flair.",
      "prefill": false,
      "title": "Only posts with flair",
      "type": "boolean"
    },
    "postType": {
      "description": "Keep only posts of this type.",
      "editor": "select",
      "enum": [
        "self",
        "link",
        "image",
        "video",
        "gallery",
        "poll"
      ],
      "enumTitles": [
        "Text (self)",
        "Link",
        "Image",
        "Video",
        "Gallery",
        "Poll"
      ],
      "title": "Post type",
      "type": "string"
    },
    "postUrls": {
      "default": [],
      "description": "Post URLs, comment URLs, share links or bare post IDs (mode=post).",
      "editor": "stringList",
      "example": [
        "https://www.reddit.com/r/programming/comments/1vqukkf/",
        "1xbw0h8"
      ],
      "prefill": [],
      "title": "Post URLs or IDs",
      "type": "array"
    },
    "postedAfter": {
      "description": "UTC date lower bound (YYYY-MM-DD).",
      "editor": "datepicker",
      "title": "Created on or after",
      "type": "string"
    },
    "postedBefore": {
      "description": "UTC date upper bound (YYYY-MM-DD), inclusive.",
      "editor": "datepicker",
      "title": "Created on or before",
      "type": "string"
    },
    "proxyMode": {
      "default": "none",
      "description": "Direct (no proxy) is the default. Choose datacenter if Reddit blocks your runs. Residential is an explicit last resort and is capped by maxProxyBytesMb.",
      "editor": "select",
      "enum": [
        "none",
        "datacenter",
        "residential"
      ],
      "enumTitles": [
        "Direct / no proxy",
        "Datacenter proxy",
        "Residential proxy (explicit fallback)"
      ],
      "prefill": "none",
      "title": "Connection",
      "type": "string"
    },
    "restrictSubreddits": {
      "default": [],
      "description": "Only keep profile posts/comments made in these subreddits.",
      "editor": "stringList",
      "prefill": [],
      "title": "Restrict profile history to subreddits",
      "type": "array"
    },
    "searchComments": {
      "default": false,
      "description": "Include comment results in keyword search when Reddit's comment tab returns them.",
      "prefill": false,
      "title": "Search comments (mode=search)",
      "type": "boolean"
    },
    "searchCommunities": {
      "default": false,
      "description": "Include subreddit matches in keyword search.",
      "prefill": false,
      "title": "Search communities (mode=search)",
      "type": "boolean"
    },
    "searchPosts": {
      "default": true,
      "description": "Include post results in keyword search.",
      "prefill": true,
      "title": "Search posts (mode=search)",
      "type": "boolean"
    },
    "searchQuery": {
      "default": "",
      "description": "Keyword or phrase to search for (mode=search). Reddit search syntax such as \"exact phrase\", author:name, subreddit:name and -exclude is supported by live search.",
      "editor": "textfield",
      "example": "asyncio",
      "prefill": "",
      "title": "Search query",
      "type": "string"
    },
    "searchUsers": {
      "default": false,
      "description": "Include matching Reddit accounts in keyword search.",
      "prefill": false,
      "title": "Search users (mode=search)",
      "type": "boolean"
    },
    "sections": {
      "default": [
        "overview"
      ],
      "description": "Which history sections to fetch (mode=profile). Allowed values: overview, posts, comments.",
      "editor": "stringList",
      "items": {
        "type": "string"
      },
      "prefill": [
        "posts"
      ],
      "title": "Profile sections",
      "type": "array"
    },
    "sort": {
      "default": "hot",
      "description": "Post/listing sort. Search accepts relevance, hot, top, new or comments; other modes use hot, new, top, rising, controversial or best.",
      "editor": "select",
      "enum": [
        "hot",
        "new",
        "top",
        "rising",
        "controversial",
        "best",
        "relevance",
        "comments"
      ],
      "enumTitles": [
        "Hot",
        "New",
        "Top",
        "Rising",
        "Controversial",
        "Best",
        "Relevance (search)",
        "Most comments (search)"
      ],
      "prefill": "hot",
      "title": "Sort",
      "type": "string"
    },
    "source": {
      "default": "auto",
      "description": "auto uses live Reddit first and the Arctic Shift archive for depth/bulk or as a fallback. archive is faster and cheaper but lags live Reddit by several hours; live never uses archive data.",
      "editor": "select",
      "enum": [
        "auto",
        "live",
        "archive"
      ],
      "enumTitles": [
        "Auto (live + archive fallback)",
        "Live only",
        "Archive only (Arctic Shift)"
      ],
      "prefill": "archive",
      "title": "Data source",
      "type": "string"
    },
    "stateKey": {
      "default": "reddit-mcp-state",
      "description": "Key-value store key prefix used by onlyNew watermarks.",
      "editor": "textfield",
      "prefill": "reddit-mcp-state",
      "title": "Incremental state key",
      "type": "string"
    },
    "subreddits": {
      "default": [
        "programming"
      ],
      "description": "Subreddits to scrape (mode=subreddit). Accepts names, r/ names or URLs.",
      "editor": "stringList",
      "example": [
        "programming",
        "r/Python"
      ],
      "prefill": [
        "programming"
      ],
      "title": "Subreddits",
      "type": "array"
    },
    "timeFilter": {
      "default": "day",
      "description": "Time window for top/controversial sorts and search.",
      "editor": "select",
      "enum": [
        "hour",
        "day",
        "week",
        "month",
        "year",
        "all"
      ],
      "enumTitles": [
        "Past hour",
        "Past day",
        "Past week",
        "Past month",
        "Past year",
        "All time"
      ],
      "prefill": "day",
      "title": "Time filter",
      "type": "string"
    },
    "titleContains": {
      "description": "Keep only posts whose title contains this text.",
      "editor": "textfield",
      "title": "Title contains",
      "type": "string"
    },
    "usernames": {
      "default": [],
      "description": "Reddit usernames to scrape (mode=profile). Accepts names, u/ names or profile URLs.",
      "editor": "stringList",
      "example": [
        "spez"
      ],
      "prefill": [],
      "title": "Usernames",
      "type": "array"
    },
    "withinCommunity": {
      "description": "Limit post/comment search to a single subreddit (name, r/name or URL). Required for archive keyword search.",
      "editor": "textfield",
      "example": "r/technology",
      "title": "Restrict search to one community",
      "type": "string"
    }
  },
  "required": [
    "mode"
  ],
  "schemaVersion": 1,
  "title": "Reddit Multi-Mode 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
redditRecordsstringoptionalDataset containing post, comment, profile or community records (see `recordType`). Every record carries `source` (live/archive), `fetchedAt` and, for archive data, `snapshotFreshness` plus a warning.

Download the published output schema

View complete JSON
{
  "actorOutputSchemaVersion": 1,
  "description": "Reddit posts, comments, profiles and community records with engagement metrics, derived activity and per-record source provenance.",
  "properties": {
    "redditRecords": {
      "description": "Dataset containing post, comment, profile or community records (see `recordType`). Every record carries `source` (live/archive), `fetchedAt` and, for archive data, `snapshotFreshness` plus a warning.",
      "template": "{{links.apiDefaultDatasetUrl}}/items",
      "title": "Reddit records",
      "type": "string"
    }
  },
  "title": "Reddit Multi-Mode Scraper for Posts, Comments & Profiles 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": "Reddit Records",
      "transformation": {
        "fields": [
          "recordType",
          "subreddit_prefixed",
          "title",
          "author",
          "score",
          "commentCount",
          "source",
          "createdAt",
          "permalink"
        ]
      }
    }
  }
}

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

Reddit Multi-Mode Scraper for Posts, Comments & Profiles

Extract public Reddit data without an account, cookie, or API key. Choose a subreddit feed, specific post URLs with their comment trees, a user profile and history, or a keyword search. Every record is JSON with a stable recordType (post, comment, profile, or community), the original dataType, and a source tag so mixed datasets stay easy to audit.

What this actor does

  • Four modes: subreddit (post listings), post (one or more post URLs plus comments), profile (account metadata, posts and comments), and search (posts, comments, communities, and users).
  • Two data sources with provenance: live reads Reddit's public rendered pages, while archive reads the Arctic Shift historical snapshot. auto uses live data first and archive for depth, bulk history, or fallback.
  • Full comment trees: the archive path returns nested replies with depth and parent_id; live mode starts with the visible tree and expands top-level pages up to your cap.
  • Rich post fields: score, upvote ratio, comment count, flair, domain, media URLs, galleries, video metadata, awards, crossposts, NSFW/spoiler/locked flags, and derived engagement metrics.
  • Filters and incremental runs: score, comment count, upvote ratio, date range, post type, text matches, author allow/deny lists, flair, domain, awards, and an optional onlyNew watermark.
  • Empty fields are omitted: records never contain null, empty strings, or empty arrays/objects.

Output per post

  • recordType: "post", dataType: "post", source, sourceDetail, fetchedAt, snapshotFreshness
  • id, post_id, post_name, title, author, author_id, author_meta
  • subreddit, subreddit_prefixed, subreddit_id, subreddit_subscribers, subreddit_type
  • content / body, content_html, content_url, url, permalink, domain, is_self, post_type, media_type
  • score, ups, downs, upvote_ratio, num_comments, commentCount, gilded, total_awards_received, awards[]
  • link_flair, flair colors/classes/richtext, thumbnail_url, images[], gallery_images[], gallery_count
  • video_url, video_duration_seconds, video_width, video_height, video_has_audio, video_bitrate_kbps
  • poll_data, embed metadata, crosspost_parent_id
  • created_utc, created_at, createdAt, edited, edited_at
  • is_nsfw, nsfw, is_spoiler, is_stickied, is_locked, is_archived, is_original_content, is_crosspost
  • derived (ageHours, scorePerHour, commentsPerHour, engagementTotal)
  • warning and degraded when the record came from the archive snapshot

Output per comment

  • recordType: "comment", dataType: "comment", source, sourceDetail, fetchedAt
  • id, comment_id, comment_name, post_id, post_url, post_title, link_id
  • parent_id, parentId, parent_kind, depth, body, body_html
  • author, author_id, author_meta
  • subreddit, subreddit_prefixed, subreddit_id, subreddit_type
  • score, ups, downs, controversiality, gilded, total_awards_received, awards[]
  • is_op, is_stickied, is_locked, collapsed, removed_by_category
  • replies_count, replies, created_utc, created_at, createdAt, edited, edited_at, permalink
  • coverage on the parent post when comment coverage is known
  • warning and degraded for archive records

Output per profile

  • recordType: "profile", dataType: "user_profile", source, fetchedAt
  • id, username, user_id, profile_url, icon_img, snoovatar_img
  • karma (total, post, comment), plus the flat post_karma, comment_karma, total_karma
  • post_count, comment_count, created_utc, created_at, createdAt
  • description, is_gold, is_mod, is_employee, has_verified_email, verified
  • Profile history records are emitted as separate post and comment records.

Output per community

Community records appear when includeSubredditInfo, searchCommunities, or the MCP get_subreddit_info tool is used.

  • recordType: "community", dataType: "community", source, fetchedAt
  • id, subreddit, subreddit_prefixed, subreddit_id, url, title
  • subscribers, active_user_count, created_utc, created_at, createdAt
  • description, public_description, subreddit_type, over18, quarantine
  • rules[] when rules are requested

Input

Field Type Default Description
mode string subreddit subreddit, post, profile, or search. Legacy comments maps to post; posts, profiles, and subreddits are accepted aliases.
source string auto auto, live, or archive. auto prefers live data and uses the archive for depth, history, or fallback.
subreddits array ["programming"] Subreddits for mode=subreddit; names, r/ names, and URLs are accepted.
postUrls array - Post URLs, comment URLs, share links, or bare post IDs for mode=post.
usernames array - Reddit usernames for mode=profile; u/ names and profile URLs are accepted.
searchQuery string - Keyword or phrase for mode=search. Reddit search operators are supported by the live path.
maxItems int 50 Hard cap on all records emitted by the run (1-10,000).
maxPosts int 25 Posts per subreddit, keyword, or profile section (1-5,000).
maxComments int 100 Comments per post, keyword, or profile comment section; 0 disables comment records.
maxDepth int 6 Deepest reply level to emit (0-20).
includeComments bool true Emit comment records in mode=post.
includePost bool true Emit the parent post record before its comments in mode=post.
sort string hot hot, new, top, rising, controversial, best, or search values relevance and comments.
timeFilter string day hour, day, week, month, year, or all.
commentSort string confidence confidence, top, new, controversial, old, or qa.
includeNSFW bool false Include over-18 posts and communities.
includeSubredditInfo bool false Emit one community record per subreddit.
includeSubredditRules bool false Attach rules to community records.
includeProfileInfo bool true Emit the profile record in mode=profile.
sections array ["overview"] Profile history sections: overview, posts, comments.
searchPosts / searchComments / searchCommunities / searchUsers bool posts on Select which result types mode=search returns.
withinCommunity string - Restrict search to one subreddit; required for archive keyword search.
maxCommunities / maxUsers int 10 / 25 Caps for community and user search results.
onlyNew bool false Emit only records newer than the watermark stored under stateKey.
stateKey string reddit-mcp-state Key-value store key prefix for onlyNew watermarks.
failOnEmpty bool true Fail the run with a clear message when no records are found.
proxyMode string none none, datacenter, or residential. Residential is an explicit fallback and is capped by maxProxyBytesMb.
maxProxyBytesMb int 50 Stop the run before paid proxy traffic exceeds this many megabytes.
minScore / maxScore int - Score range for posts and comments.
minPostComments / maxPostComments int - Comment-count range for posts.
minUpvoteRatio number - Minimum post upvote ratio (0-1).
postType string - self, link, image, video, gallery, or poll.
titleContains / contentContains / flairContains / authorFlairContains string - Case-insensitive text matches.
domain string - Link domain contains this text.
authors / excludeAuthors array - Author allow/deny lists.
excludeKeywords array - Drop posts whose title, body, or flair contains any term.
excludeStickied / excludeRemoved / excludeCrossposts / excludeSpoilers / excludeLocked / excludeDeletedAuthor / excludeArchived bool false Exclusion toggles.
onlyWithFlair / onlyOriginalContent bool false Flair and OC filters.
minAwards int - Minimum total awards.
minContentLength / maxContentLength int - Body length range.
postedAfter / postedBefore string - UTC date bounds (YYYY-MM-DD); postedBefore is inclusive.
restrictSubreddits array - Keep profile history only from these subreddits.
keyword string - Keep profile posts/comments containing this phrase.
minCommunitySubscribers / maxCommunitySubscribers int - Community search size filters.
minUserKarma / maxUserKarma int - User search karma filters.
distinguished string - moderator, admin, special, or none.

Example: subreddit listing

{
  "mode": "subreddit",
  "subreddits": ["programming", "r/Python"],
  "sort": "top",
  "timeFilter": "week",
  "maxItems": 100,
  "maxPosts": 50,
  "includeNSFW": false
}

Example: post URLs with comments

{
  "mode": "post",
  "postUrls": [
    "https://www.reddit.com/r/programming/comments/1xbl8y1/",
    "https://www.reddit.com/r/Python/s/example"
  ],
  "maxComments": 250,
  "maxDepth": 6,
  "includePost": true,
  "source": "auto"
}

Example: profile and history

{
  "mode": "profile",
  "usernames": ["spez"],
  "sections": ["overview"],
  "maxPosts": 25,
  "maxComments": 50,
  "postedAfter": "2026-01-01"
}
{
  "mode": "search",
  "searchQuery": "asyncio",
  "withinCommunity": "python",
  "searchPosts": true,
  "searchComments": true,
  "sort": "relevance",
  "timeFilter": "month",
  "maxItems": 50
}

MCP server (Standby)

The actor runs a native Streamable HTTP MCP server at /mcp when started in Standby mode. It exposes five typed tools that reuse the same scrapers as the batch modes:

Tool What it returns
search_reddit Posts, comments, communities, or users matching a query, with optional subreddit scope, sort, time window, and NSFW toggle.
get_subreddit_posts A subreddit's posts with sort, time window, NSFW toggle, and item cap.
get_post_comments One post plus its flat, depth-tagged comments, with max_comments, max_depth, comment sort, and an optional parent-post record.
get_user_profile Profile metadata plus recent posts/comments for one user.
get_subreddit_info Community metadata, optional rules, subscriber count, and description.

MCP responses include items, count, source, and degraded; archive-backed responses also include a freshness warning. Use the Actor's Standby URL followed by /mcp:

{
  "mcpServers": {
    "reddit": {
      "type": "streamable-http",
      "url": "https://<your-actor-standby-host>/mcp",
      "headers": {
        "Authorization": "Bearer <your-apify-token>"
      }
    }
  }
}

Use cases

  • Community monitoring: follow new and top posts in a set of subreddits on a schedule with onlyNew.
  • Thread research: export a full comment tree for sentiment, topic, or quote analysis.
  • Creator and moderator analysis: profile karma, posting history, and subreddit participation.
  • Trend discovery: keyword search across Reddit posts and comments, optionally scoped to one community.
  • AI and RAG pipelines: consume flat JSON records or call the MCP tools from an agent.
  • Moderation and compliance review: filter by flair, domain, score, date, NSFW, and author.

Data source, freshness, and cost

Live records come from Reddit's public rendered pages. The archive path uses the Arctic Shift historical snapshot, which typically lags live Reddit by several hours and can have fewer comments or older scores. Archive records are marked source: "archive", degraded: true, and include a warning; the snapshotFreshness field distinguishes them from live data.

The actor defaults to 1 GB of memory; Apify bills the run by allocated memory and any proxy traffic. Browser requests block images, fonts, and media to keep traffic and cost down. No proxy is used by default; datacenter is available when Reddit blocks a run, and residential is an explicit last resort. maxProxyBytesMb stops the run when the configured proxy traffic ceiling is reached.

FAQ

Do I need a Reddit account or API key?

No. The actor reads public pages and a public archive, and no cookies, login, or API key are required.

Why do live and archive records disagree on score or comment count?

The archive is a historical crawl. Live pages reflect the current score, upvote ratio, and comment count; archive records can be several hours stale and are marked degraded.

Why are some comments missing from a very large thread?

Live mode starts with the comments Reddit renders and expands top-level pages up to maxComments; replies can be limited by Reddit's pagination. Use source: "auto" or "archive" for deeper trees, and check the parent post's coverage fields.

Why did my search return fewer results than expected?

Reddit limits search result pages and caps many queries. The actor follows the available result pages up to maxItems; use a narrower withinCommunity, a different sort, or a broader time window.

What does onlyNew do?

It stores a watermark in the key-value store under stateKey and emits only records newer than the previous run. Archive watermarks keep a small overlap so a late-indexed comment is not skipped.

Does the actor work for private or quarantined communities?

No. Only public, cookieless content is supported. NSFW posts can be included with includeNSFW, but login-gated or quarantined communities are out of scope.

How do I get community rules?

Set includeSubredditInfo and includeSubredditRules in mode=subreddit, or call the get_subreddit_info MCP tool with include_rules: true.

How do I keep runs cheap?

Use source: "archive" when you only need historical posts or deep trees, keep maxItems and maxComments small, and leave proxyMode at none. The actor defaults to 1 GB of memory and does not download images, fonts, or media. If you choose a proxy, maxProxyBytesMb stops the run when its traffic ceiling is reached.

Is this affiliated with Reddit?

No. This is a third-party tool that reads public Reddit pages and a public archive. Respect Reddit's terms and applicable law when using the data.

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 ilFk20SGtzrsuw9Db. Documentation is regenerated from the default published build; private drafts are not included.