{
  "openapi": "3.0.1",
  "info": {
    "title": "Reddit Scraper With Full Comment Threads",
    "description": "Reddit Scraper — Scrape Reddit posts with full comment threads, including nested replies, authors, scores, timestamps, post details, and engagement metrics. Extract structured conversation data for audience research, sentiment analysis, trend discovery, and community insights.",
    "version": "0.1",
    "x-build-id": "QG7qAVzkPKXtsenYc"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/scrapier~reddit-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-scrapier-reddit-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/scrapier~reddit-scraper/runs": {
      "post": {
        "operationId": "runs-sync-scrapier-reddit-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/scrapier~reddit-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-scrapier-reddit-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "redditTargetUrls": {
            "title": "🔗 Reddit URLs",
            "type": "array",
            "description": "One or more Reddit URLs to scrape. Accepted: (1) Post URLs (contain /comments/, e.g. https://www.reddit.com/r/AskReddit/comments/abc123/some_title/) — the primary target for full comment-tree extraction; (2) Subreddit URLs (e.g. https://www.reddit.com/r/python/); (3) User profile URLs (e.g. https://www.reddit.com/user/someuser/). Use \"+ Add\", \"Bulk edit\", or \"Text file\" for many URLs. Legacy key \"startUrls\" is still accepted for backward compatibility if you already have input JSON using it. Leave empty to run in keyword/comment-search-only mode below.",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "🔗 Start URLs (legacy)",
            "type": "array",
            "description": "Legacy alias of \"Reddit URLs\" above, kept for backward compatibility with existing input JSON. If both are set, \"Reddit URLs\" wins.",
            "items": {
              "type": "string"
            }
          },
          "commentTreeMaxDepth": {
            "title": "🌳 Max reply depth",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "How many levels of nested replies to include per top-level comment (1 = only top-level comments, no replies). Legacy key \"maxCommentDepth\" is still accepted. Example: depth 3 keeps comment → reply → reply-to-reply, and collapses anything deeper into an honest \"more replies\" marker with the real count."
          },
          "maxCommentDepth": {
            "title": "🌳 Max comment tree depth (legacy)",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Legacy alias of \"Max reply depth\" above, kept for backward compatibility."
          },
          "maxRepliesPerComment": {
            "title": "↩️ Max replies per comment (breadth)",
            "minimum": 1,
            "maximum": 200,
            "type": "integer",
            "description": "Maximum number of direct child replies kept under any single comment. Extra real replies are not dropped silently — they are summarized as a \"more replies\" marker with the true remaining count, the same way Reddit's own UI collapses large threads. Set higher for very active threads."
          },
          "maxCommentsPerThread": {
            "title": "💬 Max comments fetched per post",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Total comment nodes (top-level + nested) fetched per post before the tree is built. Legacy key \"limitCommentsPerPage\" is still accepted. Reddit threads can have thousands of comments; this caps the request size. Use a higher value for deep-dive threads."
          },
          "limitCommentsPerPage": {
            "title": "💬 Limit comments (legacy)",
            "minimum": 1,
            "type": "integer",
            "description": "Legacy alias of \"Max comments fetched per post\" above."
          },
          "skipComments": {
            "title": "⏭️ Skip comment trees",
            "type": "boolean",
            "description": "If enabled, post URLs are scraped for post-level data only (title, score, body, etc.) and the comment tree fetch is skipped entirely. Use to speed up runs when you only need post metadata.",
            "default": false
          },
          "commentSearchQueries": {
            "title": "🔎 Comment keyword(s)",
            "type": "array",
            "description": "One or more keywords/phrases to search for inside comment bodies. Each is queried separately. Requires at least one subreddit or author below to be set (comment full-text search must be scoped). Leave empty to skip standalone comment search.",
            "items": {
              "type": "string"
            }
          },
          "commentSearchSubreddits": {
            "title": "🏘️ Search comments in subreddit(s)",
            "type": "array",
            "description": "Restrict standalone comment search (and/or list recent comments with no keyword) to these subreddit names (without \"r/\"). Combine with Comment keyword(s) for a scoped keyword search, or leave keyword empty to pull recent comments from these subreddits.",
            "items": {
              "type": "string"
            }
          },
          "commentSearchAuthors": {
            "title": "👤 Search comments by author(s)",
            "type": "array",
            "description": "Restrict standalone comment search to comments written by these usernames (without \"u/\"). Can be combined with subreddit scope and/or keyword.",
            "items": {
              "type": "string"
            }
          },
          "commentSearchMaxResults": {
            "title": "🔢 Max comments per search",
            "minimum": 1,
            "maximum": 2000,
            "type": "integer",
            "description": "Maximum number of comments to collect per keyword/scope combination in standalone comment search.",
            "default": 50
          },
          "enableSentimentAnalysis": {
            "title": "🤖 Enable comment sentiment/topic tagging",
            "type": "boolean",
            "description": "When on, every comment collected by the comment tree and/or standalone comment search features is sent to the selected AI model for sentiment (positive/neutral/negative), emotion, and topic-keyword tagging. Off by default — a genuine opt-in feature.",
            "default": false
          },
          "aiModel": {
            "title": "🤖 AI model / provider",
            "enum": [
              "claude-haiku-4-5",
              "claude-sonnet-5",
              "gpt-4o-mini",
              "gpt-4o",
              "gemini-2.0-flash-lite",
              "gemini-2.0-flash",
              "grok-3-mini",
              "deepseek-chat",
              "sonar",
              "mistral-small-latest"
            ],
            "type": "string",
            "description": "Provider is auto-detected from the model name: claude-*=Anthropic, gpt-*/o1/o3=OpenAI, gemini-*=Google, grok-*=xAI, deepseek-*=DeepSeek, sonar*=Perplexity, mistral-*=Mistral. Only used when sentiment tagging is enabled above.",
            "default": "claude-haiku-4-5"
          },
          "aiApiKey": {
            "title": "🔑 AI provider API key",
            "type": "string",
            "description": "API key for the selected AI provider. Optional — if left empty, the actor also checks the matching environment variable (e.g. ANTHROPIC_API_KEY, OPENAI_API_KEY). If no key is found anywhere, sentiment/topic fields are left null and the run completes normally."
          },
          "keywordSearchTerms": {
            "title": "🔎 Keyword(s)",
            "type": "array",
            "description": "One or more search phrases to run against Reddit posts. Legacy key \"searchTerms\" is still accepted. Each term is queried separately.",
            "items": {
              "type": "string"
            }
          },
          "searchTerms": {
            "title": "🔎 Search terms (legacy)",
            "type": "array",
            "description": "Legacy alias of \"Keyword(s)\" above.",
            "items": {
              "type": "string"
            }
          },
          "keywordSearchSubreddit": {
            "title": "🏘️ Restrict keyword search to subreddit (optional)",
            "type": "string",
            "description": "Optional subreddit name without \"r/\". When set, keyword post search is restricted to this community. Legacy key \"searchCommunity\" is still accepted. Leave empty to search all of Reddit."
          },
          "searchCommunity": {
            "title": "🏘️ Community (legacy)",
            "type": "string",
            "description": "Legacy alias of \"Restrict keyword search to subreddit\" above."
          },
          "ignoreStartUrls": {
            "title": "⏭️ Ignore Reddit URLs (keyword-search-only mode)",
            "type": "boolean",
            "description": "When enabled, Reddit URLs above are not scraped — only Keyword Post Search and/or Standalone Comment Search run.",
            "default": false
          },
          "sortSearch": {
            "title": "📊 Sort keyword post search",
            "enum": [
              "relevance",
              "new",
              "top",
              "comments"
            ],
            "type": "string",
            "description": "Order for keyword post search results: relevance, new (newest first), top (highest score), comments (most comments). \"hot\"/trending cannot be honestly reproduced from an archive with no live ranking signal, so it is not offered here — use \"top\" or \"new\" instead.",
            "default": "new"
          },
          "dateFilter": {
            "title": "📅 Only include content from",
            "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$|^(\\d+)\\s*(day|week|month|year)s?$|^$",
            "type": "string",
            "description": "Real, working absolute-or-relative date filter (e.g. \"2025-01-15\" or \"2 weeks\"). Applies to keyword post search, standalone comment search, and subreddit listings. Legacy keys \"filterByDate\" and \"postDateLimit\" (both previously non-functional in the base actor) are still accepted as a fallback. Leave empty for no date filter."
          },
          "filterByDate": {
            "title": "📅 Filter by date (legacy)",
            "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$|^(\\d+)\\s*(day|week|month|year)s?$|^$",
            "type": "string",
            "description": "Legacy alias of \"Only include content from\" above."
          },
          "postDateLimit": {
            "title": "📅 Post date limit (legacy)",
            "pattern": "^(\\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$|^$",
            "type": "string",
            "description": "Legacy alias of \"Only include content from\" above (previously non-functional in the base actor; now wired to the same real date filter)."
          },
          "timeFilter": {
            "title": "⏱️ Time filter (base actor field)",
            "enum": [
              "hour",
              "day",
              "week",
              "month",
              "year",
              "all"
            ],
            "type": "string",
            "description": "Real, working relative time window matching the base actor's \"Time filter\": hour (last 60 min), day, week, month, year, or all (no time limit). Applies to search, comment search, and subreddit listings, on top of \"Only include content from\" above — whichever cutoff is more recent/restrictive wins. This is additive to this variant's own richer date filter above, not a replacement for it.",
            "default": "all"
          },
          "searchForPosts": {
            "title": "📝 Search for posts",
            "type": "boolean",
            "description": "Include posts in keyword search results. This is the only search scope this actor supports (matching the base actor's field of the same name); turn off to skip keyword post search entirely even when keywords are set (equivalent to disabling \"Enable keyword post search\" below).",
            "default": true
          },
          "enableSearch": {
            "title": "🔍 Enable keyword post search",
            "type": "boolean",
            "description": "When on, runs Keyword Post Search if keywords are provided and search mode is active (see \"Ignore Reddit URLs\").",
            "default": true
          },
          "enableSubreddit": {
            "title": "📰 Enable subreddit listings",
            "type": "boolean",
            "description": "When on, subreddit URLs among Reddit URLs are scraped for a post listing.",
            "default": true
          },
          "sortSubreddit": {
            "title": "📊 Subreddit listing order",
            "enum": [
              "new",
              "top",
              "hot_approx"
            ],
            "type": "string",
            "description": "How to order posts from each subreddit: new (newest first, always accurate), top (highest score). \"hot\"/\"rising\"/\"controversial\" are Reddit's own live ranking-algorithm outputs and cannot be honestly reproduced from an archive — they are approximated here as recency-weighted score and disclosed as such in the output, never presented as Reddit's real live ranking.",
            "default": "new"
          },
          "enablePost": {
            "title": "📝 Enable post + comment tree",
            "type": "boolean",
            "description": "When on, post URLs among Reddit URLs are scraped for the full post and its comment tree (unless \"Skip comment trees\" is on).",
            "default": true
          },
          "enableUser": {
            "title": "👤 Enable user scraper",
            "type": "boolean",
            "description": "When on, user profile URLs among Reddit URLs are scraped for profile, submitted posts, and comments.",
            "default": true
          },
          "enableSubredditInfo": {
            "title": "🏘️ Enable subreddit info",
            "type": "boolean",
            "description": "When on, fetches metadata (subscribers, description, creation date) for subreddits found in Reddit URLs or the search scope.",
            "default": true
          },
          "skipUserPosts": {
            "title": "👤 Skip user posts",
            "type": "boolean",
            "description": "If enabled, user profile URLs are ignored entirely.",
            "default": false
          },
          "skipCommunity": {
            "title": "🏘️ Skip community metadata",
            "type": "boolean",
            "description": "If enabled, subreddit metadata (description, subscriber count) is not fetched, though post listings still run when enabled above.",
            "default": false
          },
          "maxTotalItems": {
            "title": "📦 Max total items across the whole run",
            "minimum": 1,
            "type": "integer",
            "description": "Genuine cross-source running total — once this many items (posts, comments, search results combined) have been saved across ALL sources in this run, the actor stops. Legacy key \"maxItemsToSave\" is still accepted (in the base actor this cap only applied per search term, not globally — now fixed)."
          },
          "maxItemsToSave": {
            "title": "📦 Max items to save (legacy)",
            "minimum": 1,
            "type": "integer",
            "description": "Legacy alias of \"Max total items across the whole run\" above."
          },
          "limitPostsPerPage": {
            "title": "📄 Posts per subreddit/search page",
            "minimum": 1,
            "type": "integer",
            "description": "Maximum number of posts fetched from a single subreddit-listing or keyword-search archive request.",
            "default": 25
          },
          "limitCommunityPages": {
            "title": "🏘️ Max pages per subreddit",
            "minimum": 1,
            "type": "integer",
            "description": "For each subreddit URL, the maximum number of listing pages to paginate through (each page holds up to \"Posts per subreddit/search page\" items). Now genuinely enforced (previously accepted but ignored in the base actor).",
            "default": 3
          },
          "limitUserPages": {
            "title": "👤 Max pages per user",
            "minimum": 1,
            "type": "integer",
            "description": "For each user profile URL, the maximum number of pages fetched for submitted posts and comments. Now genuinely enforced (previously accepted but ignored in the base actor).",
            "default": 3
          },
          "maxItemsPerUser": {
            "title": "👤 Max items per user (posts/comments)",
            "minimum": 1,
            "type": "integer",
            "description": "Per user, the maximum number of submitted posts and the maximum number of comments to fetch.",
            "default": 20
          },
          "fetchUserProfile": {
            "title": "👤 Fetch user profile",
            "type": "boolean",
            "description": "When on, fetch each user's aggregate profile (karma, post/comment counts). Coverage note: this data is aggregate-only and updated infrequently by the underlying archive, and the profile id can be null for accounts inactive in recent years — disclosed, never fabricated.",
            "default": true
          },
          "fetchUserSubmitted": {
            "title": "📝 Fetch user submitted posts",
            "type": "boolean",
            "description": "When on, fetch posts submitted by each user.",
            "default": true
          },
          "fetchUserComments": {
            "title": "💬 Fetch user comments",
            "type": "boolean",
            "description": "When on, fetch comments made by each user.",
            "default": true
          },
          "fetchUserOverview": {
            "title": "📋 Fetch user overview summary",
            "type": "boolean",
            "description": "When on, adds a combined summary (total items, posts count, comments count) built from the submitted-posts and comments fetches above.",
            "default": false
          },
          "fetchPopularSubreddits": {
            "title": "🔥 Fetch top subreddits by subscribers",
            "type": "boolean",
            "description": "When on, fetches subreddits ranked by subscriber count (an honest proxy for \"popular\" — no free archive exposes Reddit's live trending signal). Optionally scoped by \"Subreddit name prefix\" below. Best-effort: the underlying archive's unscoped subreddit index can time out under load; on failure this returns an empty list rather than fabricated data. Legacy key \"fetchTopSubreddits\" (the base actor's field name) is still accepted as a fallback if this is left unset.",
            "default": false
          },
          "fetchTopSubreddits": {
            "title": "🔝 Fetch top subreddits (legacy)",
            "type": "boolean",
            "description": "Legacy alias of \"Fetch top subreddits by subscribers\" above, matching the base actor's field name. Used as a fallback only when \"Fetch top subreddits by subscribers\" itself is left unset.",
            "default": false
          },
          "fetchNewSubreddits": {
            "title": "🆕 Fetch newest created subreddits",
            "type": "boolean",
            "description": "When on, fetches recently created subreddits (sorted by creation date), optionally scoped by \"Subreddit name prefix\" below. Same best-effort/timeout disclosure as above.",
            "default": false
          },
          "subredditNamePrefix": {
            "title": "🔤 Subreddit name prefix (optional)",
            "type": "string",
            "description": "Optional prefix to scope \"Fetch top subreddits\"/\"Fetch newest subreddits\" (e.g. \"ask\" matches r/askreddit, r/askscience, …). An unscoped, prefix-less lookup is more likely to time out on the underlying archive."
          },
          "maxSubredditsInfo": {
            "title": "🔢 Max subreddits (top/newest lists)",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "Maximum number of subreddits to fetch for the top/newest subreddit lists above.",
            "default": 25
          },
          "requestDelaySeconds": {
            "title": "⏳ Delay between requests (seconds)",
            "minimum": 0,
            "type": "integer",
            "description": "Seconds to wait between consecutive requests to the data source. Helps avoid rate limiting.",
            "default": 1
          },
          "proxyConfiguration": {
            "title": "🌐 Proxy configuration",
            "type": "object",
            "description": "Configure Apify Proxy for this run. By default the actor connects directly and automatically escalates to datacenter, then residential proxy if it hits a temporary block or rate limit."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}