{
  "data": {
    "id": "YDxWZQ5NFS5bB9C71",
    "actId": "dT3hCTn5EGjdCyIWb",
    "userId": "tnBVjt3CXmcUrEE3L",
    "startedAt": "2026-11-13T18:16:17.208Z",
    "finishedAt": "2026-11-13T18:16:26.369Z",
    "status": "SUCCEEDED",
    "meta": {
      "origin": "CI"
    },
    "stats": {
      "durationMillis": 9080,
      "runTimeSecs": 9.08,
      "computeUnits": 0.010088888888888889,
      "imageSizeBytes": 302873600
    },
    "options": {
      "useCache": true,
      "betaPackages": false,
      "memoryMbytes": 4096,
      "diskMbytes": 8192
    },
    "createdByOrganizationMemberUserId": "F2Aeb3gE2syjqz9xC",
    "exitCode": 0,
    "inputSchema": "{\n  \"title\": \"Reddit Profile Scraper Input\",\n  \"type\": \"object\",\n  \"schemaVersion\": 1,\n  \"properties\": {\n    \"usernames\": {\n      \"title\": \"Reddit Usernames\",\n      \"type\": \"array\",\n      \"description\": \"List of Reddit usernames to scrape. Accepts bare names (spez), u/ prefixed (u/spez) or profile URLs.\",\n      \"editor\": \"stringList\",\n      \"example\": [\n        \"spez\",\n        \"u/example_user\",\n        \"https://www.reddit.com/user/another_user/\"\n      ],\n      \"prefill\": [\n        \"spez\"\n      ],\n      \"minItems\": 1\n    },\n    \"includeProfileInfo\": {\n      \"title\": \"Include profile info record\",\n      \"type\": \"boolean\",\n      \"description\": \"Emit a user_profile record with archive-wide post/comment/total karma, archived post/comment counts, first/last activity dates, and any profile fields the public profile page exposes.\",\n      \"default\": true,\n      \"prefill\": true\n    },\n    \"sections\": {\n      \"title\": \"Profile sections\",\n      \"type\": \"array\",\n      \"description\": \"Which parts of the user's history to scrape. Overview returns posts and comments merged newest-first (or by the selected sort).\",\n      \"editor\": \"select\",\n      \"items\": {\n        \"type\": \"string\",\n        \"enum\": [\n          \"overview\",\n          \"posts\",\n          \"comments\"\n        ],\n        \"enumTitles\": [\n          \"Overview (posts + comments)\",\n          \"Posts\",\n          \"Comments\"\n        ]\n      },\n      \"prefill\": [\n        \"posts\"\n      ],\n      \"default\": [\n        \"posts\"\n      ],\n      \"example\": [\n        \"posts\",\n        \"comments\"\n      ]\n    },\n    \"maxPosts\": {\n      \"title\": \"Maximum posts per user\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum number of matching posts to emit per user.\",\n      \"minimum\": 1,\n      \"maximum\": 5000,\n      \"default\": 100,\n      \"prefill\": 3,\n      \"example\": 100\n    },\n    \"maxComments\": {\n      \"title\": \"Maximum comments per user\",\n      \"type\": \"integer\",\n      \"description\": \"Maximum number of matching comments to emit per user.\",\n      \"minimum\": 1,\n      \"maximum\": 5000,\n      \"default\": 100,\n      \"prefill\": 3,\n      \"example\": 100\n    },\n    \"sort\": {\n      \"title\": \"Sort history by\",\n      \"type\": \"string\",\n      \"description\": \"Newest or oldest first by creation time. Top ranks the fetched items by score (the archive itself only sorts by date, so this is a ranking within the most recent items up to the cap).\",\n      \"enum\": [\n        \"newest\",\n        \"oldest\",\n        \"top\"\n      ],\n      \"enumTitles\": [\n        \"Newest first\",\n        \"Oldest first\",\n        \"Top scored (within fetched items)\"\n      ],\n      \"default\": \"newest\",\n      \"prefill\": \"newest\"\n    },\n    \"timeFilter\": {\n      \"title\": \"Created within the last\",\n      \"type\": \"string\",\n      \"description\": \"Only keep posts/comments created within this rolling window (UTC). Applied as a date window for every sort; an explicit 'postedAfter' later than the window wins.\",\n      \"enum\": [\n        \"hour\",\n        \"day\",\n        \"week\",\n        \"month\",\n        \"year\",\n        \"all\"\n      ],\n      \"default\": \"all\",\n      \"prefill\": \"all\",\n      \"enumTitles\": [\n        \"Past hour\",\n        \"Past day\",\n        \"Past week\",\n        \"Past month\",\n        \"Past year\",\n        \"All time\"\n      ]\n    },\n    \"includeNSFW\": {\n      \"title\": \"Include NSFW (18+) content\",\n      \"type\": \"boolean\",\n      \"description\": \"Include NSFW posts in the user's history.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"onlyWithFlair\": {\n      \"title\": \"Only posts with flair\",\n      \"type\": \"boolean\",\n      \"description\": \"Keep only posts that have a link flair set. Has no effect on comments (comments don't carry link flair).\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"subreddits\": {\n      \"title\": \"Restrict to subreddits\",\n      \"type\": \"array\",\n      \"description\": \"Only keep posts/comments made in these subreddits (case-insensitive). Accepts bare names (python), r/ prefixed (r/python), or subreddit URLs. Leave empty to include every subreddit in the user's history.\",\n      \"editor\": \"stringList\",\n      \"example\": [\n        \"AskReddit\",\n        \"r/technology\"\n      ]\n    },\n    \"keyword\": {\n      \"title\": \"Keyword filter\",\n      \"type\": \"string\",\n      \"description\": \"Only keep posts/comments whose title, self-text or comment body contains this text (case-insensitive substring match). Leave empty to disable.\",\n      \"editor\": \"textfield\",\n      \"example\": \"climate\"\n    },\n    \"titleContains\": {\n      \"title\": \"Title contains keyword\",\n      \"type\": \"string\",\n      \"description\": \"Only keep posts whose title contains this text (case-insensitive substring match). Has no effect on comments. Leave empty to keep all titles.\",\n      \"editor\": \"textfield\",\n      \"example\": \"launch\"\n    },\n    \"contentContains\": {\n      \"title\": \"Post text contains keyword\",\n      \"type\": \"string\",\n      \"description\": \"Only keep self (text) posts whose body contains this text (case-insensitive substring match). Link/image/video posts have no body text and are excluded when this is set. Has no effect on comments. Leave empty to keep all posts.\",\n      \"editor\": \"textfield\",\n      \"example\": \"tutorial\"\n    },\n    \"flairContains\": {\n      \"title\": \"Flair contains keyword\",\n      \"type\": \"string\",\n      \"description\": \"Only keep posts whose link flair text contains this text (case-insensitive substring match). Has no effect on comments. Leave empty to keep all flairs.\",\n      \"editor\": \"textfield\",\n      \"example\": \"Discussion\"\n    },\n    \"authorFlairContains\": {\n      \"title\": \"Author flair contains keyword\",\n      \"type\": \"string\",\n      \"description\": \"Only keep posts whose author flair text contains this text (case-insensitive substring match). Has no effect on comments. Leave empty to keep all.\",\n      \"editor\": \"textfield\",\n      \"example\": \"Moderator\"\n    },\n    \"domain\": {\n      \"title\": \"Domain contains\",\n      \"type\": \"string\",\n      \"description\": \"Only keep posts whose link domain contains this text (case-insensitive, e.g. 'youtube.com' or 'self.python'). Has no effect on comments. Leave empty to keep all domains.\",\n      \"editor\": \"textfield\",\n      \"example\": \"youtube.com\"\n    },\n    \"distinguished\": {\n      \"title\": \"Distinguished (official) posts only\",\n      \"type\": \"string\",\n      \"description\": \"Only keep posts distinguished by Reddit as moderator, admin or special (e.g. Reddit-team) posts, or only regular (non-distinguished) posts. Has no effect on comments. Leave unset to keep all posts.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"moderator\",\n        \"admin\",\n        \"special\",\n        \"none\"\n      ],\n      \"enumTitles\": [\n        \"Moderator posts only\",\n        \"Admin posts only\",\n        \"Special (official) posts only\",\n        \"Regular posts only (exclude all distinguished)\"\n      ]\n    },\n    \"minAwards\": {\n      \"title\": \"Minimum awards received\",\n      \"type\": \"integer\",\n      \"description\": \"Only keep posts with at least this many total awards. Has no effect on comments. Leave unset to keep all posts.\",\n      \"minimum\": 0,\n      \"maximum\": 1000000,\n      \"example\": 1\n    },\n    \"onlyOriginalContent\": {\n      \"title\": \"Only original content (OC) posts\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, only posts the author tagged as original content are kept. Has no effect on comments.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"excludeArchived\": {\n      \"title\": \"Exclude archived posts\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, posts that Reddit has archived (locked from further voting/commenting after 6 months) are dropped from the results. Has no effect on comments.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"excludeKeywords\": {\n      \"title\": \"Exclude keywords\",\n      \"type\": \"array\",\n      \"description\": \"Drop posts whose title, self-text body or flair contains any of these keywords or phrases (case-insensitive substring match) — useful for filtering out megathreads, giveaways or spam boilerplate. Has no effect on comments. Leave empty to keep all posts.\",\n      \"editor\": \"stringList\",\n      \"example\": [\n        \"megathread\"\n      ]\n    },\n    \"minContentLength\": {\n      \"title\": \"Minimum post body length (characters)\",\n      \"type\": \"integer\",\n      \"description\": \"Only keep self (text) posts whose body is at least this many characters long. Link/image/video posts have no body and are excluded when this is set. Has no effect on comments. Leave unset to keep all lengths.\",\n      \"minimum\": 0,\n      \"maximum\": 1000000,\n      \"example\": 100\n    },\n    \"maxContentLength\": {\n      \"title\": \"Maximum post body length (characters)\",\n      \"type\": \"integer\",\n      \"description\": \"Only keep self (text) posts whose body is at most this many characters long. Has no effect on comments. Leave unset to keep all lengths.\",\n      \"minimum\": 0,\n      \"maximum\": 1000000,\n      \"example\": 5000\n    },\n    \"postType\": {\n      \"title\": \"Only posts of this type\",\n      \"type\": \"string\",\n      \"description\": \"Keep only posts of the selected content type. Leave unset to keep all types. Has no effect on comments.\",\n      \"editor\": \"select\",\n      \"enum\": [\n        \"self\",\n        \"link\",\n        \"image\",\n        \"video\",\n        \"gallery\",\n        \"poll\"\n      ],\n      \"enumTitles\": [\n        \"Text (self post)\",\n        \"Link\",\n        \"Image\",\n        \"Video\",\n        \"Gallery\",\n        \"Poll\"\n      ]\n    },\n    \"minScore\": {\n      \"title\": \"Minimum score (upvotes minus downvotes)\",\n      \"type\": \"integer\",\n      \"description\": \"Only keep posts/comments with a score at or above this value. Leave unset to keep all scores.\",\n      \"minimum\": -1000000,\n      \"maximum\": 1000000,\n      \"example\": 10\n    },\n    \"maxScore\": {\n      \"title\": \"Maximum score (upvotes minus downvotes)\",\n      \"type\": \"integer\",\n      \"description\": \"Only keep posts/comments with a score at or below this value. Useful for finding overlooked/low-visibility items. Leave unset to keep all scores.\",\n      \"minimum\": -1000000,\n      \"maximum\": 1000000,\n      \"example\": 1000\n    },\n    \"minPostComments\": {\n      \"title\": \"Minimum comments on the post\",\n      \"type\": \"integer\",\n      \"description\": \"Only keep posts that have at least this many comments (the post's own comment count — not to be confused with 'Maximum comments per user' above, which caps how many comment records are scraped). Has no effect on comments.\",\n      \"minimum\": 0,\n      \"maximum\": 1000000,\n      \"example\": 5\n    },\n    \"maxPostComments\": {\n      \"title\": \"Maximum comments on the post\",\n      \"type\": \"integer\",\n      \"description\": \"Only keep posts that have at most this many comments. Useful for finding under-discussed posts. Has no effect on comments.\",\n      \"minimum\": 0,\n      \"maximum\": 1000000,\n      \"example\": 500\n    },\n    \"minUpvoteRatio\": {\n      \"title\": \"Minimum upvote ratio\",\n      \"type\": \"number\",\n      \"description\": \"Only keep posts whose upvote ratio (fraction of votes that are upvotes, 0-1) is at or above this value. Useful for filtering out controversial/divisive posts. Has no effect on comments.\",\n      \"minimum\": 0,\n      \"maximum\": 1,\n      \"example\": 0.8\n    },\n    \"excludeStickied\": {\n      \"title\": \"Exclude stickied/pinned posts\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, posts pinned/stickied in their community are dropped from the results.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"excludeRemoved\": {\n      \"title\": \"Exclude removed/deleted posts\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, posts removed by a moderator, Reddit, or deleted by their author (marker: removed_by_category) are dropped from the results.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"excludeCrossposts\": {\n      \"title\": \"Exclude crossposts\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, posts that are crossposts from another subreddit are dropped, keeping only the user's original submissions.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"excludeSpoilers\": {\n      \"title\": \"Exclude spoiler-tagged posts\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, posts marked as a spoiler by their author are dropped from the results.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"excludeLocked\": {\n      \"title\": \"Exclude locked posts\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, posts with comments locked by a moderator are dropped from the results.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"excludeDeletedAuthor\": {\n      \"title\": \"Exclude posts with a deleted author\",\n      \"type\": \"boolean\",\n      \"description\": \"When enabled, posts whose author account was deleted (shown as [deleted]/[removed]) are dropped from the results.\",\n      \"default\": false,\n      \"prefill\": false\n    },\n    \"postedAfter\": {\n      \"title\": \"Items created on or after (YYYY-MM-DD)\",\n      \"type\": \"string\",\n      \"description\": \"Only keep items created on or after this date (UTC).\",\n      \"editor\": \"datepicker\",\n      \"example\": \"2025-01-01\"\n    },\n    \"postedBefore\": {\n      \"title\": \"Items created on or before (YYYY-MM-DD)\",\n      \"type\": \"string\",\n      \"description\": \"Only keep items created on or before this date (interpreted as the end of that day, UTC).\",\n      \"editor\": \"datepicker\",\n      \"example\": \"2025-12-31\"\n    }\n  }\n}",
    "readme": "# Reddit User Karma & Post History Extractor\n\nGive this actor a list of Reddit usernames and it returns each account's public profile summary — post karma, comment karma, total karma, archived post/comment counts, and first/last activity dates — together with their post and comment history, filtered by subreddit, keyword, score, date window, post type, flair and 20+ other criteria. No Reddit API key, login or proxy setup is required.\n\n## Data source\n\nReddit's anonymous `.json` endpoints now return HTTP 403, and the www HTML is JavaScript-challenged from datacenter IPs. The actor therefore reads the public Reddit archive through **Arctic Shift** (`arctic-shift.photon-reddit.com`), which mirrors Reddit posts, comments and account aggregates over a no-key HTTP API.\n\n- **Primary:** Arctic Shift `/api/posts/search`, `/api/comments/search`, `/api/users/search`, `/api/posts/ids`, `/api/comments/ids`.\n- **Fallback:** Reddit's public Atom feed (`/user/<name>/.rss`) and profile HTML where reachable. Feed IDs are enriched through the archive ID endpoints when available, which restores scores for recent items.\n- Reddit `.json` is never called.\n\n### Freshness and fallback limits\n\n- Arctic Shift archives an item shortly after it is posted. Its `score` and `num_comments` can read 0 or 1 until the archive re-crawls the item (~36 hours). The `score_captured_at` field on each post/comment shows when the archived score was captured.\n- Account karma and archived post/comment counts come from Arctic's `/api/users/search` aggregate. That aggregate is refreshed infrequently; each profile record carries `post_stats_updated_at`, `comment_stats_updated_at` and `karma_updated_at` so you can see how current the numbers are.\n- The Atom fallback returns at most the most recent ~100 items. The feed itself has no score or karma values; scores are restored only when the archive ID lookup succeeds. Reddit rate-limits or blocks the feed from some networks (429/503); the actor retries with backoff (honouring `Retry-After`/`X-RateLimit-Reset`) before giving up. It is best effort, not a full-history replacement.\n- Profile HTML is often a JavaScript challenge or WAF block. When it is reachable, it fills account creation date, avatar, bio and account flags; otherwise those fields are omitted.\n\n## What this actor does\n\n- **Profile summary** — archive-wide post/comment/total karma, archived post/comment counts, first/last post, comment and overall activity dates, plus account flags/avatar/bio when the profile page is reachable\n- **Post and comment history** — newest first, oldest first, or top-scored within the fetched window\n- **Overview mode** — posts and comments merged into one chronological feed\n- **Date windows and filters** — subreddit, keyword, score range, post type, flair, domain, awards, content length, comment counts, upvote ratio, and exclusion toggles for stickied/removed/crossposted/spoiler/locked/archived posts\n- **Flexible username input** — bare usernames, `u/name`, profile URLs, or comma-separated names\n- **Pagination** — walks the archive by creation-time cursor until the requested caps or source exhaustion\n- **Legacy inputs** — old saved tasks using `username`, `section`, `sortBy`, `maxPost`, `includeComments`, `minPostScore`, `excludeNsfwPosts`, `maxPostAgeDays`, `subreddit` or `keywords` keep working (mapped in code)\n- Empty fields are omitted from every record — no `null`, `\"\"`, `[]` or `{}` values\n\n## Output: profile record\n\nOne record per username (`dataType: \"user_profile\"`) when \"Include profile info record\" is on:\n\n- `username`, `user_id`, `profile_url`\n- `post_karma`, `comment_karma`, `total_karma`\n- `archived_posts`, `archived_comments` — archive-wide counts, not just the rows in this dataset\n- `first_post_at`, `last_post_at`, `first_comment_at`, `last_comment_at`, `first_activity_at`, `last_activity_at` (+ matching `*_utc` epochs)\n- `post_stats_updated_at`, `comment_stats_updated_at`, `karma_updated_at`\n- `created_at` / `created_utc` — account creation, when the profile page exposes it\n- `is_gold` (Reddit Premium), `is_mod`, `is_employee`, `has_verified_email`, `verified`, `accept_followers`, `hide_from_robots` — when exposed by the profile page\n- `icon_img` (avatar), `snoovatar_img`, `snoovatar_size`, `user_subreddit` (bio, banner, display name, subscribers, NSFW flag, type, URL)\n- `crawled_at`, `source`\n\n## Output: post record\n\nOne record per post (`dataType: \"post\"`) returned by the `posts` or `overview` sections:\n\n- `subreddit`, `subreddit_prefixed`, `subreddit_id`, `subreddit_subscribers`, `subreddit_type`\n- `post_id`, `post_name`, `title`\n- `author`, `author_meta` — `{username, id, flair, flair_background_color, flair_text_color, flair_css_class, flair_richtext, flair_template_id, flair_type, is_premium, is_blocked, has_patreon_flair}`\n- `content`, `content_html` — self-post body\n- `content_url`, `url`, `permalink`, `url_overridden_by_dest`, `domain`\n- `post_hint`, `is_self`, `post_type`, `media_type`\n- `score`, `ups`, `downs`, `upvote_ratio`, `num_comments`, `num_crossposts`, `num_duplicates`\n- `link_flair`, `link_flair_background_color`, `link_flair_text_color`, `link_flair_css_class`, `link_flair_template_id`, `link_flair_type`, `link_flair_richtext`\n- `thumbnail_url`, `thumbnail_width`, `thumbnail_height`\n- `created_utc`, `created_at`, `edited`, `edited_at`\n- `is_stickied`, `is_locked`, `is_archived`, `is_pinned`, `is_nsfw`, `is_spoiler`, `is_original_content`, `is_crosspost`, `crosspost_parent_id`\n- `is_crosspostable`, `is_meta`, `is_reddit_media_domain`, `is_robot_indexable`, `is_created_from_ads_ui`\n- `allow_live_comments`, `contest_mode`, `hide_score`, `content_categories`, `media_only`, `quarantine`, `suggested_sort`, `no_follow`, `send_replies`\n- `gilded`, `total_awards_received`, `awards` — `[{name, count, coin_price, icon_url}]`\n- `removed_by_category`, `distinguished`, `hidden`\n- `has_media`, `images`, `gallery_images`, `gallery_count`\n- `video_url`, `video_duration_seconds`, `video_width`, `video_height`, `video_has_audio`, `video_bitrate_kbps`\n- `poll_data` — poll options, vote counts and end time\n- `embed_provider`, `embed_type`, `embed_title`, `embed_author_name`, `embed_thumbnail_url`, `embed_html`, `embed_width`, `embed_height`\n- `search_term` — the keyword filter that matched, when set\n- `score_captured_at` — when the archived score was captured\n- `crawled_at`, `source` — `arctic_shift`, `arctic_ids`, `rss` or `username_only`\n\n## Output: comment record\n\nOne record per comment (`dataType: \"comment\"`) returned by the `comments` or `overview` sections:\n\n- `post_id`, `post_url`, `post_title`, `post_author`, `link_id`\n- `comment_id`, `comment_name`\n- `author`, `author_meta`\n- `body`, `body_html`\n- `score`, `ups`, `downs`, `score_hidden`, `controversiality`\n- `subreddit`, `subreddit_prefixed`, `subreddit_id`, `subreddit_type`\n- `created_utc`, `created_at`, `edited`, `edited_at`\n- `depth`, `parent_id`, `parent_kind`, `is_op`, `comment_type`\n- `is_stickied`, `is_locked`, `distinguished`, `is_nsfw`, `collapsed`, `collapsed_reason`, `collapsed_reason_code`, `collapsed_because_crowd_control`\n- `can_gild`, `no_follow`, `send_replies`, `unrepliable_reason`\n- `gilded`, `total_awards_received`, `awards`\n- `removed_by_category`, `permalink`\n- `search_term` — the keyword filter that matched, when set\n- `score_captured_at`\n- `crawled_at`, `source`\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `usernames` | array | – | Usernames to scrape — bare (`spez`), `u/`-prefixed, profile URLs, or comma-separated names |\n| `includeProfileInfo` | boolean | `true` | Emit the profile summary record |\n| `sections` | array | `[\"posts\"]` | `overview` (posts + comments), `posts`, `comments` |\n| `maxPosts` | integer | `100` | Max matching posts per user (1–5,000) |\n| `maxComments` | integer | `100` | Max matching comments per user (1–5,000) |\n| `sort` | select | `newest` | `newest`, `oldest`, or `top` (score-ranked within the fetched items) |\n| `timeFilter` | select | `all` | Created within the past hour/day/week/month/year |\n| `includeNSFW` | boolean | `false` | Include 18+ posts and comments on 18+ posts |\n| `onlyWithFlair` | boolean | `false` | Keep only posts that have a link flair |\n| `subreddits` | array | – | Restrict to posts/comments made in these subreddits |\n| `keyword` | string | – | Keep only posts/comments whose title, self-text or body contains this text |\n| `titleContains` | string | – | Keep only posts whose title contains this text |\n| `contentContains` | string | – | Keep only self posts whose body contains this text |\n| `flairContains` | string | – | Keep only posts whose link flair contains this text |\n| `authorFlairContains` | string | – | Keep only posts whose author flair contains this text |\n| `domain` | string | – | Keep only posts whose link domain contains this text, e.g. `youtube.com` |\n| `distinguished` | select | – | Only `moderator`, `admin`, `special`, or `none` (regular) posts |\n| `postType` | select | – | Only `self`, `link`, `image`, `video`, `gallery` or `poll` posts |\n| `minScore` / `maxScore` | integer | – | Keep only posts/comments with a score in this range |\n| `minPostComments` / `maxPostComments` | integer | – | Keep only posts whose own comment count is in this range |\n| `minUpvoteRatio` | number | – | Keep only posts with an upvote ratio at or above this value (0–1) |\n| `minAwards` | integer | – | Keep only posts with at least this many total awards |\n| `minContentLength` / `maxContentLength` | integer | – | Keep only self posts whose body length (characters) is in this range |\n| `onlyOriginalContent` | boolean | `false` | Keep only posts tagged as original content |\n| `excludeStickied` | boolean | `false` | Drop stickied/pinned posts |\n| `excludeRemoved` | boolean | `false` | Drop removed/deleted posts |\n| `excludeCrossposts` | boolean | `false` | Drop crossposted posts |\n| `excludeSpoilers` | boolean | `false` | Drop spoiler-tagged posts |\n| `excludeLocked` | boolean | `false` | Drop posts with comments locked by a moderator |\n| `excludeArchived` | boolean | `false` | Drop archived posts |\n| `excludeDeletedAuthor` | boolean | `false` | Drop posts whose author account was deleted |\n| `excludeKeywords` | array | – | Drop posts whose title/body/flair contains any of these terms |\n| `postedAfter` / `postedBefore` | date | – | Keep only items created within this date range (UTC) |\n\n### Example: profile summary and recent overview\n\n```json\n{\n  \"usernames\": [\"spez\"],\n  \"includeProfileInfo\": true,\n  \"sections\": [\"overview\"],\n  \"maxPosts\": 50,\n  \"maxComments\": 50\n}\n```\n\n### Example: recent posts in selected subreddits\n\n```json\n{\n  \"usernames\": [\"u/example_user\"],\n  \"sections\": [\"posts\"],\n  \"sort\": \"newest\",\n  \"maxPosts\": 200,\n  \"subreddits\": [\"pics\", \"AskReddit\"],\n  \"keyword\": \"photo\",\n  \"excludeStickied\": true\n}\n```\n\n### Example: high-scoring comments from the past year\n\n```json\n{\n  \"usernames\": [\"spez\"],\n  \"includeProfileInfo\": false,\n  \"sections\": [\"comments\"],\n  \"timeFilter\": \"year\",\n  \"maxComments\": 500,\n  \"minScore\": 50\n}\n```\n\n## Use cases\n\n- **User research** — analyze an account's posting patterns, engagement and karma\n- **Account vetting** — check activity dates, karma and history before trusting a recommendation or partnership\n- **Content discovery** — pull a creator's or influencer's posts by subreddit, keyword or score\n- **Moderation research** — audit a user's post history across specific communities\n- **Behavioral and social research** — bulk-export public user history for academic or market research\n- **Profile monitoring** — track a user's public activity over time on a schedule\n\n## FAQ\n\n**Do I need a Reddit API key or account login?**\nNo — the actor reads the public Reddit archive and public profile surfaces without credentials.\n\n**Do I need to configure a proxy?**\nNo — there is no proxy setting to configure.\n\n**Why do some scores read 0 or 1?**\nArctic Shift archives an item at posting time and updates score/comment counts on a later crawl (~36 hours). Check `score_captured_at`; the item's score becomes accurate after that re-crawl.\n\n**Why are karma totals different from the live profile?**\nArctic's account aggregate is refreshed infrequently and may lag the live profile. `karma_updated_at` shows the aggregate date. The actor never invents a fresher number.\n\n**What happens when the archive is rate-limited?**\nThe actor retries with backoff (and a smaller page size) and, if the search still fails, falls back to the public Atom feed (most recent ~100 items; scores only where the archive ID lookup succeeds). The run status message says which source was used.\n\n**Does it include private activity like upvotes or saved posts?**\nNo — only public posts and comments are available. Voting history, saved items and hidden posts are private to the account owner.\n\n**What happens for suspended or nonexistent usernames?**\nThe run completes and reports that no records were found for that username.\n\n**Is history capped?**\nThe actor pages through the archive by creation-time cursor until `maxPosts`/`maxComments` or source exhaustion. Reddit's Atom fallback is capped at the most recent ~100 items by Reddit itself.\n\n**Can I filter to a date range?**\nYes — use `postedAfter` / `postedBefore` (UTC dates) or `timeFilter`. The window is passed to the archive, so pagination stops at the boundary.\n\n**Is this actor affiliated with Reddit?**\nNo — this is an independent, third-party actor reading public Reddit archive data. It is not built, endorsed or maintained by Reddit, Inc.\n",
    "actorDefinition": {
      "actorSpecification": 1,
      "name": "reddit-user-karma-and-post-history-extractor",
      "title": "Reddit User Karma & Post History Extractor",
      "description": "Look up Reddit accounts by username for archive-wide post/comment/total karma, archived post and comment counts, first/last activity dates, and their public post and comment history with 30+ filters. No API key, login or proxy setup required.",
      "version": "2.0",
      "buildTag": "latest",
      "dockerfile": "./Dockerfile",
      "readme": "# Reddit User Karma & Post History Extractor\n\nGive this actor a list of Reddit usernames and it returns each account's public profile summary — post karma, comment karma, total karma, archived post/comment counts, and first/last activity dates — together with their post and comment history, filtered by subreddit, keyword, score, date window, post type, flair and 20+ other criteria. No Reddit API key, login or proxy setup is required.\n\n## Data source\n\nReddit's anonymous `.json` endpoints now return HTTP 403, and the www HTML is JavaScript-challenged from datacenter IPs. The actor therefore reads the public Reddit archive through **Arctic Shift** (`arctic-shift.photon-reddit.com`), which mirrors Reddit posts, comments and account aggregates over a no-key HTTP API.\n\n- **Primary:** Arctic Shift `/api/posts/search`, `/api/comments/search`, `/api/users/search`, `/api/posts/ids`, `/api/comments/ids`.\n- **Fallback:** Reddit's public Atom feed (`/user/<name>/.rss`) and profile HTML where reachable. Feed IDs are enriched through the archive ID endpoints when available, which restores scores for recent items.\n- Reddit `.json` is never called.\n\n### Freshness and fallback limits\n\n- Arctic Shift archives an item shortly after it is posted. Its `score` and `num_comments` can read 0 or 1 until the archive re-crawls the item (~36 hours). The `score_captured_at` field on each post/comment shows when the archived score was captured.\n- Account karma and archived post/comment counts come from Arctic's `/api/users/search` aggregate. That aggregate is refreshed infrequently; each profile record carries `post_stats_updated_at`, `comment_stats_updated_at` and `karma_updated_at` so you can see how current the numbers are.\n- The Atom fallback returns at most the most recent ~100 items. The feed itself has no score or karma values; scores are restored only when the archive ID lookup succeeds. Reddit rate-limits or blocks the feed from some networks (429/503); the actor retries with backoff (honouring `Retry-After`/`X-RateLimit-Reset`) before giving up. It is best effort, not a full-history replacement.\n- Profile HTML is often a JavaScript challenge or WAF block. When it is reachable, it fills account creation date, avatar, bio and account flags; otherwise those fields are omitted.\n\n## What this actor does\n\n- **Profile summary** — archive-wide post/comment/total karma, archived post/comment counts, first/last post, comment and overall activity dates, plus account flags/avatar/bio when the profile page is reachable\n- **Post and comment history** — newest first, oldest first, or top-scored within the fetched window\n- **Overview mode** — posts and comments merged into one chronological feed\n- **Date windows and filters** — subreddit, keyword, score range, post type, flair, domain, awards, content length, comment counts, upvote ratio, and exclusion toggles for stickied/removed/crossposted/spoiler/locked/archived posts\n- **Flexible username input** — bare usernames, `u/name`, profile URLs, or comma-separated names\n- **Pagination** — walks the archive by creation-time cursor until the requested caps or source exhaustion\n- **Legacy inputs** — old saved tasks using `username`, `section`, `sortBy`, `maxPost`, `includeComments`, `minPostScore`, `excludeNsfwPosts`, `maxPostAgeDays`, `subreddit` or `keywords` keep working (mapped in code)\n- Empty fields are omitted from every record — no `null`, `\"\"`, `[]` or `{}` values\n\n## Output: profile record\n\nOne record per username (`dataType: \"user_profile\"`) when \"Include profile info record\" is on:\n\n- `username`, `user_id`, `profile_url`\n- `post_karma`, `comment_karma`, `total_karma`\n- `archived_posts`, `archived_comments` — archive-wide counts, not just the rows in this dataset\n- `first_post_at`, `last_post_at`, `first_comment_at`, `last_comment_at`, `first_activity_at`, `last_activity_at` (+ matching `*_utc` epochs)\n- `post_stats_updated_at`, `comment_stats_updated_at`, `karma_updated_at`\n- `created_at` / `created_utc` — account creation, when the profile page exposes it\n- `is_gold` (Reddit Premium), `is_mod`, `is_employee`, `has_verified_email`, `verified`, `accept_followers`, `hide_from_robots` — when exposed by the profile page\n- `icon_img` (avatar), `snoovatar_img`, `snoovatar_size`, `user_subreddit` (bio, banner, display name, subscribers, NSFW flag, type, URL)\n- `crawled_at`, `source`\n\n## Output: post record\n\nOne record per post (`dataType: \"post\"`) returned by the `posts` or `overview` sections:\n\n- `subreddit`, `subreddit_prefixed`, `subreddit_id`, `subreddit_subscribers`, `subreddit_type`\n- `post_id`, `post_name`, `title`\n- `author`, `author_meta` — `{username, id, flair, flair_background_color, flair_text_color, flair_css_class, flair_richtext, flair_template_id, flair_type, is_premium, is_blocked, has_patreon_flair}`\n- `content`, `content_html` — self-post body\n- `content_url`, `url`, `permalink`, `url_overridden_by_dest`, `domain`\n- `post_hint`, `is_self`, `post_type`, `media_type`\n- `score`, `ups`, `downs`, `upvote_ratio`, `num_comments`, `num_crossposts`, `num_duplicates`\n- `link_flair`, `link_flair_background_color`, `link_flair_text_color`, `link_flair_css_class`, `link_flair_template_id`, `link_flair_type`, `link_flair_richtext`\n- `thumbnail_url`, `thumbnail_width`, `thumbnail_height`\n- `created_utc`, `created_at`, `edited`, `edited_at`\n- `is_stickied`, `is_locked`, `is_archived`, `is_pinned`, `is_nsfw`, `is_spoiler`, `is_original_content`, `is_crosspost`, `crosspost_parent_id`\n- `is_crosspostable`, `is_meta`, `is_reddit_media_domain`, `is_robot_indexable`, `is_created_from_ads_ui`\n- `allow_live_comments`, `contest_mode`, `hide_score`, `content_categories`, `media_only`, `quarantine`, `suggested_sort`, `no_follow`, `send_replies`\n- `gilded`, `total_awards_received`, `awards` — `[{name, count, coin_price, icon_url}]`\n- `removed_by_category`, `distinguished`, `hidden`\n- `has_media`, `images`, `gallery_images`, `gallery_count`\n- `video_url`, `video_duration_seconds`, `video_width`, `video_height`, `video_has_audio`, `video_bitrate_kbps`\n- `poll_data` — poll options, vote counts and end time\n- `embed_provider`, `embed_type`, `embed_title`, `embed_author_name`, `embed_thumbnail_url`, `embed_html`, `embed_width`, `embed_height`\n- `search_term` — the keyword filter that matched, when set\n- `score_captured_at` — when the archived score was captured\n- `crawled_at`, `source` — `arctic_shift`, `arctic_ids`, `rss` or `username_only`\n\n## Output: comment record\n\nOne record per comment (`dataType: \"comment\"`) returned by the `comments` or `overview` sections:\n\n- `post_id`, `post_url`, `post_title`, `post_author`, `link_id`\n- `comment_id`, `comment_name`\n- `author`, `author_meta`\n- `body`, `body_html`\n- `score`, `ups`, `downs`, `score_hidden`, `controversiality`\n- `subreddit`, `subreddit_prefixed`, `subreddit_id`, `subreddit_type`\n- `created_utc`, `created_at`, `edited`, `edited_at`\n- `depth`, `parent_id`, `parent_kind`, `is_op`, `comment_type`\n- `is_stickied`, `is_locked`, `distinguished`, `is_nsfw`, `collapsed`, `collapsed_reason`, `collapsed_reason_code`, `collapsed_because_crowd_control`\n- `can_gild`, `no_follow`, `send_replies`, `unrepliable_reason`\n- `gilded`, `total_awards_received`, `awards`\n- `removed_by_category`, `permalink`\n- `search_term` — the keyword filter that matched, when set\n- `score_captured_at`\n- `crawled_at`, `source`\n\n## Input\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `usernames` | array | – | Usernames to scrape — bare (`spez`), `u/`-prefixed, profile URLs, or comma-separated names |\n| `includeProfileInfo` | boolean | `true` | Emit the profile summary record |\n| `sections` | array | `[\"posts\"]` | `overview` (posts + comments), `posts`, `comments` |\n| `maxPosts` | integer | `100` | Max matching posts per user (1–5,000) |\n| `maxComments` | integer | `100` | Max matching comments per user (1–5,000) |\n| `sort` | select | `newest` | `newest`, `oldest`, or `top` (score-ranked within the fetched items) |\n| `timeFilter` | select | `all` | Created within the past hour/day/week/month/year |\n| `includeNSFW` | boolean | `false` | Include 18+ posts and comments on 18+ posts |\n| `onlyWithFlair` | boolean | `false` | Keep only posts that have a link flair |\n| `subreddits` | array | – | Restrict to posts/comments made in these subreddits |\n| `keyword` | string | – | Keep only posts/comments whose title, self-text or body contains this text |\n| `titleContains` | string | – | Keep only posts whose title contains this text |\n| `contentContains` | string | – | Keep only self posts whose body contains this text |\n| `flairContains` | string | – | Keep only posts whose link flair contains this text |\n| `authorFlairContains` | string | – | Keep only posts whose author flair contains this text |\n| `domain` | string | – | Keep only posts whose link domain contains this text, e.g. `youtube.com` |\n| `distinguished` | select | – | Only `moderator`, `admin`, `special`, or `none` (regular) posts |\n| `postType` | select | – | Only `self`, `link`, `image`, `video`, `gallery` or `poll` posts |\n| `minScore` / `maxScore` | integer | – | Keep only posts/comments with a score in this range |\n| `minPostComments` / `maxPostComments` | integer | – | Keep only posts whose own comment count is in this range |\n| `minUpvoteRatio` | number | – | Keep only posts with an upvote ratio at or above this value (0–1) |\n| `minAwards` | integer | – | Keep only posts with at least this many total awards |\n| `minContentLength` / `maxContentLength` | integer | – | Keep only self posts whose body length (characters) is in this range |\n| `onlyOriginalContent` | boolean | `false` | Keep only posts tagged as original content |\n| `excludeStickied` | boolean | `false` | Drop stickied/pinned posts |\n| `excludeRemoved` | boolean | `false` | Drop removed/deleted posts |\n| `excludeCrossposts` | boolean | `false` | Drop crossposted posts |\n| `excludeSpoilers` | boolean | `false` | Drop spoiler-tagged posts |\n| `excludeLocked` | boolean | `false` | Drop posts with comments locked by a moderator |\n| `excludeArchived` | boolean | `false` | Drop archived posts |\n| `excludeDeletedAuthor` | boolean | `false` | Drop posts whose author account was deleted |\n| `excludeKeywords` | array | – | Drop posts whose title/body/flair contains any of these terms |\n| `postedAfter` / `postedBefore` | date | – | Keep only items created within this date range (UTC) |\n\n### Example: profile summary and recent overview\n\n```json\n{\n  \"usernames\": [\"spez\"],\n  \"includeProfileInfo\": true,\n  \"sections\": [\"overview\"],\n  \"maxPosts\": 50,\n  \"maxComments\": 50\n}\n```\n\n### Example: recent posts in selected subreddits\n\n```json\n{\n  \"usernames\": [\"u/example_user\"],\n  \"sections\": [\"posts\"],\n  \"sort\": \"newest\",\n  \"maxPosts\": 200,\n  \"subreddits\": [\"pics\", \"AskReddit\"],\n  \"keyword\": \"photo\",\n  \"excludeStickied\": true\n}\n```\n\n### Example: high-scoring comments from the past year\n\n```json\n{\n  \"usernames\": [\"spez\"],\n  \"includeProfileInfo\": false,\n  \"sections\": [\"comments\"],\n  \"timeFilter\": \"year\",\n  \"maxComments\": 500,\n  \"minScore\": 50\n}\n```\n\n## Use cases\n\n- **User research** — analyze an account's posting patterns, engagement and karma\n- **Account vetting** — check activity dates, karma and history before trusting a recommendation or partnership\n- **Content discovery** — pull a creator's or influencer's posts by subreddit, keyword or score\n- **Moderation research** — audit a user's post history across specific communities\n- **Behavioral and social research** — bulk-export public user history for academic or market research\n- **Profile monitoring** — track a user's public activity over time on a schedule\n\n## FAQ\n\n**Do I need a Reddit API key or account login?**\nNo — the actor reads the public Reddit archive and public profile surfaces without credentials.\n\n**Do I need to configure a proxy?**\nNo — there is no proxy setting to configure.\n\n**Why do some scores read 0 or 1?**\nArctic Shift archives an item at posting time and updates score/comment counts on a later crawl (~36 hours). Check `score_captured_at`; the item's score becomes accurate after that re-crawl.\n\n**Why are karma totals different from the live profile?**\nArctic's account aggregate is refreshed infrequently and may lag the live profile. `karma_updated_at` shows the aggregate date. The actor never invents a fresher number.\n\n**What happens when the archive is rate-limited?**\nThe actor retries with backoff (and a smaller page size) and, if the search still fails, falls back to the public Atom feed (most recent ~100 items; scores only where the archive ID lookup succeeds). The run status message says which source was used.\n\n**Does it include private activity like upvotes or saved posts?**\nNo — only public posts and comments are available. Voting history, saved items and hidden posts are private to the account owner.\n\n**What happens for suspended or nonexistent usernames?**\nThe run completes and reports that no records were found for that username.\n\n**Is history capped?**\nThe actor pages through the archive by creation-time cursor until `maxPosts`/`maxComments` or source exhaustion. Reddit's Atom fallback is capped at the most recent ~100 items by Reddit itself.\n\n**Can I filter to a date range?**\nYes — use `postedAfter` / `postedBefore` (UTC dates) or `timeFilter`. The window is passed to the archive, so pagination stops at the boundary.\n\n**Is this actor affiliated with Reddit?**\nNo — this is an independent, third-party actor reading public Reddit archive data. It is not built, endorsed or maintained by Reddit, Inc.\n",
      "input": {
        "title": "Reddit Profile Scraper Input",
        "type": "object",
        "schemaVersion": 1,
        "properties": {
          "usernames": {
            "title": "Reddit Usernames",
            "type": "array",
            "description": "List of Reddit usernames to scrape. Accepts bare names (spez), u/ prefixed (u/spez) or profile URLs.",
            "editor": "stringList",
            "example": [
              "spez",
              "u/example_user",
              "https://www.reddit.com/user/another_user/"
            ],
            "prefill": [
              "spez"
            ],
            "minItems": 1
          },
          "includeProfileInfo": {
            "title": "Include profile info record",
            "type": "boolean",
            "description": "Emit a user_profile record with archive-wide post/comment/total karma, archived post/comment counts, first/last activity dates, and any profile fields the public profile page exposes.",
            "default": true,
            "prefill": true
          },
          "sections": {
            "title": "Profile sections",
            "type": "array",
            "description": "Which parts of the user's history to scrape. Overview returns posts and comments merged newest-first (or by the selected sort).",
            "editor": "select",
            "items": {
              "type": "string",
              "enum": [
                "overview",
                "posts",
                "comments"
              ],
              "enumTitles": [
                "Overview (posts + comments)",
                "Posts",
                "Comments"
              ]
            },
            "prefill": [
              "posts"
            ],
            "default": [
              "posts"
            ],
            "example": [
              "posts",
              "comments"
            ]
          },
          "maxPosts": {
            "title": "Maximum posts per user",
            "type": "integer",
            "description": "Maximum number of matching posts to emit per user.",
            "minimum": 1,
            "maximum": 5000,
            "default": 100,
            "prefill": 3,
            "example": 100
          },
          "maxComments": {
            "title": "Maximum comments per user",
            "type": "integer",
            "description": "Maximum number of matching comments to emit per user.",
            "minimum": 1,
            "maximum": 5000,
            "default": 100,
            "prefill": 3,
            "example": 100
          },
          "sort": {
            "title": "Sort history by",
            "type": "string",
            "description": "Newest or oldest first by creation time. Top ranks the fetched items by score (the archive itself only sorts by date, so this is a ranking within the most recent items up to the cap).",
            "enum": [
              "newest",
              "oldest",
              "top"
            ],
            "enumTitles": [
              "Newest first",
              "Oldest first",
              "Top scored (within fetched items)"
            ],
            "default": "newest",
            "prefill": "newest"
          },
          "timeFilter": {
            "title": "Created within the last",
            "type": "string",
            "description": "Only keep posts/comments created within this rolling window (UTC). Applied as a date window for every sort; an explicit 'postedAfter' later than the window wins.",
            "enum": [
              "hour",
              "day",
              "week",
              "month",
              "year",
              "all"
            ],
            "default": "all",
            "prefill": "all",
            "enumTitles": [
              "Past hour",
              "Past day",
              "Past week",
              "Past month",
              "Past year",
              "All time"
            ]
          },
          "includeNSFW": {
            "title": "Include NSFW (18+) content",
            "type": "boolean",
            "description": "Include NSFW posts in the user's history.",
            "default": false,
            "prefill": false
          },
          "onlyWithFlair": {
            "title": "Only posts with flair",
            "type": "boolean",
            "description": "Keep only posts that have a link flair set. Has no effect on comments (comments don't carry link flair).",
            "default": false,
            "prefill": false
          },
          "subreddits": {
            "title": "Restrict to subreddits",
            "type": "array",
            "description": "Only keep posts/comments made in these subreddits (case-insensitive). Accepts bare names (python), r/ prefixed (r/python), or subreddit URLs. Leave empty to include every subreddit in the user's history.",
            "editor": "stringList",
            "example": [
              "AskReddit",
              "r/technology"
            ]
          },
          "keyword": {
            "title": "Keyword filter",
            "type": "string",
            "description": "Only keep posts/comments whose title, self-text or comment body contains this text (case-insensitive substring match). Leave empty to disable.",
            "editor": "textfield",
            "example": "climate"
          },
          "titleContains": {
            "title": "Title contains keyword",
            "type": "string",
            "description": "Only keep posts whose title contains this text (case-insensitive substring match). Has no effect on comments. Leave empty to keep all titles.",
            "editor": "textfield",
            "example": "launch"
          },
          "contentContains": {
            "title": "Post text contains keyword",
            "type": "string",
            "description": "Only keep self (text) posts whose body contains this text (case-insensitive substring match). Link/image/video posts have no body text and are excluded when this is set. Has no effect on comments. Leave empty to keep all posts.",
            "editor": "textfield",
            "example": "tutorial"
          },
          "flairContains": {
            "title": "Flair contains keyword",
            "type": "string",
            "description": "Only keep posts whose link flair text contains this text (case-insensitive substring match). Has no effect on comments. Leave empty to keep all flairs.",
            "editor": "textfield",
            "example": "Discussion"
          },
          "authorFlairContains": {
            "title": "Author flair contains keyword",
            "type": "string",
            "description": "Only keep posts whose author flair text contains this text (case-insensitive substring match). Has no effect on comments. Leave empty to keep all.",
            "editor": "textfield",
            "example": "Moderator"
          },
          "domain": {
            "title": "Domain contains",
            "type": "string",
            "description": "Only keep posts whose link domain contains this text (case-insensitive, e.g. 'youtube.com' or 'self.python'). Has no effect on comments. Leave empty to keep all domains.",
            "editor": "textfield",
            "example": "youtube.com"
          },
          "distinguished": {
            "title": "Distinguished (official) posts only",
            "type": "string",
            "description": "Only keep posts distinguished by Reddit as moderator, admin or special (e.g. Reddit-team) posts, or only regular (non-distinguished) posts. Has no effect on comments. Leave unset to keep all posts.",
            "editor": "select",
            "enum": [
              "moderator",
              "admin",
              "special",
              "none"
            ],
            "enumTitles": [
              "Moderator posts only",
              "Admin posts only",
              "Special (official) posts only",
              "Regular posts only (exclude all distinguished)"
            ]
          },
          "minAwards": {
            "title": "Minimum awards received",
            "type": "integer",
            "description": "Only keep posts with at least this many total awards. Has no effect on comments. Leave unset to keep all posts.",
            "minimum": 0,
            "maximum": 1000000,
            "example": 1
          },
          "onlyOriginalContent": {
            "title": "Only original content (OC) posts",
            "type": "boolean",
            "description": "When enabled, only posts the author tagged as original content are kept. Has no effect on comments.",
            "default": false,
            "prefill": false
          },
          "excludeArchived": {
            "title": "Exclude archived posts",
            "type": "boolean",
            "description": "When enabled, posts that Reddit has archived (locked from further voting/commenting after 6 months) are dropped from the results. Has no effect on comments.",
            "default": false,
            "prefill": false
          },
          "excludeKeywords": {
            "title": "Exclude keywords",
            "type": "array",
            "description": "Drop posts whose title, self-text body or flair contains any of these keywords or phrases (case-insensitive substring match) — useful for filtering out megathreads, giveaways or spam boilerplate. Has no effect on comments. Leave empty to keep all posts.",
            "editor": "stringList",
            "example": [
              "megathread"
            ]
          },
          "minContentLength": {
            "title": "Minimum post body length (characters)",
            "type": "integer",
            "description": "Only keep self (text) posts whose body is at least this many characters long. Link/image/video posts have no body and are excluded when this is set. Has no effect on comments. Leave unset to keep all lengths.",
            "minimum": 0,
            "maximum": 1000000,
            "example": 100
          },
          "maxContentLength": {
            "title": "Maximum post body length (characters)",
            "type": "integer",
            "description": "Only keep self (text) posts whose body is at most this many characters long. Has no effect on comments. Leave unset to keep all lengths.",
            "minimum": 0,
            "maximum": 1000000,
            "example": 5000
          },
          "postType": {
            "title": "Only posts of this type",
            "type": "string",
            "description": "Keep only posts of the selected content type. Leave unset to keep all types. Has no effect on comments.",
            "editor": "select",
            "enum": [
              "self",
              "link",
              "image",
              "video",
              "gallery",
              "poll"
            ],
            "enumTitles": [
              "Text (self post)",
              "Link",
              "Image",
              "Video",
              "Gallery",
              "Poll"
            ]
          },
          "minScore": {
            "title": "Minimum score (upvotes minus downvotes)",
            "type": "integer",
            "description": "Only keep posts/comments with a score at or above this value. Leave unset to keep all scores.",
            "minimum": -1000000,
            "maximum": 1000000,
            "example": 10
          },
          "maxScore": {
            "title": "Maximum score (upvotes minus downvotes)",
            "type": "integer",
            "description": "Only keep posts/comments with a score at or below this value. Useful for finding overlooked/low-visibility items. Leave unset to keep all scores.",
            "minimum": -1000000,
            "maximum": 1000000,
            "example": 1000
          },
          "minPostComments": {
            "title": "Minimum comments on the post",
            "type": "integer",
            "description": "Only keep posts that have at least this many comments (the post's own comment count — not to be confused with 'Maximum comments per user' above, which caps how many comment records are scraped). Has no effect on comments.",
            "minimum": 0,
            "maximum": 1000000,
            "example": 5
          },
          "maxPostComments": {
            "title": "Maximum comments on the post",
            "type": "integer",
            "description": "Only keep posts that have at most this many comments. Useful for finding under-discussed posts. Has no effect on comments.",
            "minimum": 0,
            "maximum": 1000000,
            "example": 500
          },
          "minUpvoteRatio": {
            "title": "Minimum upvote ratio",
            "type": "number",
            "description": "Only keep posts whose upvote ratio (fraction of votes that are upvotes, 0-1) is at or above this value. Useful for filtering out controversial/divisive posts. Has no effect on comments.",
            "minimum": 0,
            "maximum": 1,
            "example": 0.8
          },
          "excludeStickied": {
            "title": "Exclude stickied/pinned posts",
            "type": "boolean",
            "description": "When enabled, posts pinned/stickied in their community are dropped from the results.",
            "default": false,
            "prefill": false
          },
          "excludeRemoved": {
            "title": "Exclude removed/deleted posts",
            "type": "boolean",
            "description": "When enabled, posts removed by a moderator, Reddit, or deleted by their author (marker: removed_by_category) are dropped from the results.",
            "default": false,
            "prefill": false
          },
          "excludeCrossposts": {
            "title": "Exclude crossposts",
            "type": "boolean",
            "description": "When enabled, posts that are crossposts from another subreddit are dropped, keeping only the user's original submissions.",
            "default": false,
            "prefill": false
          },
          "excludeSpoilers": {
            "title": "Exclude spoiler-tagged posts",
            "type": "boolean",
            "description": "When enabled, posts marked as a spoiler by their author are dropped from the results.",
            "default": false,
            "prefill": false
          },
          "excludeLocked": {
            "title": "Exclude locked posts",
            "type": "boolean",
            "description": "When enabled, posts with comments locked by a moderator are dropped from the results.",
            "default": false,
            "prefill": false
          },
          "excludeDeletedAuthor": {
            "title": "Exclude posts with a deleted author",
            "type": "boolean",
            "description": "When enabled, posts whose author account was deleted (shown as [deleted]/[removed]) are dropped from the results.",
            "default": false,
            "prefill": false
          },
          "postedAfter": {
            "title": "Items created on or after (YYYY-MM-DD)",
            "type": "string",
            "description": "Only keep items created on or after this date (UTC).",
            "editor": "datepicker",
            "example": "2025-01-01"
          },
          "postedBefore": {
            "title": "Items created on or before (YYYY-MM-DD)",
            "type": "string",
            "description": "Only keep items created on or before this date (interpreted as the end of that day, UTC).",
            "editor": "datepicker",
            "example": "2025-12-31"
          }
        }
      },
      "output": {
        "actorOutputSchemaVersion": 1,
        "title": "Reddit User Karma & Post History Extractor Output",
        "description": "One user_profile record per username (archive-wide karma, archived post/comment counts and activity dates), plus one record per scraped post or comment, distinguished by dataType.",
        "properties": {
          "profilePostAndCommentRecords": {
            "type": "string",
            "title": "Profile, post & comment records",
            "description": "Dataset with one user_profile record per requested username and one record per scraped post/comment. Records are distinguished by the dataType field (user_profile, post or comment).",
            "template": "{{links.apiDefaultDatasetUrl}}/items"
          }
        }
      },
      "storages": {
        "dataset": {
          "actorSpecification": 1,
          "views": {
            "overview": {
              "title": "User Activity",
              "transformation": {
                "fields": [
                  "dataType",
                  "username",
                  "title",
                  "body",
                  "subreddit_prefixed",
                  "score",
                  "num_comments",
                  "url",
                  "created_at"
                ]
              },
              "display": {
                "component": "table",
                "properties": {}
              }
            }
          }
        }
      },
      "environmentVariables": {},
      "defaultRunOptions": {
        "build": "latest",
        "timeoutSecs": 3600,
        "memoryMbytes": 2048
      }
    },
    "buildNumber": "2.0.1",
    "imageDigest": "3b5f529c149b5f04c03d3a8a76fd0fd4f7763631250964d265ae14b3df95c801",
    "actVersion": {
      "sourceType": "SOURCE_FILES",
      "buildTag": "latest",
      "versionNumber": "2.0"
    },
    "usage": {
      "ACTOR_COMPUTE_UNITS": 0.010088888888888889
    }
  }
}