# Sentiment Analyzer — Text Signals, Emotion & Keywords (`junipr/sentiment-analyzer`) Actor

Analyze text sentiment, emotion keywords, polarity, confidence, and evidence snippets for reviews, comments, support tickets, and datasets.

- **URL**: https://apify.com/junipr/sentiment-analyzer.md
- **Developed by:** [junipr](https://apify.com/junipr) (community)
- **Categories:** AI, Developer tools
- **Features:** Limited permissions
- **Stats:** 4 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.90 / 1,000 text analyzeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Sentiment Analyzer — Text Signals, Emotion & Keywords

Batch English-language sentiment analysis with emotion signals, key phrase extraction, and language labeling. Processes up to 100,000 texts using offline NLP without an external AI API.

The analyzer runs inside the Actor process with deterministic lexicon and rule-based scoring. It is suitable when you need repeatable signals without sending text to a separate model API.

### How to Use

**Zero-config (just provide texts):**

```json
{
  "texts": [
    "This product is amazing! Best purchase ever."
  ]
}
```

**With ID and metadata:**

```json
{
  "texts": [
    { "id": "review-123", "text": "Love this product!", "metadata": { "source": "amazon" } }
  ]
}
```

**Review analysis pipeline (filter negative reviews):**

```json
{
  "texts": ["... your review texts ..."],
  "onlySentiment": "negative",
  "extractKeyPhrases": true
}
```

### Input Configuration

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `texts` | array | sample texts | Text strings to analyze. API callers can also send `{id, text, metadata}` objects. Max 100K. |
| `sentimentModel` | string | `"combined"` | `afinn`, `vader`, or `combined` (most accurate) |
| `detectEmotions` | boolean | `true` | Detect joy, anger, sadness, fear, surprise, disgust |
| `extractKeyPhrases` | boolean | `true` | Extract key phrases contributing to sentiment |
| `detectLanguage` | boolean | `true` | Detect language of each text |
| `neutralThreshold` | number | `0.05` | Compound score range for neutral classification |
| `onlySentiment` | string | null | Filter: `positive`, `negative`, `neutral`, `mixed` |
| `includeWordScores` | boolean | `false` | Per-word sentiment scores |
| `minimumConfidence` | number | `0` | Minimum confidence threshold |

### Output Format

```json
{
  "id": "review-123",
  "text": "This product is amazing!",
  "textLength": 25,
  "language": { "detected": "en", "name": "English", "confidence": 0.9 },
  "sentiment": {
    "label": "positive",
    "compound": 0.8721,
    "positive": 0.8721,
    "negative": 0.0,
    "neutral": 0.1279,
    "confidence": 0.9721
  },
  "emotions": {
    "joy": 0.8, "anger": 0.0, "sadness": 0.0,
    "fear": 0.0, "surprise": 0.1, "disgust": 0.0,
    "dominant": "joy"
  },
  "keyPhrases": [
    { "phrase": "amazing", "sentiment": 1.0, "importance": 0.9 }
  ],
  "analyzedAt": "2026-03-11T12:00:00.000Z"
}
```

#### Sentiment Score Interpretation

| Compound Score | Label | Description |
|----------------|-------|-------------|
| 0.05 to 1.0 | positive | Positive sentiment |
| -0.05 to 0.05 | neutral | No strong sentiment |
| -1.0 to -0.05 | negative | Negative sentiment |
| Both pos & neg > 0.3 | mixed | Contains both positive and negative |

### Tips and Advanced Usage

**Choosing the right model:**

- `combined` (default) — Uses the AFINN and VADER-style signals together
- `vader` — Better for social media with emojis, slang, caps, punctuation
- `afinn` — Fastest, purely lexicon-based

**Adjusting neutral threshold:**

- Default `0.05` works well for most use cases
- Increase to `0.15-0.20` for stricter positive/negative classification

**Handling sarcasm:** Lexicon-based analysis cannot reliably detect sarcasm ("Oh great, another delay"). For sarcasm, consider LLM-based tools.

**Multi-language:** Works best with English. 20+ languages supported via translated lexicons with lower accuracy.

### Pricing

**Pay-Per-Event:** $0.0039 for each `text-analyzed` event ($3.90 per 1,000 texts)

Pricing includes all platform compute costs — no hidden fees.

| Scenario | Texts | Cost |
|----------|-------|------|
| Product reviews batch (500) | 500 | $1.95 |
| Twitter mentions (5,000) | 5,000 | $19.50 |
| Customer feedback (20,000) | 20,000 | $78.00 |
| Monthly monitoring (100,000) | 100,000 | $390.00 |

### Related Actors

- [Finance News Scraper](https://apify.com/junipr/finance-news-scraper) — Pair with sentiment for financial signal detection
- [Google News Scraper](https://apify.com/junipr/google-news-scraper) — News to analyze with sentiment

### FAQ

#### How accurate is the sentiment analysis?

Accuracy depends on domain, wording, irony, and language. Validate the deterministic scores against labeled examples from your own use case before automating decisions.

#### Does it detect sarcasm?

No. Sarcasm detection requires contextual understanding that lexicon-based NLP cannot reliably provide. Document this limitation for your users.

#### What languages are supported?

Sentiment scoring is designed for English text. Language detection may label other languages, but that does not make the English sentiment lexicon reliable for them.

#### Can I analyze social media posts with emojis?

Yes — emoji sentiment mapping is built in. Common emojis are mapped to sentiment values.

#### What's the difference between AFINN and VADER models?

AFINN: lexicon-based word scoring, fast and simple. VADER: rule-based with negation handling, emphasis (CAPS, !!!), and emoji support — better for social media.

#### How does emotion detection work?

Emotion detection uses a word-emotion association lexicon. Each word is mapped to one of 6 emotions. The dominant emotion is the one most frequently detected in the text.

# Actor input Schema

## `texts` (type: `array`):

List of text strings to analyze. Max 100,000 texts.

## `detectEmotions` (type: `boolean`):

Detect specific emotions (joy, anger, sadness, fear, surprise, disgust) in addition to sentiment polarity.

## `extractKeyPhrases` (type: `boolean`):

Extract key phrases/words that contribute most to the sentiment score.

## `detectLanguage` (type: `boolean`):

Detect language of each text. Analysis quality is best for English.

## `sentimentModel` (type: `string`):

Sentiment analysis approach: afinn (AFINN-165 lexicon), vader (rules-based), combined (ensemble — most accurate).

## `neutralThreshold` (type: `number`):

Compound score between -threshold and +threshold is classified as neutral. Min: 0.01, Max: 0.30.

## `includeWordScores` (type: `boolean`):

Include per-word sentiment scores in output (detailed breakdown).

## `onlySentiment` (type: `string`):

Filter output to only texts matching this sentiment: positive, negative, neutral, mixed. Leave empty for all.

## `minimumConfidence` (type: `number`):

Only output results with confidence >= this threshold. Min: 0, Max: 1.

## Actor input object example

```json
{
  "texts": [
    "This product is amazing! Best purchase I've ever made."
  ],
  "detectEmotions": true,
  "extractKeyPhrases": true,
  "detectLanguage": true,
  "sentimentModel": "combined",
  "neutralThreshold": 0.05,
  "includeWordScores": false,
  "minimumConfidence": 0
}
```

# Actor output Schema

## `results` (type: `string`):

One sentiment analysis result per input text.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("junipr/sentiment-analyzer").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("junipr/sentiment-analyzer").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 '{}' |
apify call junipr/sentiment-analyzer --silent --output-dataset

```

## MCP server setup

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

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/FDMWsldh06esNwFvF/builds/oIv4cKRa8XOnOfqrI/openapi.json
