Build a Twitter Sentiment Analysis Tool with XCROP API
Why Twitter Sentiment Matters in Crypto
Crypto markets are driven by narratives, and narratives live on Twitter. Before a token pumps or dumps, the sentiment shift is visible in tweets — hours or even days before price action. A twitter sentiment analysis API lets you quantify this shift programmatically.
Professional trading desks have been using social sentiment tools for years. With XCROP's search API, you can build your own crypto sentiment twitter tracker without expensive data providers or complex scraping infrastructure.
Architecture Overview
The system is simple:
XCROP Search API ──→ Tweet Collection ──→ Sentiment Scorer ──→ Dashboard/Alert
($BTC) (100 tweets) (bull/bear/neutral) (score: +0.72)Step 1: Collecting Tweets with XCROP Search
The /v2/search endpoint lets you search for tweets by keyword, hashtag, or cashtag. For crypto sentiment, cashtags like $BTC or $ETH work best.
import requests import os API_KEY = os.environ["XCROP_API_KEY"] BASE = "https://xcrop.io/api/v2" HEADERS = {"Authorization": "Bearer " + API_KEY} def search_tweets(query, count=50, sort="latest"): """Search tweets using XCROP API.""" response = requests.post( BASE + "/search", headers=HEADERS, json={ "query": query, "count": count, "sort": sort } ) if response.status_code == 200: return response.json()["data"] print("Error: " + str(response.status_code)) return [] # Fetch latest tweets about Bitcoin tweets = search_tweets("$BTC", count=100) print("Collected " + str(len(tweets)) + " tweets about $BTC")
Filtering for Quality
Not all tweets are useful for sentiment. Filter out spam, bots, and low-engagement noise:
def filter_quality_tweets(tweets, min_likes=5, min_followers=100): """Filter tweets for quality signals.""" filtered = [] for tweet in tweets: likes = tweet["metrics"]["likes"] followers = tweet["author"].get("followers_count", 0) # Skip low-engagement tweets (likely bots or spam) if likes < min_likes: continue # Skip accounts with very few followers if followers < min_followers: continue # Skip retweets (we want original opinions) if tweet["text"].startswith("RT @"): continue filtered.append(tweet) return filtered quality_tweets = filter_quality_tweets(tweets) print("Quality tweets: " + str(len(quality_tweets)) + " / " + str(len(tweets)))
Step 2: Keyword-Based Sentiment Scoring
The simplest approach uses keyword matching. It's fast, requires no external APIs, and works surprisingly well for crypto:
# Sentiment keyword dictionaries BULLISH_WORDS = [ "bullish", "moon", "pump", "buy", "long", "accumulate", "breakout", "rally", "ath", "all time high", "undervalued", "loading", "aping", "send it", "wagmi", "diamond hands", "higher high", "support holding", "reversal", "bottomed", "green candle", "massive", "explosive", "parabolic" ] BEARISH_WORDS = [ "bearish", "dump", "sell", "short", "crash", "overvalued", "rug", "scam", "dead", "rekt", "ngmi", "paper hands", "lower low", "resistance", "breakdown", "topped", "red candle", "liquidated", "capitulation", "bleeding" ] def score_sentiment(text): """Score a tweet's sentiment from -1 (bearish) to +1 (bullish).""" text_lower = text.lower() bull_count = sum(1 for word in BULLISH_WORDS if word in text_lower) bear_count = sum(1 for word in BEARISH_WORDS if word in text_lower) total = bull_count + bear_count if total == 0: return 0.0 # neutral # Score from -1 to +1 score = (bull_count - bear_count) / total return round(score, 2) # Test it print(score_sentiment("BTC looking bullish, breakout incoming")) # +1.0 print(score_sentiment("This is going to dump hard, sell now")) # -1.0 print(score_sentiment("BTC at 95k, interesting price action")) # 0.0
Step 3: LLM-Based Sentiment (Optional)
For more nuanced analysis, use an LLM to classify sentiment. This catches sarcasm, context, and complex opinions that keyword matching misses:
from openai import OpenAI llm = OpenAI() def score_sentiment_llm(text): """Use LLM for nuanced sentiment scoring.""" response = llm.chat.completions.create( model="gpt-4o-mini", messages=[ { "role": "system", "content": ( "Score the crypto sentiment of this tweet. " "Return ONLY a number from -1.0 (very bearish) " "to +1.0 (very bullish). 0 = neutral." ) }, {"role": "user", "content": text} ], max_tokens=10 ) try: return float(response.choices[0].message.content.strip()) except ValueError: return 0.0
> Tip: The keyword approach is free and fast — use it for real-time monitoring. Reserve LLM scoring for daily summaries or high-stakes analysis where accuracy matters most.
Step 4: Complete Sentiment Analysis Tool
Here's the full working script that ties everything together:
import requests import os from datetime import datetime API_KEY = os.environ["XCROP_API_KEY"] BASE = "https://xcrop.io/api/v2" HEADERS = {"Authorization": "Bearer " + API_KEY} BULLISH_WORDS = [ "bullish", "moon", "pump", "buy", "long", "accumulate", "breakout", "rally", "ath", "undervalued", "loading", "wagmi", "diamond hands", "reversal", "bottomed", "parabolic" ] BEARISH_WORDS = [ "bearish", "dump", "sell", "short", "crash", "overvalued", "rug", "scam", "rekt", "ngmi", "breakdown", "topped", "liquidated", "capitulation", "bleeding" ] def search_tweets(query, count=100): response = requests.post( BASE + "/search", headers=HEADERS, json={"query": query, "count": count, "sort": "latest"} ) if response.status_code == 200: return response.json()["data"] return [] def score_sentiment(text): text_lower = text.lower() bull = sum(1 for w in BULLISH_WORDS if w in text_lower) bear = sum(1 for w in BEARISH_WORDS if w in text_lower) total = bull + bear if total == 0: return 0.0 return round((bull - bear) / total, 2) def analyze_token(token): """Run full sentiment analysis on a token.""" print("Analyzing sentiment for " + token + "...") print("-" * 50) tweets = search_tweets(token, count=100) if not tweets: print("No tweets found.") return # Filter quality tweets quality = [t for t in tweets if t["metrics"]["likes"] >= 3] print("Tweets collected: " + str(len(tweets))) print("Quality tweets: " + str(len(quality))) print() # Score each tweet scores = [] bullish_tweets = [] bearish_tweets = [] for tweet in quality: score = score_sentiment(tweet["text"]) scores.append(score) if score > 0: bullish_tweets.append(tweet) elif score < 0: bearish_tweets.append(tweet) # Calculate aggregates if not scores: print("No scorable tweets found.") return avg_score = round(sum(scores) / len(scores), 3) bullish_pct = round(len(bullish_tweets) / len(quality) * 100, 1) bearish_pct = round(len(bearish_tweets) / len(quality) * 100, 1) neutral_pct = round(100 - bullish_pct - bearish_pct, 1) # Determine overall sentiment if avg_score > 0.2: sentiment = "BULLISH" elif avg_score < -0.2: sentiment = "BEARISH" else: sentiment = "NEUTRAL" # Print report print("===== SENTIMENT REPORT: " + token + " =====") print("Timestamp: " + datetime.now().strftime("%Y-%m-%d %H:%M UTC")) print("Overall: " + sentiment + " (score: " + str(avg_score) + ")") print() print("Distribution:") print(" Bullish: " + str(bullish_pct) + "% (" + str(len(bullish_tweets)) + " tweets)") print(" Neutral: " + str(neutral_pct) + "%") print(" Bearish: " + str(bearish_pct) + "% (" + str(len(bearish_tweets)) + " tweets)") print() # Top bullish tweets if bullish_tweets: bullish_tweets.sort(key=lambda t: t["metrics"]["likes"], reverse=True) print("Top Bullish Tweets:") for t in bullish_tweets[:3]: author = t["author"]["username"] likes = t["metrics"]["likes"] print(" @" + author + " (" + str(likes) + " likes): " + t["text"][:100]) print() # Top bearish tweets if bearish_tweets: bearish_tweets.sort(key=lambda t: t["metrics"]["likes"], reverse=True) print("Top Bearish Tweets:") for t in bearish_tweets[:3]: author = t["author"]["username"] likes = t["metrics"]["likes"] print(" @" + author + " (" + str(likes) + " likes): " + t["text"][:100]) return { "token": token, "sentiment": sentiment, "score": avg_score, "bullish_pct": bullish_pct, "bearish_pct": bearish_pct, "tweet_count": len(quality) } # Analyze multiple tokens tokens = ["$BTC", "$ETH", "$SOL"] results = [] for token in tokens: result = analyze_token(token) if result: results.append(result) print() # Summary table if results: print("=" * 50) print("MULTI-TOKEN SENTIMENT SUMMARY") print("=" * 50) for r in results: emoji = "+" if r["score"] > 0 else "" print( r["token"].ljust(8) + r["sentiment"].ljust(10) + (emoji + str(r["score"])).ljust(8) + "Bull:" + str(r["bullish_pct"]) + "%" )
Run it:
export XCROP_API_KEY="your_key" python sentiment_analyzer.py
Example output:
===== SENTIMENT REPORT: $BTC =====
Timestamp: 2026-02-12 14:30 UTC
Overall: BULLISH (score: 0.342)
Distribution:
Bullish: 52.3% (34 tweets)
Neutral: 33.8%
Bearish: 13.8% (9 tweets)Use Cases
Trading Signals
Use sentiment score as one input in a trading strategy. A sustained shift from neutral to bullish across multiple tokens often precedes market moves.
Community Monitoring
Track sentiment for your own project's token. A sudden bearish spike might indicate FUD you need to address.
Alerts on Sentiment Shifts
Combine with a polling loop to get notified when sentiment flips:
import time previous_sentiment = {} def check_sentiment_shift(token): result = analyze_token(token) if not result: return prev = previous_sentiment.get(token) if prev and prev != result["sentiment"]: print("[ALERT] " + token + " sentiment shifted: " + prev + " -> " + result["sentiment"]) previous_sentiment[token] = result["sentiment"] # Poll every 5 minutes while True: for token in ["$BTC", "$ETH", "$SOL"]: check_sentiment_shift(token) time.sleep(300)