Twitter (now X) data is still one of the most valuable sources for sentiment analysis, trend monitoring, and competitive intelligence. But accessing that data has gotten expensive. The API pricing changes in 2023 priced out most small teams, and the landscape has shifted further in 2026.
Let's break down your options: the official API vs. web scraping, with a practical comparison to help you decide.
Twitter API v2: The Official Route
Current Pricing (2026)
| Tier | Monthly Cost | Tweet Cap | Features |
|---|---|---|---|
| Free | $0 | 1,500 tweets/mo (write) | Post only, 1 app |
| Basic | $200/mo | 10,000 reads/mo | Read + write, 2 apps |
| Pro | $5,000/mo | 1M reads/mo | Full archive search, analytics |
| Enterprise | Custom | Custom | Firehose access |
What the Free Tier Actually Gets You
Almost nothing for data extraction:
Write-only — you can post tweets, but can't read/search them- 1,500 tweets per month posting limit
- No search endpoint access
- No user lookup
- Useful only if you're building a posting bot
Basic Tier ($200/mo)
The entry point for data access:
- 10,000 tweet reads per month
- Basic search (recent tweets, last 7 days)
- User lookup and follower data
- No historical/archive search
At $200/month for 10,000 tweets, that's $0.02 per tweet. For many research and monitoring use cases, that's too expensive.
API Code Example
import requests
BEARER_TOKEN = "YOUR_BEARER_TOKEN"
def search_tweets(query: str, max_results: int = 10):
url = "https://api.twitter.com/2/tweets/search/recent"
headers = {"Authorization": f"Bearer {BEARER_TOKEN}"}
params = {
"query": query,
"max_results": max_results,
"tweet.fields": "created_at,public_metrics,author_id",
"expansions": "author_id",
"user.fields": "username,name,public_metrics"
}
response = requests.get(url, headers=headers, params=params)
return response.json()
def get_user_tweets(username: str, max_results: int = 10):
# First get user ID
url = f"https://api.twitter.com/2/users/by/username/{username}"
headers = {"Authorization": f"Bearer {BEARER_TOKEN}"}
user = requests.get(url, headers=headers).json()
user_id = user["data"]["id"]
# Then get their tweets
url = f"https://api.twitter.com/2/users/{user_id}/tweets"
params = {
"max_results": max_results,
"tweet.fields": "created_at,public_metrics"
}
response = requests.get(url, headers=headers, params=params)
return response.json()
# Search for tweets about Python
results = search_tweets("python programming", max_results=10)
for tweet in results.get("data", []):
metrics = tweet["public_metrics"]
print(f"Tweet: {tweet['text']}")
print(f"Likes: {metrics['like_count']} | RTs: {metrics['retweet_count']}")
print("---")
Web Scraping: The Alternative
When Scraping Makes More Sense
Budget under $200/mo — the API's cheapest data tier costs $200
Need more than 10K tweets — Basic tier caps out quickly
Historical data — API archive search requires Pro ($5K/mo)
Specific data needs — the API doesn't expose everything (e.g., view counts were added late)
One-time research — paying $200/mo for a one-off analysis doesn't make sense
Challenges with Scraping Twitter
Twitter/X actively fights scraping:
- Aggressive rate limiting
- Login walls for search results
- Frequent frontend changes
- Legal threats (though enforcement is rare for research)
Building and maintaining your own Twitter scraper is a full-time job. That's where managed scraping tools come in.
Using an Apify Actor
I built a offer a more cost-effective path to the same data.
The best approach depends on your budget, scale, and use case. Start with scraping for research, and upgrade to the API when you need real-time reliability in production.
SOCIAL SHARE CARD GENERATOR