Python wrapper for the Mastodon API providing comprehensive access to social media functionality
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Creating, editing, and managing posts (statuses/toots) on Mastodon including media attachments, polls, scheduling, and all status-related actions like favoriting, boosting, and bookmarking.
Create new posts with various content types, media attachments, and configuration options.
def status_post(
self,
status: str,
in_reply_to_id: int = None,
media_ids: list = None,
sensitive: bool = False,
visibility: str = None,
spoiler_text: str = None,
language: str = None,
idempotency_key: str = None,
content_type: str = None,
scheduled_at: datetime = None,
poll: dict = None,
quote_id: int = None
) -> dict:
"""
Create a new status (post/toot).
Args:
status: Status text content (required)
in_reply_to_id: ID of status to reply to
media_ids: List of media attachment IDs
sensitive: Mark as sensitive content
visibility: Visibility level ('public', 'unlisted', 'private', 'direct')
spoiler_text: Content warning/spoiler text
language: ISO 639-1 language code
idempotency_key: Unique key to prevent duplicate posts
content_type: Content type ('text/plain', 'text/markdown', 'text/html')
scheduled_at: Schedule post for future publication
poll: Poll configuration dictionary
quote_id: ID of status to quote (instance-dependent)
Returns:
Dictionary containing created status information
"""
def toot(self, status: str) -> dict:
"""
Alias for status_post() - not recommended, use status_post() instead.
Args:
status: Status text content
Returns:
Dictionary containing created status information
"""
def status_reply(
self,
to_status: dict,
status: str,
media_ids: list = None,
sensitive: bool = False,
visibility: str = None,
spoiler_text: str = None,
language: str = None,
idempotency_key: str = None,
content_type: str = None,
scheduled_at: datetime = None,
poll: dict = None,
untag: bool = False
) -> dict:
"""
Reply to an existing status with automatic mention handling.
Args:
to_status: Status dictionary to reply to
status: Reply text content
media_ids: List of media attachment IDs
sensitive: Mark as sensitive content
visibility: Visibility level (defaults to original status visibility)
spoiler_text: Content warning/spoiler text
language: ISO 639-1 language code
idempotency_key: Unique key to prevent duplicate posts
content_type: Content type
scheduled_at: Schedule reply for future publication
poll: Poll configuration dictionary
untag: Remove automatic mentions from reply
Returns:
Dictionary containing created reply status
"""Edit existing posts and view edit history (Mastodon 3.5.0+).
def status_update(
self,
id: int,
status: str = None,
spoiler_text: str = None,
sensitive: bool = None,
media_ids: list = None,
poll: dict = None,
language: str = None
) -> dict:
"""
Edit an existing status (Mastodon 3.5.0+).
Args:
id: Status ID to edit
status: New status text content
spoiler_text: New content warning/spoiler text
sensitive: New sensitive content flag
media_ids: New list of media attachment IDs
poll: New poll configuration
language: New ISO 639-1 language code
Returns:
Dictionary containing updated status information
"""
def status_history(self, id: int) -> list:
"""
Get edit history for a status (Mastodon 3.5.0+).
Args:
id: Status ID
Returns:
List of status edit history entries
"""
def status_source(self, id: int) -> dict:
"""
Get the source text of a status for editing purposes.
Args:
id: Status ID
Returns:
Dictionary containing status source information
"""
def generate_media_edit_attributes(
self,
media_dict: dict,
media_ids: list
) -> list:
"""
Helper function to generate media edit attributes for status updates.
Args:
media_dict: Dictionary of media attachment updates
media_ids: List of media IDs to update
Returns:
List of media edit attribute dictionaries
"""Retrieve status details, context, and interaction information.
def status(self, id: int) -> dict:
"""
Get a single status by ID.
Args:
id: Status ID
Returns:
Dictionary containing status information
"""
def statuses(self, ids: list) -> list:
"""
Get multiple statuses by IDs (Mastodon 4.3.0+).
Args:
ids: List of status IDs
Returns:
List of status dictionaries
"""
def status_context(self, id: int) -> dict:
"""
Get the context (ancestors and descendants) of a status.
Args:
id: Status ID
Returns:
Dictionary with 'ancestors' and 'descendants' lists
"""
def status_card(self, id: int) -> dict:
"""
Get the preview card for a status (deprecated - use status() instead).
Args:
id: Status ID
Returns:
Dictionary containing preview card information
"""
def status_reblogged_by(
self,
id: int,
max_id: int = None,
min_id: int = None,
since_id: int = None,
limit: int = 40
) -> list:
"""
Get accounts that reblogged (boosted) a status.
Args:
id: Status ID
max_id: Return results older than this ID
min_id: Return results newer than this ID
since_id: Return results newer than this ID
limit: Maximum number of results (default 40, max 80)
Returns:
List of account dictionaries
"""
def status_favourited_by(
self,
id: int,
max_id: int = None,
min_id: int = None,
since_id: int = None,
limit: int = 40
) -> list:
"""
Get accounts that favorited a status.
Args:
id: Status ID
max_id: Return results older than this ID
min_id: Return results newer than this ID
since_id: Return results newer than this ID
limit: Maximum number of results (default 40, max 80)
Returns:
List of account dictionaries
"""Perform actions on statuses including favoriting, boosting, bookmarking, and deletion.
def status_favourite(self, id: int) -> dict:
"""
Favorite (like) a status.
Args:
id: Status ID to favorite
Returns:
Dictionary containing updated status with favorited=True
"""
def status_unfavourite(self, id: int) -> dict:
"""
Remove favorite from a status.
Args:
id: Status ID to unfavorite
Returns:
Dictionary containing updated status with favorited=False
"""
def status_reblog(self, id: int, visibility: str = None) -> dict:
"""
Reblog (boost) a status.
Args:
id: Status ID to reblog
visibility: Visibility of the reblog ('public', 'unlisted', 'private')
Returns:
Dictionary containing the reblog status
"""
def status_unreblog(self, id: int) -> dict:
"""
Remove reblog from a status.
Args:
id: Status ID to unreblog
Returns:
Dictionary containing the original status with reblogged=False
"""
def status_bookmark(self, id: int) -> dict:
"""
Bookmark a status for later reference.
Args:
id: Status ID to bookmark
Returns:
Dictionary containing updated status with bookmarked=True
"""
def status_unbookmark(self, id: int) -> dict:
"""
Remove bookmark from a status.
Args:
id: Status ID to remove bookmark from
Returns:
Dictionary containing updated status with bookmarked=False
"""
def status_delete(self, id: int) -> dict:
"""
Delete a status.
Args:
id: Status ID to delete (must be owned by authenticated user)
Returns:
Dictionary containing deleted status information
"""Pin statuses to profile, mute conversations, and translate content.
def status_pin(self, id: int) -> dict:
"""
Pin a status to your profile.
Args:
id: Status ID to pin (must be owned by authenticated user)
Returns:
Dictionary containing updated status with pinned=True
"""
def status_unpin(self, id: int) -> dict:
"""
Unpin a status from your profile.
Args:
id: Status ID to unpin
Returns:
Dictionary containing updated status with pinned=False
"""
def status_mute(self, id: int) -> dict:
"""
Mute notifications from a conversation thread.
Args:
id: Status ID in conversation to mute
Returns:
Dictionary containing updated status with muted=True
"""
def status_unmute(self, id: int) -> dict:
"""
Unmute notifications from a conversation thread.
Args:
id: Status ID in conversation to unmute
Returns:
Dictionary containing updated status with muted=False
"""
def status_translate(self, id: int, lang: str = None) -> dict:
"""
Translate a status to another language (Mastodon 4.0.0+).
Args:
id: Status ID to translate
lang: Target language code (auto-detected from user preferences if None)
Returns:
Dictionary containing translation information
"""Manage scheduled posts including viewing, updating, and deleting future posts.
def scheduled_statuses(
self,
max_id: int = None,
min_id: int = None,
since_id: int = None,
limit: int = 20
) -> list:
"""
Get scheduled statuses for the authenticated user.
Args:
max_id: Return results older than this ID
min_id: Return results newer than this ID
since_id: Return results newer than this ID
limit: Maximum number of results (default 20, max 40)
Returns:
List of scheduled status dictionaries
"""
def scheduled_status(self, id: int) -> dict:
"""
Get a single scheduled status by ID.
Args:
id: Scheduled status ID
Returns:
Dictionary containing scheduled status information
"""
def scheduled_status_update(
self,
id: int,
scheduled_at: datetime
) -> dict:
"""
Update the scheduled time for a scheduled status.
Args:
id: Scheduled status ID
scheduled_at: New scheduled publication time
Returns:
Dictionary containing updated scheduled status
"""
def scheduled_status_delete(self, id: int) -> dict:
"""
Delete a scheduled status.
Args:
id: Scheduled status ID to delete
Returns:
Empty dictionary on success
"""from mastodon import Mastodon
from datetime import datetime, timedelta
mastodon = Mastodon(
access_token='your_token',
api_base_url='https://mastodon.social'
)
# Simple status post
status = mastodon.status_post("Hello, Mastodon! 👋")
print(f"Posted status: {status['url']}")
# Status with content warning and sensitive flag
sensitive_status = mastodon.status_post(
"This is sensitive content behind a warning",
spoiler_text="Content Warning: Sensitive Topic",
sensitive=True,
visibility="unlisted"
)
# Schedule a status for later
future_time = datetime.now() + timedelta(hours=2)
scheduled = mastodon.status_post(
"This post will appear in 2 hours!",
scheduled_at=future_time
)
print(f"Scheduled status ID: {scheduled['id']}")# Upload media first
with open('image.jpg', 'rb') as image_file:
media = mastodon.media_post(
image_file,
description="A beautiful sunset photo"
)
# Create poll options
poll_options = {
'options': ['Option 1', 'Option 2', 'Option 3'],
'expires_in': 86400, # 24 hours in seconds
'multiple': False, # Single choice
'hide_totals': False # Show vote counts
}
# Post status with media and poll
status = mastodon.status_post(
"Check out this sunset! Also, what's your favorite time of day?",
media_ids=[media['id']],
poll=poll_options,
sensitive=False
)# Get a status to reply to
timeline = mastodon.timeline_home(limit=1)
original_status = timeline[0]
# Reply to the status
reply = mastodon.status_reply(
original_status,
"This is my reply to your post!",
visibility="public"
)
# Get the full conversation context
context = mastodon.status_context(reply['id'])
print(f"Ancestors: {len(context['ancestors'])}")
print(f"Descendants: {len(context['descendants'])}")
# Mute the conversation to stop notifications
mastodon.status_mute(reply['id'])# Get a status
status_id = 123456789
# Perform various actions
mastodon.status_favourite(status_id)
mastodon.status_reblog(status_id, visibility="public")
mastodon.status_bookmark(status_id)
# Check who interacted with the status
favorites = mastodon.status_favourited_by(status_id, limit=10)
reblogs = mastodon.status_reblogged_by(status_id, limit=10)
print(f"Favorited by {len(favorites)} accounts")
print(f"Reblogged by {len(reblogs)} accounts")
# Pin to profile (if it's your status)
my_status = mastodon.status_post("This is my pinned post!")
mastodon.status_pin(my_status['id'])# Create a status
original = mastodon.status_post("This is my original post with a typo.")
# Edit the status (Mastodon 3.5.0+)
edited = mastodon.status_update(
original['id'],
status="This is my original post with the typo fixed!",
language="en"
)
# View edit history
history = mastodon.status_history(original['id'])
print(f"Status has been edited {len(history) - 1} times")
# Get source text for further editing
source = mastodon.status_source(original['id'])
print(f"Source text: {source['text']}")from datetime import datetime, timedelta
# Create scheduled statuses
tomorrow = datetime.now() + timedelta(days=1)
next_week = datetime.now() + timedelta(weeks=1)
mastodon.status_post("Daily reminder!", scheduled_at=tomorrow)
mastodon.status_post("Weekly update!", scheduled_at=next_week)
# List all scheduled statuses
scheduled_list = mastodon.scheduled_statuses()
for scheduled in scheduled_list:
print(f"'{scheduled['params']['text']}' scheduled for {scheduled['scheduled_at']}")
# Update scheduling time
if scheduled_list:
new_time = datetime.now() + timedelta(hours=3)
updated = mastodon.scheduled_status_update(
scheduled_list[0]['id'],
scheduled_at=new_time
)
print(f"Rescheduled to: {updated['scheduled_at']}")# Status object structure
Status = {
'id': str, # Status ID
'created_at': str, # Creation timestamp
'in_reply_to_id': str, # ID of replied-to status
'in_reply_to_account_id': str,# ID of replied-to account
'sensitive': bool, # Contains sensitive content
'spoiler_text': str, # Content warning text
'visibility': str, # Visibility level
'language': str, # Language code
'uri': str, # ActivityPub URI
'url': str, # Web URL
'replies_count': int, # Number of replies
'reblogs_count': int, # Number of reblogs
'favourites_count': int, # Number of favorites
'edited_at': str, # Last edit timestamp
'favourited': bool, # User has favorited
'reblogged': bool, # User has reblogged
'muted': bool, # User has muted thread
'bookmarked': bool, # User has bookmarked
'pinned': bool, # Pinned to user profile
'content': str, # HTML content
'filtered': list, # Applied filters
'reblog': dict, # Reblogged status (if reblog)
'application': dict, # Publishing application
'account': dict, # Author account
'media_attachments': list, # Media files
'mentions': list, # Account mentions
'tags': list, # Hashtags
'emojis': list, # Custom emojis
'card': dict, # Preview card
'poll': dict, # Poll data
}
# Poll structure for status creation
Poll = {
'options': list, # List of option strings
'expires_in': int, # Expiration time in seconds
'multiple': bool, # Allow multiple choices
'hide_totals': bool, # Hide vote counts until closed
}
# Scheduled status structure
ScheduledStatus = {
'id': str, # Scheduled status ID
'scheduled_at': str, # Publication timestamp
'params': dict, # Status parameters
'media_attachments': list, # Media attachments
}Install with Tessl CLI
npx tessl i tessl/pypi-mastodon-py