Skip to main content

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.StreamListener was removed entirely.
  • tweepy.Stream (which used OAuth 1.0a) was replaced by tweepy.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'
info

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()
caution

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

FeatureOld API (StreamListener)New API (StreamingClient)
Class to inherittweepy.StreamListenertweepy.StreamingClient
AuthenticationOAuth 1.0a (OAuthHandler)Bearer Token
Twitter API versionv1.1v2
Tweet callback methodon_status(self, status)on_tweet(self, tweet)
Filteringstream.filter(track=['...'])stream.add_rules(StreamRule('...'))
Tweet text accessstatus.texttweet.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"))
Best Practice

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.