Tutorial 3 of 4

Find Reddit Discussions Ranking on Google with Python

Discover high-traffic Reddit threads for any keyword - with traffic estimates and competitor sentiment analysis.

Reading time: 12 min Level: Beginner Updated: December 2025

The Reddit SEO Opportunity Most People Miss

If you've searched Google recently, you've probably noticed Reddit showing up everywhere. Reddit threads now appear in the Discussion Box, get cited in AI Overviews, and regularly claim top organic positions.

These aren't just random appearances. For commercial keywords like "best CRM software" or "project management tools," Reddit threads can receive tens of thousands of monthly visits from Google alone.

Here's what makes this interesting for SEO automation: these discussions contain real user opinions about your brand and your competitors. People are actively discussing which products they recommend, which ones disappointed them, and why.

In this tutorial, we'll build a Python script that:

What You'll Need

Before we start, make sure you have:

Why an API?

You could scrape Google and Reddit directly, but you'd be dealing with rate limits, CAPTCHAs, and constantly breaking selectors. An API handles all that complexity and gives you clean, structured data. The free tier gives you 15 requests to test with.

The Discovery Script

Let's start with a simple script that discovers Reddit discussions for a keyword. This is the foundation we'll build on.

reddit_discovery.py
import requests
import json

def discover_reddit_threads(keyword, api_key):
    """
    Find Reddit threads ranking on Google for a keyword.
    
    Args:
        keyword: The search term to analyze
        api_key: Your RapidAPI key
    
    Returns:
        dict: Thread data with traffic estimates and analysis
    """
    url = "https://reddit-traffic-and-intelligence-api.p.rapidapi.com/api/v2/discover-threads"
    
    headers = {
        "Content-Type": "application/json",
        "x-rapidapi-host": "reddit-traffic-and-intelligence-api.p.rapidapi.com",
        "x-rapidapi-key": api_key
    }
    
    payload = {
        "keyword": keyword,
        "max_threads": 10
    }
    
    response = requests.post(url, json=payload, headers=headers)
    return response.json()


# Example usage
if __name__ == "__main__":
    API_KEY = "your_api_key_here"
    
    result = discover_reddit_threads("crm software", API_KEY)
    
    print(f"Found {result['threads_discovered']} threads")
    print(f"Total estimated traffic: {result['summary']['estimated_monthly_traffic']:,}/month")
    
    for thread in result['threads']:
        print(f"\n[{thread['priority']}] {thread['title']}")
        print(f"  Traffic: ~{thread['estimated_traffic']:,}/month")
        print(f"  Source: {thread['source']} (Position {thread['position']})")

Run this and you'll see something like:

Sample Output

Found 8 threads
Total estimated traffic: 134,705/month

[HIGH] Best CRM for small business?
  Traffic: ~33,677/month
  Source: discussion_box (Position 0)

[HIGH] HubSpot vs Salesforce - honest opinions?
  Traffic: ~16,838/month
  Source: organic (Position 3)

[MEDIUM] Anyone using Pipedrive? Worth it?
  Traffic: ~8,419/month
  Source: organic (Position 5)

Adding Competitor Sentiment Analysis

Here's where it gets interesting. By passing in your brand and competitors, the API analyzes sentiment for each one across all discovered threads.

competitor_sentiment.py
import requests

def analyze_competitor_sentiment(keyword, your_brand, competitors, api_key):
    """
    Discover Reddit threads and analyze sentiment for specific brands.
    
    Args:
        keyword: Search term
        your_brand: Your company/product name
        competitors: List of competitor names
        api_key: Your RapidAPI key
    
    Returns:
        dict: Threads with brand-specific sentiment analysis
    """
    url = "https://reddit-traffic-and-intelligence-api.p.rapidapi.com/api/v2/discover-threads"
    
    headers = {
        "Content-Type": "application/json",
        "x-rapidapi-host": "reddit-traffic-and-intelligence-api.p.rapidapi.com",
        "x-rapidapi-key": api_key
    }
    
    payload = {
        "keyword": keyword,
        "your_brand": your_brand,
        "competitors": competitors,
        "max_threads": 10,
        "max_comments_per_thread": 10
    }
    
    response = requests.post(url, json=payload, headers=headers)
    return response.json()


def print_sentiment_report(data):
    """Print a formatted sentiment report."""
    print("=" * 60)
    print(f"SENTIMENT ANALYSIS: {data['keyword']}")
    print("=" * 60)
    
    for thread in data['threads']:
        analysis = thread.get('analysis', {})
        brands = analysis.get('brand_sentiments', {})
        
        if not brands:
            continue
        
        print(f"\n--- {thread['title'][:50]}...")
        print(f"    Traffic: ~{thread['estimated_traffic']:,}/month")
        
        for brand, sentiment in brands.items():
            pos = sentiment.get('positive', 0)
            neg = sentiment.get('negative', 0)
            
            print(f"\n    {brand}: +{pos} / -{neg}")
            
            if sentiment.get('praise'):
                print(f"      Praise: {', '.join(sentiment['praise'][:3])}")
            if sentiment.get('complaints'):
                print(f"      Complaints: {', '.join(sentiment['complaints'][:3])}")


# Example usage
if __name__ == "__main__":
    API_KEY = "your_api_key_here"
    
    result = analyze_competitor_sentiment(
        keyword="crm software",
        your_brand="Acme CRM",
        competitors=["HubSpot", "Salesforce", "Pipedrive"],
        api_key=API_KEY
    )
    
    print_sentiment_report(result)

Sample Output

============================================================
SENTIMENT ANALYSIS: crm software
============================================================

--- Best CRM for small business?...
    Traffic: ~33,677/month

    HubSpot: +15 / -8
      Praise: easy to use, good free tier, great integrations
      Complaints: expensive at scale, pushy sales team

    Salesforce: +4 / -12
      Praise: powerful features, industry standard
      Complaints: too complex, expensive, overkill for SMB

    Pipedrive: +13 / -3
      Praise: simple and focused, great for sales teams
      Complaints: limited marketing features

Finding Opportunities: Where You're Missing

The real value is finding high-traffic threads where competitors are mentioned but you're not. These represent conversations happening about your market where your brand is absent.

find_opportunities.py
def find_gaps(data, your_brand):
    """
    Find high-traffic threads where your brand isn't mentioned
    but competitors are.
    
    Args:
        data: API response from discover_threads
        your_brand: Your brand name
    
    Returns:
        list: Threads representing opportunities
    """
    opportunities = []
    
    for thread in data.get('threads', []):
        analysis = thread.get('analysis', {})
        brands = analysis.get('brand_sentiments', {})
        
        # Check if your brand is mentioned
        your_brand_mentioned = your_brand.lower() in [b.lower() for b in brands.keys()]
        
        # Check if any competitors are mentioned
        has_competitor_mentions = len(brands) > 0
        
        # High traffic + competitors mentioned + you're not = opportunity
        if not your_brand_mentioned and has_competitor_mentions:
            if thread.get('estimated_traffic', 0) > 1000:
                opportunities.append({
                    'title': thread['title'],
                    'url': thread['url'],
                    'traffic': thread['estimated_traffic'],
                    'priority': thread['priority'],
                    'competitors_mentioned': list(brands.keys()),
                    'why_matters': thread.get('why_matters', '')
                })
    
    # Sort by traffic (highest first)
    return sorted(opportunities, key=lambda x: x['traffic'], reverse=True)


# Example usage
if __name__ == "__main__":
    # Using data from previous example
    gaps = find_gaps(result, "Acme CRM")
    
    print(f"\nFound {len(gaps)} opportunities:\n")
    
    for gap in gaps:
        print(f"[{gap['priority']}] {gap['title']}")
        print(f"  Traffic: ~{gap['traffic']:,}/month")
        print(f"  Competitors: {', '.join(gap['competitors_mentioned'])}")
        print(f"  URL: {gap['url']}\n")

Understanding the Results

Let's break down what the API returns and how to interpret it:

Field What It Means
estimated_traffic Monthly visitors from Google. Calculated as search_volume x position_CTR. The CTR is included so you can verify.
source Where the thread appears: discussion_box (highest visibility), ai_overview, or organic
priority HIGH/MEDIUM/LOW based on traffic, position, and opportunity. HIGH = act on this first.
brand_sentiments Positive/negative counts plus extracted praise and complaints for each brand.
confidence How confident the sentiment analysis is (0-1). Higher = more data points.

About Traffic Estimates

Traffic numbers are estimates based on keyword search volume and position-based CTR rates. They're directionally accurate for prioritization, but don't treat them as exact. A thread showing 30,000/month is definitely getting more traffic than one showing 500/month.

Practical Applications

1. Competitive Intelligence Reports

Run this weekly for your core keywords. Track how sentiment shifts over time. When a competitor starts getting more complaints about pricing, that's your opening.

2. Content Gap Analysis

The "opportunities" output shows you exactly where to focus. If a thread has 30K monthly visitors discussing CRM options and you're not mentioned, that's content waiting to be created.

3. Community Engagement Prioritization

Don't waste time on low-traffic threads. Focus your Reddit engagement on discussions that actually rank on Google and drive traffic.

4. Battle Card Generation

The extracted praise/complaints give you real quotes for sales battle cards. "Users say Salesforce is 'overkill for SMB' and 'too complex'" - that's straight from the data.

Complete Script

Here's everything combined into a single, runnable script:

reddit_seo_discovery.py (complete)
"""
Reddit SEO Discovery Script
Find Reddit threads ranking on Google with traffic estimates and sentiment analysis.
"""

import requests
import json
from datetime import datetime


class RedditSEODiscovery:
    def __init__(self, api_key):
        self.api_key = api_key
        self.base_url = "https://reddit-traffic-and-intelligence-api.p.rapidapi.com"
        self.headers = {
            "Content-Type": "application/json",
            "x-rapidapi-host": "reddit-traffic-and-intelligence-api.p.rapidapi.com",
            "x-rapidapi-key": api_key
        }
    
    def discover(self, keyword, your_brand=None, competitors=None, max_threads=10):
        """Discover Reddit threads ranking for a keyword."""
        payload = {
            "keyword": keyword,
            "max_threads": max_threads,
            "max_comments_per_thread": 10
        }
        
        if your_brand:
            payload["your_brand"] = your_brand
        if competitors:
            payload["competitors"] = competitors
        
        response = requests.post(
            f"{self.base_url}/api/v2/discover-threads",
            json=payload,
            headers=self.headers
        )
        
        return response.json()
    
    def find_opportunities(self, data, your_brand):
        """Find threads where you're not mentioned but competitors are."""
        opportunities = []
        
        for thread in data.get('threads', []):
            brands = thread.get('analysis', {}).get('brand_sentiments', {})
            your_mentioned = your_brand.lower() in [b.lower() for b in brands.keys()]
            
            if not your_mentioned and brands and thread.get('estimated_traffic', 0) > 1000:
                opportunities.append({
                    'title': thread['title'],
                    'url': thread['url'],
                    'traffic': thread['estimated_traffic'],
                    'priority': thread['priority'],
                    'competitors': list(brands.keys())
                })
        
        return sorted(opportunities, key=lambda x: x['traffic'], reverse=True)
    
    def aggregate_sentiment(self, data):
        """Aggregate sentiment across all threads for each brand."""
        brand_totals = {}
        
        for thread in data.get('threads', []):
            brands = thread.get('analysis', {}).get('brand_sentiments', {})
            
            for brand, sentiment in brands.items():
                if brand not in brand_totals:
                    brand_totals[brand] = {
                        'positive': 0, 'negative': 0, 'neutral': 0,
                        'praise': [], 'complaints': []
                    }
                
                brand_totals[brand]['positive'] += sentiment.get('positive', 0)
                brand_totals[brand]['negative'] += sentiment.get('negative', 0)
                brand_totals[brand]['neutral'] += sentiment.get('neutral', 0)
                brand_totals[brand]['praise'].extend(sentiment.get('praise', []))
                brand_totals[brand]['complaints'].extend(sentiment.get('complaints', []))
        
        return brand_totals
    
    def print_report(self, data, your_brand=None):
        """Print a formatted discovery report."""
        print("\n" + "="*60)
        print(f"REDDIT SEO DISCOVERY: {data['keyword']}")
        print(f"Generated: {datetime.now().strftime('%Y-%m-%d %H:%M')}")
        print("="*60)
        
        # Summary
        summary = data.get('summary', {})
        print(f"\nThreads found: {data.get('threads_discovered', 0)}")
        print(f"Total estimated traffic: {summary.get('estimated_monthly_traffic', 0):,}/month")
        
        # Priority breakdown
        by_priority = summary.get('by_priority', {})
        print(f"Priority: {by_priority.get('HIGH', 0)} HIGH / {by_priority.get('MEDIUM', 0)} MEDIUM / {by_priority.get('LOW', 0)} LOW")
        
        # Top threads
        print("\n--- TOP THREADS ---")
        for thread in data.get('threads', [])[:5]:
            print(f"\n[{thread['priority']}] {thread['title'][:60]}")
            print(f"  Traffic: ~{thread['estimated_traffic']:,}/month | {thread['source']}")
        
        # Opportunities
        if your_brand:
            gaps = self.find_opportunities(data, your_brand)
            if gaps:
                print(f"\n--- OPPORTUNITIES ({len(gaps)} threads without {your_brand}) ---")
                for gap in gaps[:3]:
                    print(f"\n  {gap['title'][:50]}...")
                    print(f"  Traffic: ~{gap['traffic']:,}/month")
                    print(f"  Competitors present: {', '.join(gap['competitors'])}")
        
        # Aggregated sentiment
        sentiment = self.aggregate_sentiment(data)
        if sentiment:
            print("\n--- BRAND SENTIMENT SUMMARY ---")
            for brand, stats in sentiment.items():
                total = stats['positive'] + stats['negative'] + stats['neutral']
                if total > 0:
                    print(f"\n  {brand}: +{stats['positive']} / -{stats['negative']}")


# Main execution
if __name__ == "__main__":
    # Configuration
    API_KEY = "your_api_key_here"
    KEYWORD = "crm software"
    YOUR_BRAND = "Acme CRM"
    COMPETITORS = ["HubSpot", "Salesforce", "Pipedrive"]
    
    # Run discovery
    discovery = RedditSEODiscovery(API_KEY)
    result = discovery.discover(KEYWORD, YOUR_BRAND, COMPETITORS)
    
    # Print report
    discovery.print_report(result, YOUR_BRAND)
    
    # Save raw data
    with open("discovery_results.json", "w") as f:
        json.dump(result, f, indent=2)
    print("\nFull data saved to discovery_results.json")

Try It Yourself

The free tier includes 15 API calls - enough to test with your own keywords and competitors.

Get Free API Key

Next Steps

Now that you can discover discussions and analyze sentiment, the final step is putting it all together into automated reports that run on schedule.

Continue the Series