# Reddit Sentiment Tracker (`deepmine/reddit-sentiment-tracker`) Actor

Reddit sentiment analysis for brands: every Reddit brand or keyword mention scored positive, negative or neutral, with a sentiment % breakdown, a verdict and the top posts per keyword. A Reddit sentiment tracker and sentiment API for social listening, pay per mention.

- **URL**: https://apify.com/deepmine/reddit-sentiment-tracker.md
- **Developed by:** [DeepMine](https://apify.com/deepmine) (community)
- **Categories:** Social media, SEO tools, Automation
- **Features:** Limited permissions
- **Stats:** 3 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.59 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Reddit Sentiment Tracker — Know If Reddit Likes You

**Search Reddit for any keyword and find out: is the sentiment positive, negative, or mixed? Every mention scored, every keyword summarised.**

One run. Every mention tagged. Sentiment breakdown per keyword — so you know whether Reddit's opinion is working for you or against you.

**Real rows, run on 2026-10-30 (keywords `Notion app`, `Linear app`, `Figma`):** "Code Layers - an obvious step in the evolution of prototyping" (r/FigmaDesign, `Figma`, negative, -0.18), "Is my UI placement for this design tool logical?..." (r/UXDesign, negative, -0.44), "I built a searchable library of 3.3M real UI screens..." (r/SideProject, positive, 0.29). That run kept 63 mentions for $0.0498 at the Starter price ($0.79 per 1,000 mentions); see [Real rows](#real-rows).

***

### What It Does

Reddit is where unfiltered opinions live. But raw mentions don't tell you much — you need to know whether those mentions are good or bad. This actor searches Reddit for your keywords, scores every post and comment using a hybrid sentiment model (AFINN keyword scoring + Reddit's own upvote ratio as a community signal), and returns a clear breakdown: what percentage of mentions are positive, negative, or neutral.

***

### How Sentiment Is Scored

Two signals combined:

**1. Text scoring (AFINN word list)**
Each post or comment is scored based on the emotional weight of its words. "Amazing", "love", "recommend" push the score positive. "Terrible", "broken", "waste" push it negative. A negation flips the next word ("don't hate" counts as positive), and common emoji count too. The score is normalized by text length so short and long posts are comparable.

**2. Upvote ratio (community signal)**
Reddit's upvote ratio is the community's collective verdict. A post at 95% upvote ratio is almost certainly a positive reception. A post at 25% is controversial or disliked. This modifier adjusts the text score up or down based on how the community voted — catching cases where sarcasm or context defeats keyword matching.

**Result:** `positive` / `negative` / `neutral` label + numeric score per mention. The score is text score per word + (upvote ratio − 0.75) for posts: above 0.05 is positive, below −0.05 negative, anything in between neutral. The scoring is the same as in earlier versions, so a mention gets the same label and score.

***

### Output

Each run gives you **mentions** (posts and comments, each scored, ranked by buzz score) in the dataset, and **one sentiment summary row per keyword** (`type` = `summary`), free, in the `SUMMARY` record (the "Summary record" link on the Output tab, JSON) and, with **Add summary rows to the dataset** on, as rows in the run's own `summary` dataset. Its table link is in the run's `OUTPUT` record (the "Run summary" link on the Output tab): `summaryDataset.itemsUrl` for the rows, `summaryDataset.consoleUrl` to open it in Apify Console. Up to version 2.0.4 the summary rows also came after the mentions in the main dataset; read them from the `summary` dataset now.

#### Real rows

A run on 2026-10-30 (build 2.0.21; keywords `Notion app`, `Linear app`, `Figma`; 30 posts each, newest first, past week). Rows from it that are about the brand, with their rank in the run:

| rank | subreddit | sentiment | sentimentScore | score | numComments | matchedKeywords | title |
|---|---|---|---|---|---|---|---|
| 5 | TransitDiagrams | positive | 0.2 | 39 | 11 | Figma | \[OC] Hanoi Metro Diagram (operational and U/C lines) in Singapore's style, made with Figma (v2) |
| 6 | FigmaDesign | negative | -0.18 | 1 | 10 | Figma | Code Layers - an obvious step in the evolution of prototyping |
| 7 | UXDesign | negative | -0.44 | 0 | 3 | Figma | Is my UI placement for this design tool logical? I worry that it's too different from Figma… |
| 10 | SideProject | positive | 0.29 | 1 | 4 | Figma | I built a searchable library of 3.3M real UI screens from 460k apps and sites |
| 11 | SideProject | positive | 0.15 | 3 | 7 | Notion app | Here's another app only me and my mom will use - My first little personal project… |

**What that run cost:** it kept 63 of the 85 mentions found under a $0.05 spending limit, $0.0498 at the Starter price ($0.79 per 1,000 mentions); all 85 would have cost $0.067. The label is a word-based score of each post's own text, so a post that only names the brand in passing is scored on its whole text; in the example run 54 of the 63 rows held every word of their keyword. Set **Match** to *Every word of the keyword* or *Exact phrase* to drop the rest; they aren't delivered and aren't charged.

#### Mentions (one per post or comment)

| Field | Description |
|---|---|
| `sentiment` | `positive`, `negative`, or `neutral` |
| `sentimentScore` | Numeric score (positive = positive, negative = negative) |
| `contentType` | `post` or `comment` |
| `matchedKeywords` | Which of your keywords matched this mention |
| `title` | Post title (for a comment, the title of its thread) |
| `body` | Comment text, or a text post's own text |
| `subreddit` | Which subreddit |
| `score` | Reddit upvote score |
| `upvoteRatio` | Upvote ratio (posts only) |
| `buzzScore` | Engagement momentum score: (upvotes + 2 × comments) / age in hours^0.8 |
| `postUrl` | Link to the post |
| `commentUrl` | Link to the comment (for comments) |
| `author` | Reddit username |
| `createdAt` | When it was posted |

Every key, in row order:

- **Posts:** `rank`, `type`, `contentType`, `matchedKeywords`, `sentiment`, `sentimentScore`, `buzzScore`, `title`, `body`, `postUrl`, `commentUrl`, `subreddit`, `author`, `score`, `upvoteRatio`, `numComments`, `createdAt`, then `id`, `bodySnippet`, `postType`, `over18`, `imageUrls`, `videoUrl`, `engagementTotal`, `commentToScoreRatio`, `subredditSubscribers`, `authorFlairText`, `isOriginalContent`, `spoiler`, `locked`, `stickied`, `distinguished`, `numCrossposts`, `edited`, `shortUrl`, `scrapedAt`.
- **Comments:** `rank`, `type`, `contentType`, `matchedKeywords`, `sentiment`, `sentimentScore`, `buzzScore`, `title`, `body`, `postUrl`, `commentUrl`, `subreddit`, `author`, `score`, `upvoteRatio`, `numComments`, `createdAt`, then `id`, `bodySnippet`, `parentId`, `parentKind`, `postId`, `postCreatedAt`, `over18`, `isSubmitter`, `authorFlairText`, `edited`, `distinguished`, `stickied`, `controversiality`, `permalinkUrl`, `authorId`, `postUpVotes`, `postCommentsCount`, `postAuthor`, `scrapedAt`.

The keys up to `createdAt` are the same, in the same order and with the same values, as in earlier versions, so saved integrations keep working (`type` is always `mention`). A value Reddit doesn't give is `null`. Mentions are stored in rank order, so the Mentions table and an export both start with rank 1.

- **Comments' authors.** Reddit's comment search no longer shows who wrote a comment, so each comment found is read from its own page (about 20 KB, several at a time while the next search page loads). That fills `author`, `authorId`, `isSubmitter`, `edited`, `stickied` and the thread's `postUpVotes`, `postCommentsCount` and `postAuthor`. If Reddit doesn't answer a comment's page, that comment keeps the search page's fields (no author) and the status line says how many.

#### Sentiment Summary (one per keyword)

| Field | Description |
|---|---|
| `keyword` | The search keyword |
| `overallSentiment` | `positive`, `negative`, or `neutral` overall |
| `positiveRatio` | % of mentions scored positive |
| `negativeRatio` | % of mentions scored negative |
| `neutralRatio` | % of mentions scored neutral |
| `totalMentions` | Total mentions analysed |
| `positiveCount` / `negativeCount` / `neutralCount` | Mentions per label |
| `avgSentimentScore` | Average sentiment score across all mentions |
| `topPositiveMention` | Highest-scoring positive mention (title + URL) |
| `topNegativeMention` | Most negative mention (title + URL) |

Summary rows are never charged. Turn off **Summary Rows (free)** to skip the `summary` dataset: the summaries are still in the free `SUMMARY` record. The run's `OUTPUT` record says how each search went (pages read, results found, filtered, not matching the keyword and kept), and `commentRecordsRead` how many comments were filled from their own page ("40 of 40").

***

### Getting Started

1. Enter your keywords (brand names, product names, topics)
2. Set your time window (past week is a good default)
3. Run — get sentiment summary per keyword + every mention scored

***

### Use Cases

**Brand reputation monitoring**
Is Reddit's opinion of your brand trending positive or negative? Run weekly, check the `overallSentiment` field. If it flips from positive to negative, something changed.

**Product launch tracking**
Released something new? Search your product name after launch and see whether the Reddit reaction is positive, negative, or mixed — and which specific posts are driving the sentiment.

**Competitor analysis**
Search your competitors' names. Find out if Reddit likes them or hates them — and read the specific negative mentions to understand what they're getting wrong.

**Campaign monitoring**
Running a Reddit marketing campaign or AMA? Track your keyword during and after to see whether the campaign shifted sentiment.

***

### Input Parameters

| Parameter | Default | Description |
|---|---|---|
| `keywords` | — | Keywords to analyse (required) |
| `sortBy` | `new` | Sort order: new, relevance, top, hot, comments |
| `timeFilter` | `week` | Time window: hour, day, week, month, year, all |
| `searchPosts` | `true` | Include Reddit posts |
| `searchComments` | `false` | Include comments (more coverage) |
| `subredditFilter` | `[]` | Restrict to specific subreddits (optional) |
| `maxResultsPerKeyword` | `100` | Max posts, and max comments, per keyword (up to 1,000) |
| `minScore` | `0` | Minimum upvote score to include |
| `matchMode` | `any` | `any`: whatever Reddit's search finds; `all`: the text holds every word of the keyword; `phrase`: the exact phrase. Results that don't match are free |
| `proxyConfiguration` | Datacenter | Proxy settings. A residential pick is kept for retries only |

***

### Pricing

Pay per result: $0.79 per 1,000 mentions on Starter ($0.89 Free, $0.69 Scale, $0.59 Business). Summary rows (one per keyword) are free. No browser and no residential proxy: the actor reads Reddit's own search over Apify's datacenter proxy, so runs take seconds. Set a spending limit on the run and the actor stops there, keeping its top-ranked mentions.

***

### Related Actors

- **[Reddit Brand Monitor](https://apify.com/deepmine/reddit-brand-monitor)** — track mentions and score changes between scheduled runs
- **[Reddit Mentions Scraper](https://apify.com/deepmine/reddit-mentions-scraper)** — raw mention data without sentiment scoring
- **[Reddit Scraper](https://apify.com/deepmine/reddit-scraper)** — full posts, comment threads, users and communities from any Reddit link or search
- [Subreddit Finder](https://apify.com/deepmine/reddit-subreddit-finder) and [Subreddit Trend Finder](https://apify.com/deepmine/subreddit-trend-finder) — find the communities worth watching, and what is rising in them
- [Reddit Comments Scraper](https://apify.com/deepmine/reddit-comments-scraper) — paste a result's post link for the whole thread, every comment and reply
- [Reddit Search Scraper](https://apify.com/deepmine/reddit-search-scraper) — plain keyword search over posts and comments

***

*Built for brand managers, PR teams, and marketing teams who need to know whether Reddit's opinion is helping or hurting them.*

# Actor input Schema

## `keywords` (type: `array`):

Brand names, product names, or topics to analyse on Reddit. Each keyword is searched independently — results show sentiment breakdown per keyword. A brand that is also an everyday word (Linear, Notion, Slack, Apple) matches the ordinary word too: add a word that gives it context, like "Linear app", set Match to Exact phrase, or restrict the subreddits below (for example productivity, SaaS).

## `sortBy` (type: `string`):

How Reddit ranks the results returned for each keyword.

• New — most recent mentions first. Best for catching fresh opinions.
• Relevance — Reddit's own relevance ranking.
• Top — highest-scored posts. Good for seeing what resonated most.
• Hot — currently active discussions.
• Most Comments — most-discussed threads.

## `timeFilter` (type: `string`):

Only return mentions posted within this time window.

## `searchPosts` (type: `boolean`):

Analyse Reddit posts (links, articles, discussions) that mention your keyword.

## `searchComments` (type: `boolean`):

Also analyse individual comments mentioning your keywords. Catches opinions buried inside threads. Increases run time.

## `subredditFilter` (type: `array`):

Optionally restrict analysis to specific subreddits. Leave empty to search all of Reddit. Accepts any format: gaming, r/gaming, or full URL. Example for a software brand: productivity, SaaS, startups.

## `maxResultsPerKeyword` (type: `integer`):

Maximum number of posts, and of comments, to analyse per keyword (each counted after your Minimum Upvote Score). More results = more accurate sentiment breakdown but longer run time.

## `minScore` (type: `integer`):

Ignore mentions with fewer upvotes than this. Set to 0 to include brand-new posts with no votes yet.

## `includeSummaryRows` (type: `boolean`):

Saves one summary row per keyword (mentions, positive / negative / neutral ratios, average sentiment, top positive and negative mention) in the run's free Summary dataset (its link is in the OUTPUT record, summaryDataset). Summary rows are never charged: only mention rows are. The same summaries are always in the free SUMMARY record. Up to version 2.0.4 these rows came after the mentions in the results, at a row's price each.

## `matchMode` (type: `string`):

How closely a post or comment must match your keyword.

• Reddit's match — whatever Reddit's search finds for the words (it also matches word stems and other fields, so some results only touch the keyword).
• Every word — the post's title and text (or the comment) must hold every word of the keyword, in any order.
• Exact phrase — the words in a row, as typed (case, punctuation and line breaks don't matter).

Results that don't match aren't delivered and aren't charged. For a brand that is also an everyday word, Exact phrase with a context word ("Linear app") is the precise choice.

## `proxyConfiguration` (type: `object`):

Reddit answers Apify's datacenter proxy, so the default works for every plan. If you pick residential, the run still reads through datacenter and keeps residential for retries Reddit refuses there (charged to the run's own proxy traffic only when needed).

## Actor input object example

```json
{
  "keywords": [
    "Notion app",
    "Linear app",
    "Figma"
  ],
  "sortBy": "new",
  "timeFilter": "week",
  "searchPosts": true,
  "searchComments": false,
  "subredditFilter": [],
  "maxResultsPerKeyword": 30,
  "minScore": 0,
  "includeSummaryRows": true,
  "matchMode": "any",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `mentions` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `run` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "keywords": [
        "Notion app",
        "Linear app",
        "Figma"
    ],
    "maxResultsPerKeyword": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("deepmine/reddit-sentiment-tracker").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "keywords": [
        "Notion app",
        "Linear app",
        "Figma",
    ],
    "maxResultsPerKeyword": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("deepmine/reddit-sentiment-tracker").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "keywords": [
    "Notion app",
    "Linear app",
    "Figma"
  ],
  "maxResultsPerKeyword": 30
}' |
apify call deepmine/reddit-sentiment-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,deepmine/reddit-sentiment-tracker"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/n5hOWbiVz43RKP4XJ/builds/s6aOzF9B79x4YYqB7/openapi.json
