Reddit is the largest public database of unfiltered user opinions about software products. For SaaS market research, Reddit threads reveal pain points, feature requests, and competitive sentiment that surveys and interviews miss. The use case is research, not lead generation -- cold outreach to Reddit users is spam and will get your accounts banned.
What Reddit data reveals for SaaS research
- Pain points: "I switched from X because..." threads reveal real frustrations
- Feature priorities: "I wish X had..." comments rank features by actual demand
- Pricing sensitivity: "X is too expensive for..." threads show willingness to pay
- Competitive landscape: "X vs Y" threads show how users compare products
- Adoption triggers: "I finally started using X when..." reveals conversion moments
Structured search vs raw scraping
Raw Reddit scraping via PRAW or Pushshift is rate-limited, and Reddit tightened its API terms in 2024. A structured search API returns Reddit thread titles, post text, subreddit, score, comment counts and URLs as JSON with predictable pricing, so there is no scraper to maintain. You remain responsible for how you use the data.
import requests, os
API = "https://api.scavio.dev"
H = {"Authorization": f"Bearer {os.environ['SCAVIO_API_KEY']}"}
def research_competitor(product_name: str):
"""Find Reddit discussions about a SaaS product."""
queries = {
"review": f"{product_name} review",
"alternative": f"{product_name} alternative",
"switched": f"switched from {product_name}",
"pricing": f"{product_name} pricing too expensive",
"vs": f"{product_name} vs",
}
all_threads = []
for query_type, q in queries.items():
resp = requests.post(f"{API}/api/v1/reddit/search",
headers=H, json={"query": q}, timeout=60)
threads = resp.json()["data"].get("results", [])
for t in threads:
all_threads.append({
"query_type": query_type,
"title": t.get("title", ""),
"snippet": (t.get("text") or "")[:200],
"subreddit": t.get("subreddit", ""),
"score": t.get("score", 0),
"num_comments": t.get("num_comments", 0),
"url": t.get("url", ""),
})
return all_threads
# 5 queries x 1 credit = 5 credits per competitor ($0.01 on Growth yearly, $0.05 pay-as-you-go)
threads = research_competitor("Notion")
for t in threads[:5]:
print(f"[{t['query_type']}] r/{t['subreddit']} {t['title'][:80]}")Building a competitive intelligence dashboard
def competitive_landscape(competitors: list):
"""Map Reddit sentiment across competitors."""
landscape = {}
for comp in competitors:
threads = research_competitor(comp)
landscape[comp] = {
"total_threads": len(threads),
"review_threads": len([t for t in threads if "review" in t["query_type"]]),
"alternative_threads": len([t for t in threads if "alternative" in t["query_type"]]),
"churn_threads": len([t for t in threads if "switched" in t["query_type"]]),
"pricing_threads": len([t for t in threads if "pricing" in t["query_type"]]),
}
return landscape
# 5 competitors x 5 queries each = 25 API calls = 25 credits ($0.05 on Growth yearly, $0.25 pay-as-you-go)
competitors = ["Notion", "Asana", "Monday", "ClickUp", "Linear"]
landscape = competitive_landscape(competitors)
for comp, data in landscape.items():
print(f"{comp}: {data['churn_threads']} churn threads, {data['pricing_threads']} pricing complaints")Ethical guidelines
- Use for research only: understanding market, not harvesting leads
- Do not DM users who post about competitor problems
- Do not fake Reddit accounts to post about your own product
- Cite Reddit threads as qualitative data, not as statistically significant evidence
- Respect that Reddit opinions skew toward power users and may not represent your full market