# Stocktwits Sentiment Scraper — Bullish/Bearish Feed (`devilscrapes/stocktwits-sentiment-scraper`) Actor

Pull the message and sentiment stream from Stocktwits for stock and crypto ticker symbols. Each row carries Stocktwits' own user-applied Bullish/Bearish sentiment tag plus message text, author, and engagement counts. Keyless target, bounded per-symbol pagination.

- **URL**: https://apify.com/devilscrapes/stocktwits-sentiment-scraper.md
- **Developed by:** [DevilScrapes](https://apify.com/devilscrapes) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

<div align="center">
  <img src=".actor/icon.svg" width="160" alt="Devil Scrapes mark" />

## Stocktwits Sentiment Scraper — Bullish/Bearish Feed

**💰 $3.20 / 1 000 messages**  ·  pay only for results  ·  no credit card to try

*We do the dirty work so your dataset stays clean.* 😈

Pull the message + sentiment stream from Stocktwits for stock and crypto ticker symbols. Each row carries Stocktwits' own user-applied Bullish/Bearish sentiment tag alongside the message text, author, and engagement counts — the crowd-sourced signal a generic price feed or social-scrape can't give you.

</div>

***

### 🎯 What this scrapes

Stocktwits runs a live message stream for every stock and crypto ticker, and traders tag their own posts **Bullish** or **Bearish** as they write them. This Actor takes a list of symbols, walks each symbol's stream backward page by page, and writes one typed row per message — sentiment tag included verbatim, `null` when the author left it untagged. We handle the retries, backoff, and proxy routing so the stream lands, bounded to a predictable page/message cap per run.

### 🔥 Features

- 🔁 **Retries with exponential backoff** on `408 / 429 / 503` and network errors, honouring `Retry-After` when Stocktwits sends it.
- 🛡️ **Rotating browser fingerprints** — real-browser TLS impersonation on every request, not a bare Python client.
- 🌐 **Apify Proxy routing** on every request, fresh exit IP and session on any block.
- 🧩 **Per-symbol fault isolation** — one symbol's failure never aborts the rest of your run.
- 🧊 **Clean, typed dataset rows** — Pydantic-validated, ISO-8601 timestamps, sentiment always present as `Bullish`, `Bearish`, or `null`.
- 💰 **Predictable cost ceiling** — every run stops at whichever of your message or page cap hits first.

### 💡 Use cases

- **Sentiment dashboards** — track the Bullish/Bearish split for a watchlist over time.
- **Trading signal research** — feed crowd sentiment into a backtest alongside price data.
- **Social listening for IR/comms teams** — see what retail traders are saying about a ticker, unfiltered.
- **Crypto community monitoring** — the same stream + sentiment tag works for `.X`-suffixed crypto symbols.

### ⚙️ How to use it

1. Click **Try for free** at the top of the page.
2. Enter the ticker symbols you want — stock or crypto.
3. Click **Start**. Output streams into the run's dataset.
4. Export from **Storage → Dataset** as JSON, CSV, or Excel — or fetch via the Apify API.

For no-code workflows: install the [Apify node for n8n](https://n8n.io/integrations/apify/) or the [Apify module for Make](https://www.make.com/en/integrations/apify), connect your Apify token, and point it at `DevilScrapes/stocktwits-sentiment-scraper`.

### 📥 Input

| Field | Type | Required | Default | Notes |
|---|---|:--:|---|---|
| `symbols` | `array` | yes | `["AAPL", "TSLA"]` | Ticker symbols, e.g. `AAPL`, `TSLA`, `BTC.X`. Uppercased and deduplicated automatically. Max 50. |
| `maxMessagesPerSymbol` | `integer` | no | `100` | Hard cap on messages returned per symbol (1-2000). |
| `maxPagesPerSymbol` | `integer` | no | `10` | Hard cap on paginated requests per symbol (1-100). |
| `proxyConfiguration` | `object` | no | `{"useApifyProxy": true}` | We route every request through Apify Proxy and rotate exit IPs on any block. |

#### Example input

```json
{
  "symbols": ["AAPL", "TSLA"],
  "maxMessagesPerSymbol": 100,
  "maxPagesPerSymbol": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

### 📤 Output

One row per Stocktwits message.

| Field | Type | Notes |
|---|---|---|
| `message_id` | `integer` | Stocktwits message id — stable row identity. |
| `symbol` | `string` | Ticker symbol the row was fetched for (uppercased). |
| `text` | `string` | Message body text. |
| `sentiment` | `string \| null` | `Bullish`, `Bearish`, or `null` when the author left it untagged. |
| `author_username` | `string` | Posting user's Stocktwits handle. |
| `created_at` | `string` | Message timestamp, ISO-8601 UTC. |
| `likes_count` | `integer \| null` | Like count, if exposed by the payload. |
| `reshares_count` | `integer \| null` | Reshare count, if exposed by the payload. |

#### Example output

```json
{
  "message_id": 601234567,
  "symbol": "AAPL",
  "text": "AAPL breaking out of the range, watching 230 next",
  "sentiment": "Bullish",
  "author_username": "traderjoe22",
  "created_at": "2026-09-10T14:32:07Z",
  "likes_count": 3,
  "reshares_count": 0
}
```

### 💰 Pricing

Pay-Per-Event — pay only for what lands in your dataset:

| Event | USD | What it is |
|---|---:|---|
| `actor-start` | $0.20 | One-off warm-up charge per run |
| `message-scraped` | $0.003 | Per validated message row |

**Example**: 1 000 messages in a run ≈ **$3.20** ($0.20 start + 1 000 x $0.003). No subscription, no minimum, no card to start — Apify gives every new account $5 of free credit.

### 🚧 Limitations

- Snapshot Actor, not an unbounded archive crawler — no historical backfill beyond your page/message caps.
- No watchlist/portfolio, user-profile, or trending-symbols discovery — symbol list is user-supplied only.
- No authenticated/logged-in Stocktwits features (private streams, DMs).
- No price/OHLC quote data — sentiment-focused by design.
- No sentiment re-classification or NLP — surfaces Stocktwits' own label verbatim, never infers sentiment.

### ❓ FAQ

**Do I need a Stocktwits account or API key?**

No. The stream endpoint this Actor calls needs no auth — you only need an Apify account to run it.

**What happens to messages the author didn't tag Bullish or Bearish?**

They're still returned, with `sentiment: null` — we never drop a message for lacking a sentiment tag.

**Can I pull crypto symbols, not just stocks?**

Yes — Stocktwits' own `.X` crypto ticker convention (e.g. `BTC.X`) works the same as a stock symbol.

**What happens if one of my symbols is invalid or has no messages?**

That symbol finishes with zero rows and the run keeps going — an empty stream is a valid result, not a failure.

### 💬 Your feedback

Spotted a bug, hit a weird edge case, or need a new field? Open an issue on the Actor's **Issues** tab in Apify Console — we ship fixes weekly and we read every report.

***

<div align="center">

Built by **[Devil Scrapes](https://apify.com/DevilScrapes)** 😈 — a small fleet of
opinionated public-data Actors. Honest pricing, real engineering, zero fine print.

</div>

# Actor input Schema

## `symbols` (type: `array`):

Stocktwits ticker symbols to fetch, e.g. <code>AAPL</code>, <code>TSLA</code>, <code>BTC.X</code>. Uppercased and deduplicated automatically. Max 50.

## `maxMessagesPerSymbol` (type: `integer`):

Hard cap on messages returned per symbol; bounds run cost.

## `maxPagesPerSymbol` (type: `integer`):

Hard cap on paginated requests per symbol (each page is roughly 20-30 messages); bounds run cost independent of the message cap.

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

Apify Proxy routing. Leave this on — we rotate exit IPs and impersonation profiles on every block.

## Actor input object example

```json
{
  "symbols": [
    "AAPL",
    "TSLA"
  ],
  "maxMessagesPerSymbol": 100,
  "maxPagesPerSymbol": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All dataset items as JSON.

## `datasetItemsCsv` (type: `string`):

Same data exported to CSV.

## `datasetView` (type: `string`):

Open the run dataset in the Console.

# 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 = {
    "symbols": [
        "AAPL",
        "TSLA"
    ],
    "maxMessagesPerSymbol": 100,
    "maxPagesPerSymbol": 10,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("devilscrapes/stocktwits-sentiment-scraper").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 = {
    "symbols": [
        "AAPL",
        "TSLA",
    ],
    "maxMessagesPerSymbol": 100,
    "maxPagesPerSymbol": 10,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("devilscrapes/stocktwits-sentiment-scraper").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 '{
  "symbols": [
    "AAPL",
    "TSLA"
  ],
  "maxMessagesPerSymbol": 100,
  "maxPagesPerSymbol": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call devilscrapes/stocktwits-sentiment-scraper --silent --output-dataset

```

## MCP server setup

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

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/Kh0d4dxwXy14oxlk1/builds/xD2B80ZEVM5y8sau2/openapi.json
