Find Reddit Questions Worth Answering, Then Build a Review Queue
A useful Reddit question monitor creates a review queue, not an automatic reply target list. Search selected communities and, where suitable, inspect new-post listings. Save post IDs across runs, separate unanswered questions from noisy matches, and read the thread and community rules before anyone responds.
I founded Serpent API, whose search, listing and comment contracts supply this example. The October 1 documentation review and illustrative fixtures support the workflow; Reddit’s access rules were rechecked October 5, but no live monitoring recall or production response rate was measured for this article.
Serpent API’s Reddit search, subreddit listing and comments endpoints let you discover public posts, follow communities you know, and read comments only for selected threads. The workflow below turns those calls into a runnable Python monitor with expected parsed output, a daily budget and coverage checks. It compares official Reddit access, a dedicated monitoring product and an Apify actor using their published terms, checked October 1, 2026. For a wider vendor shortlist, see the Reddit API provider guide.
Define which subreddit questions you want to find
Write a one-sentence decision rule such as: “Show new, public questions in r/marketing about tracking brand mentions, and send a human only posts where a helpful, disclosed answer would be relevant.” That definition is narrower than “mentions a brand.” It determines your phrase list, community allowlist and review rules. A customer-support monitor, a content-research monitor and a sales-prospecting monitor need different ethics and different false-positive tolerances.
Start with a few phrase families: problem language (“how do I track …”), comparison language (“which tool …”), and failure language (“why is … not working”). Keep your own brand terms in a separate lane; someone asking a generic workflow question may never use your product name. Review the first few runs by hand and remove phrases that mostly surface unrelated topics. A post title ending in a question mark is useful evidence, but many genuine questions do not use one, and a rhetorical question can still be irrelevant.
| Signal | Candidate rule | Why it needs review |
|---|---|---|
| Query phrase | Search several ways a reader describes the problem | Search ranking and wording change which posts appear. |
| Community | Allowlist the subreddits you understand | Serpent search has no documented subreddit filter; apply it client-side. |
| Question form | Use words such as how, why, which, what or “?” | A title heuristic misses some questions and admits some noise. |
| Newness | Store first-seen post IDs and timestamps | Results can recur across phrases and later runs. |
| Thread context | Open selected comments | A reply may already answer the question or change its meaning. |
Which Reddit API endpoints should the monitor use?
Search discovers candidates. GET /api/reddit/search?q=...&limit=... accepts a phrase and a limit from 1 to 100. Its results are deliberately thin post hits: ID, title, author, subreddit, permalink, rank and a few public flags. Search does not return a post body, score, comment count or the text of comments. The current public contract does not document a subreddit, time or sort parameter for this endpoint. Do not add undocumented parameters to a monitor and assume they were applied. See the search field contract.
Posts gives a community feed. GET /api/reddit/posts?subreddit=python&sort=new&limit=25 returns a listing with richer post fields: title, body on text posts, created time, count of comments, permalink and state flags. This is useful if your monitor cares about the newest questions in a known community even when search misses a phrase. It is a separate billable call; sort=new is documented here, while it is not a documented search control. Listing limit is 1–100 synchronously and determines the billed 25-record blocks. See the listing contract.
Comments explains a selected thread. Call GET /api/reddit/comments with the candidate's subreddit and base36 post_id. Request tree=true if reply nesting matters; omit it for a flat list. The envelope includes count returned and total_comments when Reddit states it. They are not the same quantity. A 25-comment sample can show that the question was already answered; it cannot prove you read a busy thread in full. See the comments contract.
Build a subreddit question monitor in Python
The compact script below runs one pass over a phrase list. It screens subreddit and title locally, deduplicates on post id, and opens at most two newly selected threads for comments. Set INCLUDE_LISTINGS=1 to add one sort=new listing for each watched community; both discovery lanes enter the same queue. It writes a JSON file of IDs so the next run can suppress repeats. Set SERPENT_API_KEY and install requests; change the phrases and allowlist to match your use case. By default each run makes up to eight search calls and two comments calls; the optional lane adds three listing calls. The code does not send messages or post to Reddit.
import json
import os
from datetime import datetime, timezone
from pathlib import Path
import requests
BASE = "https://apiserpent.com/api/reddit"
KEY = os.environ["SERPENT_API_KEY"]
PHRASES = [
"how to track brand mentions", "monitor subreddit questions",
"best way to find customer questions", "reddit social listening",
"which reddit monitoring tool", "why reddit search misses posts",
"find unanswered reddit questions", "track product feedback reddit",
]
COMMUNITIES = {"marketing", "socialmedia", "saas"}
QUESTION_WORDS = ("how ", "why ", "what ", "which ", "where ", "can ", "does ")
SEEN_PATH = Path("reddit-question-seen.json")
REVIEW_PATH = Path("reddit-question-review.jsonl")
COMMENT_BUDGET_PATH = Path("reddit-comment-budget.json")
INCLUDE_LISTINGS = os.environ.get("INCLUDE_LISTINGS") == "1"
def get(path, params):
response = requests.get(BASE + path, params=params,
headers={"X-API-Key": KEY}, timeout=60)
response.raise_for_status()
payload = response.json()
if payload.get("success") is not True:
raise ValueError(f"Unusable {path} response")
return payload
def is_question(title):
text = (title or "").strip().lower()
return bool(text) and ("?" in text or text.startswith(QUESTION_WORDS))
seen = json.loads(SEEN_PATH.read_text()) if SEEN_PATH.exists() else {}
today = datetime.now(timezone.utc).date().isoformat()
budget = (json.loads(COMMENT_BUDGET_PATH.read_text())
if COMMENT_BUDGET_PATH.exists() else {})
if budget.get("date") != today:
budget = {"date": today, "comment_calls": 0}
selected = {}
short_runs = []
def consider(row, source):
if not isinstance(row, dict):
return
post_id = row.get("id")
community = (row.get("subreddit") or "").lower()
if (not post_id or post_id in seen or post_id in selected
or community not in COMMUNITIES
or not is_question(row.get("title"))):
return
selected[post_id] = {
"id": post_id, "title": row.get("title"),
"subreddit": community, "permalink": row.get("permalink"),
"found_by": source,
}
for phrase in PHRASES:
data = get("/search", {"q": phrase, "limit": 25})
rows = data.get("results")
if not isinstance(rows, list):
raise ValueError("Search results were not a list")
if data.get("delivery"):
short_runs.append({"phrase": phrase, "delivery": data["delivery"]})
for row in rows:
consider(row, f"search: {phrase}")
if INCLUDE_LISTINGS:
for community in sorted(COMMUNITIES):
data = get("/posts", {"subreddit": community,
"sort": "new", "limit": 25})
rows = data.get("posts")
if data.get("subreddit", "").lower() != community or not isinstance(rows, list):
raise ValueError("Subreddit listing identity or rows were unusable")
if data.get("delivery"):
short_runs.append({"community": community,
"delivery": data["delivery"]})
for row in rows:
consider(row, f"new listing: r/{community}")
remaining_comment_calls = max(0, 2 - budget["comment_calls"])
for item in list(selected.values())[:remaining_comment_calls]:
# Reserve the daily call before sending it, including an unsuccessful read.
budget["comment_calls"] += 1
COMMENT_BUDGET_PATH.write_text(json.dumps(budget))
thread = get("/comments", {
"subreddit": item["subreddit"], "post_id": item["id"],
"limit": 25, "tree": "true",
})
if not isinstance(thread.get("comments"), list):
raise ValueError("Comments were not a list")
if thread.get("post_id") != item["id"]:
raise ValueError("Thread identity did not match")
item["comments_returned"] = thread.get("count")
item["comments_stated_total"] = thread.get("total_comments")
item["comment_delivery"] = thread.get("delivery")
now = datetime.now(timezone.utc).isoformat()
with REVIEW_PATH.open("a") as review_file:
for item in selected.values():
review_file.write(json.dumps({**item, "first_seen": now}) + "\n")
for item in selected.values():
seen[item["id"]] = now
SEEN_PATH.write_text(json.dumps(seen, indent=2, sort_keys=True))
print(json.dumps({"new_candidates": list(selected.values()),
"short_observations": short_runs}, indent=2))
Illustrative parsed output, not a live run of these phrases:
{
"new_candidates": [
{
"id": "1abcde",
"title": "How can I track customer questions in a subreddit?",
"subreddit": "marketing",
"permalink": "/r/marketing/comments/1abcde/example/",
"found_by": "search: monitor subreddit questions",
"comments_returned": 12,
"comments_stated_total": 18,
"comment_delivery": {"requested": 25, "returned": 12,
"reason": "fewer_available"}
}
],
"short_observations": []
}
Those values are fictional and illustrate the shape of a decision record, not a captured thread. The script appends all candidates to a local JSONL review queue and reserves at most two comment calls per UTC day across scheduled runs; the budget file records an attempted call before it is sent. Its seen file is a simple starting point. In production, use an atomic database upsert on post ID and a shared daily budget so two workers cannot duplicate alerts or overspend. Preserve the date, phrase and raw result separately. A comment count lower than total_comments does not automatically mean a failed call; the stated total and currently readable comments can differ. Read any delivery block before calling a sample complete.
The optional new-post lane uses /api/reddit/posts?subreddit=...&sort=new&limit=25 and checks the returned community before adding rows to the same seen store and title triage. Search runs first, so a post found by both lanes keeps its search provenance in this small example; keep both discovery sources in a production event log if lane-level recall matters. A listing is still a sampled first window, and the option adds one charged 25-record block per community per run. If one call fails, this demonstration stops instead of marking the unseen community as quiet. The Reddit search access guide explains how this third-party approach differs from official access.
How much does subreddit monitoring cost?
Here is a reproducible 30-day worksheet: eight phrase searches, four runs a day, and a shared cap of two selected threads a day opened at limit=25. The sample script enforces that daily cap with a local budget file. That is 8 × 4 × 30 = 960 search calls and at most 2 × 30 = 60 comments calls. Search is flat per call at $0.12 per 1,000 Default calls. Comments are $0.12 per 1,000 calls for each started block of 25 requested comments. At the full two-per-day cap, the result is 960 × $0.00012 + 60 × $0.00012 = $0.1224 in metered usage. The initial deposit and your live balance are separate from usage; see the pricing page for account terms.
| 30-day plan | Search calls | Comments calls | Default usage | What is excluded |
|---|---|---|---|---|
Base sample, comments limit=25 | 960 flat calls | 60 × 1 block | $0.1224 | Subreddit listings, additional threads, storage, alerts and labor |
Same sample, comments limit=100 | 960 flat calls | 60 × 4 blocks | $0.1440 | More requested comments still do not guarantee a full thread |
Add three new listings each run at limit=25 | 960 flat calls | 60 × 1 block; plus 360 listing calls | $0.1656 | 3 communities × 4 runs × 30 days = 360 extra listing blocks |
Method: pricing and depth rules from Serpent's public Reddit contract, checked October 1, 2026. The listing row adds 360 × $0.00012 = $0.0432. These are pricing illustrations, not measured recall, delivered post counts or a performance benchmark. At limit=26, one comments or listing call costs two blocks, so choose a 25 boundary deliberately. Also check your account's actual request allocation with GET /api/status; a listed ceiling is not a throughput promise.
Which Reddit monitoring option fits your job?
The linked official product and pricing pages were checked on October 1, 2026. This table compares the workflow each option can support and leaves unlike billing units visible. It does not rank delivery quality. Reddit's access rules are moving: its September 30, 2026 developer announcement says new public API access requests stop on October 31, 2026, with later stages in 2027. Verify the policy before a new build.
| Option | Question-monitoring fit | Published unit or access | Trade-off to test |
|---|---|---|---|
| Reddit Developer Platform / Data API | Best for a community-installed app or approved official data use; Devvit capabilities are tied to installed communities | Platform permissions and approved access; commercial Data API use requires permission and contract under Reddit terms. No current self-serve commercial retail rate is published on these pages. | Check app scope and current migration timeline. Official access is preferable where your use qualifies. |
| Serpent Reddit endpoints | Build your own external search → review → selected-comment loop | Search $0.12/1K calls flat; posts/comments $0.12/1K per requested 25-record block, Default | Search hits are thin; no documented subreddit/time filter or direct comment search. Coverage and thread completeness must be measured. |
| redditapis.com search and monitoring | Dedicated keyword alerts plus post/comment search | $0.002 per read/search request; separate monitor plans: free one keyword, Starter $19/month for 15 keyword monitors, Growth $49/month for 50, subject to plan terms | Its search product says it can search comment bodies. A managed alert may save engineering time; read allowance and match rules. |
| Apify moxlade Reddit actor | Subreddit/date inputs and scheduled collection of post and comment records | Actor lists $2 per 1,000 post records and $1 per 1,000 comments; actor or run costs need checkout review | Record billing and scheduled actor runs suit collection jobs; compare data fields and actual returned records. |
For the same 1,020 read requests in the base illustration, redditapis.com's published $0.002/read would allocate $2.04 in read charges if all calls fall under that rate. Its keyword monitor is a separate subscription and may replace the polling work rather than use those 1,020 calls. Apify charges by delivered record, so there is no honest conversion from the 1,020 requested calls to its invoice without knowing delivered posts/comments. Reddit's official route has no current public commercial checkout price on the cited pages. If a managed alert saves several hours of engineering and moderation, its higher direct price may be the better deal. Serpent's usage price is small, but you own the queue, coverage checks and review work.
What can a subreddit monitor miss?
Search recall is unmeasured. A query can miss a post because of wording, ranking, timing or access. A zero-result search is one observation, never proof no question exists. Keep a second discovery lane from sort=new listings in your highest-priority communities, then compare how many relevant IDs each lane finds. That is your own empirical coverage estimate for your chosen communities and period.
Short delivery is not a full sample. If count is below requested limit, inspect a top-level delivery block when present. It can explain a shorter result set or an incomplete pull. Record the returned rows and the shortfall together. Do not turn the absence of a candidate in a short response into a confident negative. HTTP 200 by itself is not the acceptance test.
Threads change after you read them. Comments arrive later, moderators remove posts, and a discussion can shift direction. A comment sample may be flat or a nested tree; in tree mode count is the total comments returned, while the top-level array only contains root comments. A listed total_comments can exceed the sample. If you must act on a thread, open the source in Reddit and read the context, community rules and any newer replies. Do not auto-post a promotional answer just because a keyword matched.
Content and privacy boundaries matter. Restrict monitoring to a defensible purpose and the communities whose rules you understand. Respect deleted or removed material and your chosen retention period. Avoid collecting author histories when the question itself is enough. For user research, summarize themes and cite public posts carefully; for customer help, disclose your affiliation. The brand-monitoring overview and Reddit citation guide cover adjacent goals, but neither replaces human context review.
A useful acceptance test
- Pick three communities and a week of current posts. Manually label a small set of relevant questions and non-questions; record URLs and dates.
- Run your phrase monitor and a
newlisting lane during that week. Count the labeled question IDs each lane found and which were missed. Inspect returned parsed rows, not HTTP status. - Review alerts for duplicates, irrelevant communities, old posts, removed threads and comment context. Measure analyst minutes per useful question, not only API cost.
- Repeat after changing phrases or communities. Do not call one small test a sitewide recall guarantee, and recheck vendor price and access terms before buying.
That test is the point where a low-cost API plan becomes a useful monitoring service. This article does not include a multi-provider recall benchmark, so no option is credited with catching more questions than another.
Start with a small question queue
Use a few phrases and communities, inspect the returned post IDs and titles, and open comments only for selected threads. Keep your own evidence of missed and duplicate questions.
Get an API keyFAQ
Can Serpent search only one subreddit or search comments directly?
The current Serpent Reddit search contract accepts q and limit, and returns thin post hits. It does not expose a documented subreddit, time or sort filter, or direct comment-body search. Screen the returned subreddit and title in your application. Use the subreddit posts endpoint for a new-post listing and the comments endpoint for a selected post.
How do I avoid alerting on the same Reddit question twice?
Store each qualifying post id as a durable key and record the first-seen time. A post can appear in multiple query phrases or later runs. Keep the title, subreddit, permalink, query phrase and observation time as separate fields. Do not deduplicate on title alone.
Does a zero-result search prove no one asked the question?
No. It means no usable result was returned for that sampled query and call. Query wording, ranking, deleted or restricted content, short delivery and changes between runs can all affect what is observed. Inspect results and any delivery block, and report monitor coverage as sampled rather than complete.
What does a 30-day monitor with 960 searches and 60 comment reads cost?
At Serpent Default pricing, 960 flat search calls cost $0.1152 and 60 comments calls at limit=25 cost $0.0072, totaling $0.1224 in metered usage. If all 60 comments calls request limit=100, each uses four 25-comment blocks and the total is $0.144. This excludes any subreddit listing calls, extra reads, storage and developer time, and says nothing about delivered coverage.
Is the official Reddit API a better choice for my community app?
Often, if your app is installed in a community and works within Reddit’s documented Developer Platform capabilities, or if you have approved Data API access for your use. Official access carries platform permissions and policy obligations. A third-party read service may fit external monitoring, but it is not a substitute for official app permissions or a guarantee of complete coverage.






