How to Resolve "AttributeError: module 'tweepy' has no attribute 'StreamListener'" in Python
If you're working with Tweepy to stream tweets from the Twitter (now X) API and encounter AttributeError: module 'tweepy' has no attribute 'StreamListener', it means your code is using a deprecated class that no longer exists in modern versions of Tweepy.
In this guide, we'll explain why this error occurs, show the old code that causes it, and walk you through the exact migration steps to fix it using Tweepy's current streaming API.
Why Does This Error Occur?
The StreamListener class was part of Tweepy's original streaming implementation, which relied on Twitter API v1.1. Starting with Tweepy 4.0, the library underwent significant changes to align with Twitter API v2:
tweepy.StreamListenerwas removed entirely.tweepy.Stream(which used OAuth 1.0a) was replaced bytweepy.StreamingClient(which uses a Bearer Token).- The filtering mechanism changed from passing parameters to
filter()to using stream rules managed server-side.
If you run old code that references StreamListener with Tweepy 4.x or later, you'll see:
AttributeError: module 'tweepy' has no attribute 'StreamListener'
This isn't a bug, it's a breaking change introduced intentionally when Tweepy migrated to Twitter API v2. The fix requires updating your code to use the new API.
The Old Code That Causes the Error
Here's a typical example of the deprecated streaming pattern:
import tweepy
class MyStreamListener(tweepy.StreamListener): # ❌ StreamListener no longer exists
def on_status(self, status):
print(status.text)
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
listener = MyStreamListener()
stream = tweepy.Stream(auth=auth, listener=listener)
stream.filter(track=['python'])
Output:
AttributeError: module 'tweepy' has no attribute 'StreamListener'
How to Fix It: Migrating to StreamingClient
The modern replacement uses tweepy.StreamingClient with a Bearer Token for authentication and tweepy.StreamRule for defining what tweets to track.
Step 1: Update Tweepy
First, make sure you have the latest version of Tweepy installed:
pip install --upgrade tweepy
Verify the installed version:
import tweepy
print(tweepy.__version__) # Should be 4.x or later
Step 2: Rewrite Your Streaming Code
✅ Correct: Updated code using StreamingClient:
import tweepy
class MyStream(tweepy.StreamingClient):
def on_tweet(self, tweet):
print(tweet.text)
def on_error(self, status_code):
if status_code == 429:
print("Rate limited. Disconnecting...")
return False # Returning False disconnects the stream
print(f"Error: {status_code}")
# Authenticate with a Bearer Token (Twitter API v2)
bearer_token = "YOUR_BEARER_TOKEN"
# Create the stream instance
stream = MyStream(bearer_token)
# Add rules to filter tweets (equivalent to the old 'track' parameter)
stream.add_rules(tweepy.StreamRule("python"))
# Start streaming
stream.filter()
You need a Bearer Token from the Twitter Developer Portal. The old consumer key/secret and access token/secret combination used with OAuthHandler does not work with StreamingClient.
Key Differences Between Old and New API
| Feature | Old API (StreamListener) | New API (StreamingClient) |
|---|---|---|
| Class to inherit | tweepy.StreamListener | tweepy.StreamingClient |
| Authentication | OAuth 1.0a (OAuthHandler) | Bearer Token |
| Twitter API version | v1.1 | v2 |
| Tweet callback method | on_status(self, status) | on_tweet(self, tweet) |
| Filtering | stream.filter(track=['...']) | stream.add_rules(StreamRule('...')) |
| Tweet text access | status.text | tweet.text |
Managing Stream Rules
One important difference with the new API is that stream rules are persistent on the server. This means rules you add remain active even after your script stops. You should manage them carefully.
Adding Rules
stream.add_rules(tweepy.StreamRule("python"))
stream.add_rules(tweepy.StreamRule("machine learning"))
Viewing Existing Rules
rules = stream.get_rules()
print(rules)
Deleting Rules Before Adding New Ones
To avoid accumulating old rules, clear them before adding new ones:
# Get existing rules
existing_rules = stream.get_rules()
# Delete them if any exist
if existing_rules.data:
rule_ids = [rule.id for rule in existing_rules.data]
stream.delete_rules(rule_ids)
print(f"Deleted {len(rule_ids)} existing rules.")
# Add fresh rules
stream.add_rules(tweepy.StreamRule("python programming"))
Always clean up old rules at the start of your script. Leftover rules from previous runs can cause unexpected tweets to appear in your stream or hit your rule limit.
Complete Working Example
Here's a full, production-ready example with proper error handling and rule management:
import tweepy
class TweetStreamer(tweepy.StreamingClient):
def __init__(self, bearer_token, max_tweets=10):
super().__init__(bearer_token)
self.tweet_count = 0
self.max_tweets = max_tweets
def on_tweet(self, tweet):
self.tweet_count += 1
print(f"[{self.tweet_count}] {tweet.text[:100]}")
if self.tweet_count >= self.max_tweets:
print("Reached max tweets. Disconnecting.")
self.disconnect()
def on_error(self, status_code):
print(f"Stream error: {status_code}")
if status_code == 429:
return False # Disconnect on rate limit
def on_connection_error(self):
print("Connection error. Reconnecting...")
def main():
bearer_token = "YOUR_BEARER_TOKEN"
stream = TweetStreamer(bearer_token, max_tweets=20)
# Clean up old rules
existing_rules = stream.get_rules()
if existing_rules.data:
stream.delete_rules([rule.id for rule in existing_rules.data])
# Add new rules
stream.add_rules(tweepy.StreamRule("python"))
# Start streaming (tweet_fields adds extra data to each tweet)
print("Starting stream...")
stream.filter(tweet_fields=["created_at", "author_id"])
if __name__ == "__main__":
main()
Sample Output:
Starting stream...
[1] RT @dev_community: Check out this awesome Python tutorial for beginners...
[2] Just deployed my first Python web app using Flask! #python #webdev...
[3] Python 3.13 brings some amazing performance improvements...
...
[20] Learning Python has been the best decision of my career...
Reached max tweets. Disconnecting.
Troubleshooting
Still Getting Errors After Updating Tweepy?
If updating doesn't resolve the issue, try a clean reinstall:
pip uninstall tweepy
pip install tweepy
Error: 403 Forbidden When Starting the Stream
This usually means your Twitter Developer account doesn't have the required access level. Twitter API v2 filtered stream requires at least Basic access. Check your access level in the Developer Portal.
Error: tweepy.errors.TooManyRequests
You've hit the rate limit. Wait a few minutes before restarting the stream, or reduce the number of rules.
Conclusion
The AttributeError: module 'tweepy' has no attribute 'StreamListener' error occurs because StreamListener was removed in Tweepy 4.0 as part of the migration from Twitter API v1.1 to v2. To fix it, replace tweepy.StreamListener with tweepy.StreamingClient, switch from OAuth 1.0a to a Bearer Token, and use StreamRule objects instead of passing track parameters directly to filter(). Always refer to the official Tweepy documentation for the latest API details, as Twitter's platform continues to evolve.