You want to create a Mastodon bot that listens to a specific hashtag in real time and automatically responds, boosts, or bookmarks matching posts. The Mastodon Streaming API allows your bot to receive a continuous feed of public posts that match a hashtag without repeatedly polling the server. This article explains how to set up a Python bot using the Mastodon.py library, connect to the streaming endpoint, and handle incoming posts with custom actions.
Key Takeaways: Building a Mastodon Hashtag Bot
- Mastodon.py library: The recommended Python library for interacting with the Mastodon API, including streaming endpoints.
- StreamListener class: A handler that processes incoming posts from the streaming API and triggers custom bot actions.
- Access token with read and write scopes: Required to authenticate the bot and perform actions such as boosting or replying.
Understanding the Mastodon Streaming API for Hashtag Bots
The Mastodon Streaming API provides a WebSocket connection that delivers new posts matching a hashtag as soon as they are published. Unlike the REST API, which requires you to repeatedly send HTTP requests, the streaming API pushes data to your bot in real time. This is more efficient and allows your bot to react instantly.
The endpoint for hashtag streaming is /api/v1/streaming/hashtag?tag=yourhashtag. When your client connects, the server sends JSON objects representing new statuses that include the specified hashtag. The connection stays open until your client disconnects or the server closes it.
Prerequisites
Before building the bot, ensure you have the following:
- Python 3.7 or later installed on your system.
- A Mastodon account on any instance. The bot will use this account to authenticate and perform actions.
- An application registered on the Mastodon instance with read and write scopes. You can register an application in Preferences > Development.
- The Mastodon.py library installed via pip:
pip install Mastodon.py.
Steps to Build the Hashtag Bot
Follow these steps to create a Python script that listens to a hashtag and automatically boosts each matching post.
- Register your application and get credentials
Log in to your Mastodon account. Go to Preferences > Development > New Application. Enter a name for your bot, such as “HashtagBooster”. Under Scopes, selectread:statusesandwrite:statuses. Click Submit. Copy the Client Key, Client Secret, and Access Token from the application page. Save these in a file namedconfig.py. - Create the main bot script
Open a new Python file, for examplehashtag_bot.py. Import the Mastodon class from Mastodon.py and the StreamListener class. Define a class that inherits from StreamListener and overrides theon_updatemethod. This method receives a status object and can call API methods likestatus_reblogto boost the post. - Implement the StreamListener subclass
Inside your subclass, write theon_updatemethod. The method receives one parameter:status. Check if the status has the hashtag you are monitoring. Then callmastodon.status_reblog(status['id'])to boost the post. Optionally, add a brief delay usingtime.sleep(2)to avoid rate limiting. - Connect to the streaming endpoint
In the main block of your script, create an instance of the Mastodon class using your credentials. Then call thestream_hashtagmethod with your hashtag string and an instance of your listener. Example:mastodon.stream_hashtag('python', listener). This opens the WebSocket connection and starts receiving posts. - Run the bot
Execute the script from your terminal:python hashtag_bot.py. The bot will print incoming posts to the console and boost them. Leave the terminal open to keep the bot running. To stop it, press Ctrl+C.
Things to Avoid and Common Pitfalls
Bot Triggers Rate Limiting or Gets Blocked
Mastodon instances enforce rate limits on API calls. If your bot boosts every post immediately, it may exceed the limit and receive a 429 Too Many Requests error. Always add a delay between actions. Use time.sleep(5) or longer. Also, avoid boosting posts from a single user repeatedly in a short period.
Hashtag Case Sensitivity
Hashtags in Mastodon are case-insensitive. When filtering posts in your on_update method, compare the hashtag in lowercase. The streaming API delivers the tag in the format you specified, but users may type it in mixed case. Use status['tags'] to get a list of tag objects and check tag['name'].lower().
Connection Drops Unexpectedly
The streaming API connection may drop due to network issues or server restarts. The Mastodon.py library automatically reconnects if you set run_async=True and handle exceptions. Alternatively, wrap the stream_hashtag call in a while True loop with a try-except block to restart the stream on disconnection.
Bot Account Gets Suspended for Spam
Running a bot that automatically interacts with many posts can be mistaken for spam. Add a cooldown: track the last boost time per user and skip if the same user posted within the last 60 seconds. Also, include a note in your bot’s profile that it is automated and provide a way to opt out.
Mastodon Streaming API vs REST API for Hashtag Bots
| Item | Streaming API | REST API |
|---|---|---|
| Connection type | Persistent WebSocket | Short-lived HTTP requests |
| Data delivery | Pushed in real time | Pulled by polling |
| Latency | Sub-second | Depends on polling interval (typically 5-60 seconds) |
| Rate limit risk | Low — one connection | High — many requests per minute |
| Complexity | Requires event loop or threading | Simple loop with requests |
| Use case | Real-time reactions like boosting, replying | Periodic batch processing or analytics |
You can now build a Mastodon hashtag bot that listens in real time using the Streaming API and the Mastodon.py library. Start by registering an application, creating a StreamListener subclass, and connecting to stream_hashtag. Add a delay between actions and handle reconnections to keep the bot stable. For a more advanced bot, extend the on_update method to reply with custom messages or bookmark posts. Consider running the bot on a low-cost VPS or a Raspberry Pi so it stays online continuously.