{
  "openapi": "3.0.1",
  "info": {
    "title": "Reddit Scraper - Posts, Comments, Users & Keywords, No Login",
    "description": "Reddit scraper that works without login: posts, comments, full user history and keyword search from subreddit, user, search and domain feeds, plus user and subreddit profiles, extracted indicators (CVE, IP, hash, wallet, domain), related subreddits and a rate-limit report.",
    "version": "1.0",
    "x-build-id": "6hZaeA9FpyZABcI7l"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/ntriqpro~reddit-user-subreddit-osint/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-ntriqpro-reddit-user-subreddit-osint",
        "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/ntriqpro~reddit-user-subreddit-osint/runs": {
      "post": {
        "operationId": "runs-sync-ntriqpro-reddit-user-subreddit-osint",
        "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/ntriqpro~reddit-user-subreddit-osint/run-sync": {
      "post": {
        "operationId": "run-sync-ntriqpro-reddit-user-subreddit-osint",
        "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": {
          "subreddits": {
            "title": "Subreddits",
            "maxItems": 500,
            "type": "array",
            "description": "Subreddits to read: a name, r/name or a reddit.com link. Join several with + to read them as one listing (netsec+osint). Each gives post rows, comment rows, a subreddit profile, indicators and related subreddits. Paid Apify plans read up to 500 sources per run, as far back as Reddit lists them (1,000 posts and 1,000 comments per subreddit). Free plan runs are a preview: 2 sources, the 10 newest items of each (text cut at 280 characters), 1 indicator of each kind, 3 related subreddits and 1 keyword. Charged per source checked ($0.003) and per post or comment row ($0.002).",
            "items": {
              "type": "string"
            }
          },
          "users": {
            "title": "Users",
            "maxItems": 500,
            "type": "array",
            "description": "Reddit users to read: a name, u/name or a profile link. Each gives the user's posts and comments, a user profile row (activity by subreddit, active hours, top domains and terms) and one row per subreddit the user is active in. A hidden, suspended or missing profile is answered with a source row saying so.",
            "items": {
              "type": "string"
            }
          },
          "keywords": {
            "title": "Keywords (Reddit search)",
            "maxItems": 500,
            "type": "array",
            "description": "Searches over all of Reddit, one per entry. Search operators work: subreddit:netsec, title:CVE, author:name, url:example.com. Each keyword gives the posts found, one keyword result row (count, last 7 days, first and last, which subreddits, sample posts — also when nothing was found) and related subreddits. Reddit search stops near 250 results per query. Free plan runs search 1 keyword.",
            "items": {
              "type": "string"
            }
          },
          "domains": {
            "title": "Domains",
            "maxItems": 500,
            "type": "array",
            "description": "Posts that link to a domain, for example bleepingcomputer.com. Delivered as post rows with viaDomain set.",
            "items": {
              "type": "string"
            }
          },
          "postUrls": {
            "title": "Post URLs",
            "maxItems": 500,
            "type": "array",
            "description": "Single posts by address, for example https://www.reddit.com/r/netsec/comments/abc123/title/. Gives the post and the comments its public feed carries (the feed of one post returns only part of a long thread).",
            "items": {
              "type": "string"
            }
          },
          "include": {
            "title": "Row kinds",
            "type": "array",
            "description": "Which kinds of rows to return (all when empty). With neither posts nor comments selected the items are still read and counted for the profiles and indicators, but no post or comment row is delivered or charged. Free plan runs read one listing per subreddit: its posts, or its comments when posts are left out (10 newest).",
            "items": {
              "type": "string",
              "enum": [
                "posts",
                "comments",
                "userProfile",
                "subredditProfile",
                "keywordSummary",
                "indicators",
                "relatedSubreddits"
              ],
              "enumTitles": [
                "Posts",
                "Comments",
                "User profiles",
                "Subreddit profiles",
                "Keyword results",
                "Indicators",
                "Related subreddits"
              ]
            }
          },
          "sort": {
            "title": "Sort",
            "enum": [
              "new",
              "hot",
              "top",
              "rising",
              "controversial"
            ],
            "type": "string",
            "description": "Listing to read for subreddits and searches: new, hot, top, rising or controversial. Ranked listings add rankInFeed to each post. Users and domains are always read newest first, and so is every listing when New items only is on."
          },
          "time": {
            "title": "Time range",
            "enum": [
              "hour",
              "day",
              "week",
              "month",
              "year",
              "all"
            ],
            "type": "string",
            "description": "Time range for top and controversial listings and for searches."
          },
          "maxItemsPerSource": {
            "title": "Max items per listing",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "How many items to read from each listing of a source, newest first (1 to 1,000 — Reddit lists no more). A subreddit and a user have two listings, posts and comments. Filters below apply to the items read. Free plan runs return up to 10 newest items per source. Values above 10 (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "maxCommentsPerPost": {
            "title": "Max comments per post URL",
            "minimum": 1,
            "maximum": 3000,
            "type": "integer",
            "description": "For post URLs: how many items (the post and its comments) to read from one post, 1 to 3,000. Default 500: one request returns about 500 comments. Raise it to get more — above 500 the post is read again under other sort orders (see Deep comments). Each comment is one \"comment\" event. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "deepComments": {
            "title": "Deep comments",
            "type": "boolean",
            "description": "For post URLs: when one request comes back with 480 or more comments, read the post again under the sort orders new, old, top, controversial and Q&A (at most 6 requests) and merge the comments. Each comment is delivered and charged once. Measured 2026-10-07 on two large posts: 497 → 1,700 and 492 → 1,288 comments. Only happens when \"Max comments per post URL\" is above 500. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "since": {
            "title": "Only items since",
            "type": "string",
            "description": "Stop at items older than this date (YYYY-MM-DD). (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "after": {
            "title": "Start after item",
            "type": "string",
            "description": "Start a listing after this Reddit item id instead of at its newest item: t3_… for posts, t1_… for comments (the fullname field of a row). (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "filterKeywords": {
            "title": "Filter keywords",
            "type": "array",
            "description": "Words or phrases to look for in the items read from every source (case-insensitive; every word must be present in the title, the body or the link). Each source × keyword gives one keyword result row; matching rows carry matchedKeywords and matchedIn. Free plan runs check the first one.",
            "items": {
              "type": "string"
            }
          },
          "onlyMatching": {
            "title": "Only matching items",
            "type": "boolean",
            "description": "Deliver only posts and comments that match a filter keyword. The others are read and counted but not delivered or charged."
          },
          "strictMatch": {
            "title": "Strict search matches",
            "type": "boolean",
            "description": "For keyword searches: deliver only results whose title, body or link really contain every word of the keyword. Reddit search also returns posts that match elsewhere (in a comment, for example); those are counted in the keyword result row but not delivered."
          },
          "indicatorKinds": {
            "title": "Indicator kinds",
            "type": "array",
            "description": "Which indicators to extract from the items (all when empty). One row per distinct value per source.",
            "items": {
              "type": "string",
              "enum": [
                "cve",
                "ipv4",
                "hash",
                "wallet",
                "email",
                "phone",
                "domain",
                "mentioned_user",
                "mentioned_subreddit"
              ],
              "enumTitles": [
                "CVE IDs",
                "IPv4 addresses",
                "File hashes",
                "Wallet addresses",
                "Emails",
                "Phone numbers",
                "Domains",
                "Mentioned users (u/…)",
                "Mentioned subreddits (r/…)"
              ]
            }
          },
          "incremental": {
            "title": "New items only (monitoring)",
            "type": "boolean",
            "description": "Remember the last item of each listing and return only newer items on the next run with the same monitor key. Because Reddit lists only the newest 1,000 items, a schedule with this switch is how a busy subreddit is collected completely; the source row says when a listing reached that limit before the saved position and how often to run. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "monitorKey": {
            "title": "Monitor key",
            "type": "string",
            "description": "Name of the saved position used by \"New items only\". Use a different key for each schedule that should keep its own position: any text works; each distinct name keeps its own position. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "outputFormat": {
            "title": "Output format",
            "enum": [
              "full",
              "minimal",
              "rag"
            ],
            "type": "string",
            "description": "Shape of the post and comment rows: full (every field), minimal (ids, address, date, author, text) or rag (Markdown text and links for LLM pipelines)."
          },
          "signals": {
            "title": "Signals (rule-based)",
            "type": "boolean",
            "description": "Add a signals object to every post and comment row: intent (question, seeking_recommendation, complaint, praise, purchase_intent, comparison, self_promotion, discussion), sentiment label and score, flags (wantsHelp, mentionsPrice, mentionsCompetitor, hasQuestion), your own labels, and the words that fired each rule. Computed by word lists and patterns inside the Actor — no model is called. English rules; other languages keep intent \"discussion\" and sentiment \"uncertain\". Adds the signals-evaluated event ($0.0005) per evaluated row. Free plan: on the 10 rows shown per source."
          },
          "competitorNames": {
            "title": "Competitor names",
            "maxItems": 200,
            "type": "array",
            "description": "Names to look for when signals are on (case-insensitive, whole words). A row that mentions one gets flags.mentionsCompetitor: true and the names in competitorsMentioned. Up to 200 names of at most 80 characters each; a longer name is left out.",
            "items": {
              "type": "string"
            }
          },
          "customLabels": {
            "title": "Custom labels",
            "type": "array",
            "description": "Your own labels when signals are on, for example [{\"label\": \"pricing\", \"anyOf\": [\"too expensive\", \"price increase*\", \"CVE-#-#\"]}]. Each entry of anyOf is a word or a phrase, matched whole and case-insensitively, with two wildcards: * for any letters or digits inside one word (vuln* finds vulnerability) and # for one or more digits (CVE-#-# finds CVE-2026-12345). A row gets labels.<label>: true when any entry is found. Regular expressions are not accepted: an entry written as /…/ is refused and reported in a notice row. Up to 50 labels, 20 entries per label, 80 characters per entry; labels read the first 5,000 characters of a text. Free plan: the first label only; paid Apify plans apply every label."
          },
          "ai": {
            "title": "AI layers",
            "type": "array",
            "description": "A separate, optional layer on top of the rule-based signals: a language model reads the text, in any language. analysis adds ai.sentiment, ai.intent, ai.emotion, ai.flags, ai.category and ai.language to post and comment rows ($0.0005 each); labels answers your own questions below — AI labels come on top of the item analysis: picking labels switches analysis on for the same posts and comments, and each item is charged ai-analyzed ($0.0005) plus ai-label ($0.0001) per label; translation adds an English translation of non-English items ($0.002 each, the first 800 characters of the text); threadSummary writes one summary row per post URL ($0.02); userBrief ($0.03), subredditDigest ($0.05) and keywordInsight ($0.02) add a written summary to the profile and keyword rows, each statement with the addresses of the posts it rests on. Charged only after the model answered and the answer passed the checks. Turning a layer on sends the text of the public posts and comments read by this run to DeepSeek's API (DeepSeek is a company based in China) and nowhere else. Leave empty to send nothing. (paid Apify plans only — free plan runs ignore this and say so)",
            "items": {
              "type": "string",
              "enum": [
                "analysis",
                "labels",
                "translation",
                "threadSummary",
                "userBrief",
                "subredditDigest",
                "keywordInsight"
              ],
              "enumTitles": [
                "Analysis per post and comment (sentiment, intent, emotion, flags, category, language)",
                "Your own questions per post and comment (AI labels) — on top of the analysis, which this switches on",
                "English translation of non-English posts and comments",
                "Thread summary (post URLs)",
                "User brief (users)",
                "Subreddit digest (subreddits)",
                "Keyword insight (keywords, filter keywords)"
              ]
            }
          },
          "aiLabels": {
            "title": "AI labels (your own questions)",
            "type": "array",
            "description": "Questions a model answers for every post and comment when \"labels\" is among the AI layers, for example [{\"label\": \"churn_risk\", \"question\": \"Does the author say they will stop using a product?\"}, {\"label\": \"stage\", \"question\": \"Where is the author in buying?\", \"options\": [\"researching\", \"comparing\", \"decided\", \"not_buying\"]}]. Without options the answer is true or false; with options it is one of them. The answer is in ai.labels.<label>. AI labels come on top of the item analysis: with \"labels\" picked, \"analysis\" runs for the same posts and comments too, and each item is charged \"ai-analyzed\" ($0.0005) plus \"ai-label\" ($0.0001) per label. Up to 10 labels; a label name is letters, digits, _ or -; a question is cut at 200 characters; up to 8 options of 40 characters each. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "aiMaxItems": {
            "title": "AI: max posts and comments",
            "minimum": 1,
            "maximum": 20000,
            "type": "integer",
            "description": "The most posts and comments one run sends to the model (1 to 20,000, default 2,000). Past it the run goes on without the AI layers for single items, and the limits row says so. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "redditClientId": {
            "title": "Reddit API client ID",
            "type": "string",
            "description": "Client ID of your own Reddit app (reddit.com/prefs/apps, type \"script\" or \"web app\"). With the client secret and the User-Agent below, the run reads through Reddit's API with your key and fills score, upvote ratio, comment count, flair, comment depth and parent, author karma and subscriber count. App-only access (client_credentials): the Actor never logs in as you, takes no password and only reads. Beta: built from Reddit's published documentation; not yet verified with a live key. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "redditClientSecret": {
            "title": "Reddit API client secret",
            "type": "string",
            "description": "Client secret of the same Reddit app. Stored encrypted by Apify; never written to the log, the dataset or the run's key-value store. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "redditUserAgent": {
            "title": "Reddit API User-Agent",
            "type": "string",
            "description": "The User-Agent Reddit asks API clients to send, in its form: <platform>:<app ID>:<version> (by /u/<your Reddit username>), for example web:com.example.myapp:v1.0 (by /u/yourname). Required for the API key layer: the Actor does not make one up. When it is missing or not in this form, the run reads the public feeds instead and the limits row says why. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "apiRequestsPerMinute": {
            "title": "API requests per minute",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "Pace for requests sent with your Reddit API key (1 to 100, default 80). Reddit allows 100 per minute per key, averaged over 10 minutes. Lower it when the same key is also used elsewhere. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "apiMaxRequests": {
            "title": "Max API requests",
            "minimum": 1,
            "type": "integer",
            "description": "The most requests this run may send with your Reddit API key, the token request included (no limit when empty). When it is reached the run continues over the public feeds. (paid Apify plans only — free plan runs ignore this and say so)"
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Apify Proxy settings. Reddit allows one request per IP per minute on its public feeds, so every request of this Actor goes out on a new proxy session; keep Apify Proxy on. The default datacenter proxy is what the Actor was measured with."
          }
        }
      },
      "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "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
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}