Global Reddit search, scoped subreddit passes, comment pulls on high-signal threads, then dedupe and export. Running example: a fictional Notion competitor check — swap in your product and subreddit list.
You'll need an API key. Try a search in the Playground. New to Reddit access? See How to get a Reddit API key or smoke-test in the free Reddit research tool. Search mechanics (parameters, pagination, global vs scoped routes) live in the Reddit search API guide.
Build the query matrix
Write one sentence the sprint must answer, then list 8–15 query variants:
| Research goal | Example question | Bad query | Better query |
|---|---|---|---|
| Competitive positioning | Why do teams leave Notion for Coda? | notion | switching from notion |
| Feature gaps | What do users want that our roadmap lacks? | project management | wish notion had OR notion missing |
| Pricing sensitivity | Are we expensive vs incumbents? | expensive | notion too expensive |
| Launch monitoring | Did v2.4 change sentiment? | acme | acme v2.4 with timeframe=week |
Group variants:
- Brand — product name, common misspellings.
- Alternatives —
{product} alternative,best {category} tool. - Switching —
switching from {product},migrated from {product},leaving {product}. - Pain —
{product} slow,{product} pricing,{product} support.
Search Reddit
Start with site-wide GET /v1/reddit/search. This catches cross-posts and communities you would not guess from subreddit names alone.
curl -sS \
-H "x-api-key: $SOCIALFETCH_API_KEY" \
-G "https://api.socialfetch.dev/v1/reddit/search" \
--data-urlencode "query=best project management software" \
--data-urlencode "sortBy=top"| Parameter | Values | When to use |
|---|---|---|
sortBy | relevance, new, top | top + timeframe=year for battlecard fodder; new for launch week |
timeframe | day, week, month, year, all | Pair with sortBy=top; skip on new |
cursor | opaque string from data.page.nextCursor | Next page — do not construct manually |
Full spec and pagination patterns: Reddit search API · API reference.
Paginate until data.page.hasMore is false or you hit your credit budget:
Check data.page.hasMore — do not infer completion from data.totalResults alone.
Scope to subreddits
Global search is noisy. Run a second pass in communities where buyers post.
| Category | Example subreddits | What you learn |
|---|---|---|
| B2B SaaS | r/SaaS, r/startups, r/Entrepreneur | Pricing, churn, stack choices |
| Role-specific | r/sysadmin, r/devops, r/productivity | Workflow constraints incumbents ignore |
| Product-specific | r/Notion, r/ObsidianMD, r/selfhosted | Power-user requests, workarounds |
| Vertical | r/realestate, r/ecommerce, r/legaltech | Industry-specific objections |
Tally post.subreddit from global results and promote the top five. Validate before cron jobs:
Reference: Get subreddit.
Scoped keyword search — GET /v1/reddit/subreddits/search when you know the community:
Reference: Subreddit search. Use sort=comments for debate threads. Search frustrated or cancel inside r/YourProductSubreddit before searching competitor names globally.
Browse a feed — when you want hot posts without a keyword:
sort value | Typical research use |
|---|---|
top | Highest engagement in the timeframe window |
new | Fresh complaints after a competitor launch |
hot | Active engagement now |
rising | Early signal before front page |
Reference: Subreddit posts. Subreddit names must match Reddit casing (SaaS not saas). Filter client-side by keyword list or metrics.commentCount threshold.
Pull comment threads
Comments hold objections, workarounds, and switching rationale. Pass a post URL:
Paginate with data.page.nextCursor until hasMore is false. Nested replies on each comment — flatten or walk the tree for your tool.
Reference: Reddit post comments. For scoring at scale, see social comments for sentiment analysis.
Pull selectively to save credits:
metrics.commentCountabove 20metrics.scoreabove 50 for niche subreddits (adjust per community)- Title matches a switching phrase from your query matrix
Batch and dedupe
Run query variants and merge results. Dedupe by post.id or canonical url before analysis.
import { SocialFetchClient } from "@socialfetch/sdk";
const client = new SocialFetchClient({
apiKey: process.env.SOCIALFETCH_API_KEY!,
});
const product = "notion";
const queries = [
`${product} alternative`,
`switching from ${product}`,
`best ${product} competitor`,
];
const mentions = [];
for (const query of queries) {
const result = await client.reddit.search({ query, sortBy: "top", timeframe: "year" });
if (!result.ok) continue;
for (const post of result.value.data.posts ?? []) {
mentions.push({
query,
title: post.title,
subreddit: post.subreddit,
score: post.metrics?.score,
url: post.url,
});
}
}
console.log(mentions.length, "threads to review");Add timeframe, paginate inner loops when hasMore is true, and write meta.requestId on every row. For weekly monitoring, wrap in cron or QStash — same pattern as the social listening guide, with Reddit query matrices instead of cross-platform brand keywords.
Store rows your PM can sort
Normalize into flat rows for Airtable, Postgres, Sheets, or Notion:
| Column | Source field | Why |
|---|---|---|
| Theme | your taxonomy | "pricing", "performance", "missing feature" — manual or LLM-tagged |
| Evidence | url | Link back for quotes in decks |
| Weight | score, commentCount | Rank by engagement, not mention count |
| Freshness | createdAt / publishedAt | Deprioritize stale threads unless evergreen |
Export to CSV, or pipe title + bodyText + top comments into an LLM summary with the thread URL as citation. Keep requestId for audit.
Troubleshooting
Empty results but the thread exists in a browser
- Try scoped
subreddits/searchwith the subreddit from the URL. - Check
timeframe—dayon a year-old thread returns nothing withsortBy=top. - Query maxes at 512 characters; shorten long boolean strings.
not_found on subreddit or post lookups
- Casing:
Fitnessandfitnessdiffer. Copy the exact name from the address bar. - Deleted or quarantined content returns
not_found— not a billing bug. - Pass full
https://www.reddit.com/r/.../comments/...URLs to comments.
Duplicate threads in merged results
- Dedupe on
post.idbefore counting mentions. - Cross-posts share text but have different IDs — dedupe on
urlif you want one row per discussion.
Scores and counts look stale
- Each response is point-in-time. Re-fetch before quoting in a deck. Store
capturedAtalongsidescore.
lookup_failed or HTTP 503
- Not charged. Retry with backoff; include
meta.requestIdif you contact support. - Sequential pagination with modest concurrency is fine — bursting hundreds of parallel requests is unnecessary.
Rate limits
- Credits are the limit on metered routes. Under extreme concurrency you may get
503withRetry-After(not charged). ~500 concurrent requests is a courtesy ceiling.
Billing and boundaries
Each search page, subreddit feed page, and comment page is one credit (typically 1 per successful request). Completed lookups with zero posts still bill. No charge for pre-send validation errors, lookup_failed, or 503 temporarily_unavailable.
| Step | Calls | Credits (approx.) |
|---|---|---|
| 10 queries × 2 pages global search | 20 | 20 |
| 5 subreddits × 1 scoped search | 5 | 5 |
| 15 high-signal comment pulls | 15 | 15 |
| Total | 40 | 40 |
Public data only — lawful use under Terms. See Credits. Official Reddit rates vs Social Fetch: Reddit API pricing.
What you can build
- Competitive battlecards — weekly pull of
alternative to {product}andswitching from {product}with top comment quotes. - Feature prioritization — rank request themes by upvote-weighted frequency in product subreddits.
- Launch monitoring — alert on mention spikes (
sortBy=new,timeframe=week). - Churn autopsy feed — tag threads matching
cancel,refund,moved to. - Persona research — same product across r/sysadmin vs r/marketing to compare job-to-be-done language.
Next steps: Playground · Reddit hub · Reddit research recipe · Reddit API pricing · Pricing