Skip to main content

Transfer posts from Mastodon to Bluesky

Project description

Mastodon to Bluesky Transfer Tool

Python 3.11+ License: MIT Code style: ruff

A command-line tool to transfer your posts from Mastodon to Bluesky, preserving media attachments, thread structure, and rich text formatting.

Why This Tool?

As social media platforms evolve, many users find themselves wanting to establish a presence on multiple platforms. This tool helps you migrate your Mastodon content to Bluesky while preserving as much of the original formatting and context as possible. Whether you're cross-posting, migrating, or just backing up your content, this tool automates what would otherwise be a tedious manual process.

Features

  • Transfer posts from Mastodon to Bluesky
  • Preserve media attachments (up to 4 images per post)
  • Convert long posts into proper threads
  • Parse and preserve mentions, hashtags, and links
  • Handle content warnings
  • Incremental transfers (remembers what's been transferred)
  • Dry-run mode for testing
  • Filter by date range, replies, and boosts
  • Interactive mode for selective transfers
  • Configuration file and environment variable support
  • Automatic retry with exponential backoff

Requirements

  • Python 3.11 or higher
  • A Mastodon account with an access token
  • A Bluesky account with an app password

Installation

Using uv tool (recommended for regular use)

# Install the tool globally
uv tool install mastodon-to-bluesky

# Now use it directly
mastodon-to-bluesky transfer --help

# Update to latest version
uv tool upgrade mastodon-to-bluesky

# Uninstall
uv tool uninstall mastodon-to-bluesky

Using uvx (for one-time use)

# Run without installing
uvx mastodon-to-bluesky transfer --help

# Or use with environment variables set
uvx mastodon-to-bluesky transfer --limit 10

# Run a specific version
uvx mastodon-to-bluesky@1.0.0 transfer --help

Using pip

pip install mastodon-to-bluesky

From source

git clone https://github.com/jonatkinson/mastodon-to-bluesky.git
cd mastodon-to-bluesky
uv pip install -e .

Quick Start

  1. Get your Mastodon access token:

    • Go to your Mastodon instance settings
    • Navigate to Development > New Application
    • Give it a name and grant read permissions
    • Copy the access token
  2. Get your Bluesky app password:

    • Go to Settings > App Passwords in Bluesky
    • Create a new app password
    • Copy the generated password
  3. Run the transfer:

uvx mastodon-to-bluesky transfer \
  --mastodon-instance https://mastodon.social \
  --mastodon-token YOUR_MASTODON_TOKEN \
  --bluesky-handle you.bsky.social \
  --bluesky-password YOUR_APP_PASSWORD

Configuration

Configuration File

Create ~/.config/mastodon-to-bluesky/config.json:

{
  "mastodon_instance": "https://mastodon.social",
  "mastodon_token": "your-mastodon-token",
  "bluesky_handle": "you.bsky.social",
  "bluesky_password": "your-app-password"
}

Environment Variables

export MASTODON_INSTANCE="https://mastodon.social"
export MASTODON_TOKEN="your-mastodon-token"
export BLUESKY_HANDLE="you.bsky.social"
export BLUESKY_PASSWORD="your-app-password"

Usage Examples

Test Connections

Test your Mastodon connection:

uvx mastodon-to-bluesky test-mastodon --limit 5

Test your Bluesky connection:

uvx mastodon-to-bluesky test-bluesky

Transfer Options

Dry run (preview what would be posted):

uvx mastodon-to-bluesky transfer --dry-run --limit 10

Transfer posts from a specific date range:

uvx mastodon-to-bluesky transfer \
  --since 2024-01-01 \
  --until 2024-12-31

Include replies and boosts:

uvx mastodon-to-bluesky transfer \
  --include-replies \
  --include-boosts

Interactive mode (select posts one by one):

uvx mastodon-to-bluesky transfer --interactive --limit 20

Retry failed posts:

uvx mastodon-to-bluesky retry-failed

How It Works

  1. Fetches posts from your Mastodon account via the API
  2. Converts content from HTML to plain text while preserving formatting
  3. Downloads media attachments (images only, up to 4 per post)
  4. Splits long posts into threads (Bluesky has a 300-character limit)
  5. Parses rich text to create proper mentions, hashtags, and links
  6. Creates posts on Bluesky with proper threading
  7. Tracks progress to avoid duplicates in future runs

Features in Detail

Media Handling

  • Downloads and re-uploads images (JPEG, PNG, GIF, WebP)
  • Preserves alt text from Mastodon
  • Supports up to 4 images per post (Bluesky limitation)
  • Videos and audio files are skipped with a note

Text Processing

  • Converts HTML to plain text
  • Preserves paragraph breaks
  • Handles mentions (@user.bsky.social format)
  • Preserves hashtags and links
  • Content warnings become "CW: [warning]" prefix

Thread Creation

  • Posts over 300 characters are split into threads
  • Each part is numbered (e.g., "[1/3]", "[2/3]", "[3/3]")
  • Smart splitting at sentence boundaries
  • Maintains readability at split points

State Management

  • Tracks transferred post IDs in .mastodon-to-bluesky-state.json
  • Stores state in the current directory by default
  • Allows incremental transfers
  • Prevents duplicate posts

Retry Logic

  • Automatic retry for failed posts with exponential backoff
  • Categorizes errors (rate limit, network, API errors)
  • Configurable retry attempts (default: 3)
  • Manual retry command for persistent failures

Limitations

  • Post timestamps: Bluesky doesn't support backdating posts. All transferred posts will have the current date/time. The original Mastodon timestamp is appended to each post as "[Originally posted: YYYY-MM-DD HH:MM UTC]"
  • Media types: Only supports image media (no video/audio yet)
  • Polls: Not supported (Bluesky doesn't have polls)
  • Formatting: Some rich text formatting may be simplified
  • Quote posts: Converted to regular posts with links
  • Post visibility: All posts are public on Bluesky (no granular privacy controls)

Troubleshooting

"Rate limit exceeded"

The tool handles rate limits automatically by waiting. If you see repeated rate limit errors, wait a few minutes before retrying.

"Authentication failed"

  • For Mastodon: Check your access token has read permissions
  • For Bluesky: Make sure you're using an app password, not your main password

"Failed to parse mention"

Some Mastodon mentions may not have corresponding Bluesky accounts. These are left as plain text.

Media upload failures

  • Check file size (Bluesky has limits)
  • Ensure the media URL is still accessible
  • Try running with fewer posts at a time

"Invalid datetime format" errors

  • This is usually due to timezone handling
  • The tool now converts all timestamps to current time due to Bluesky limitations
  • Original timestamps are preserved in the post text

Development

Setup

# Clone the repository
git clone https://github.com/jonatkinson/mastodon-to-bluesky.git
cd mastodon-to-bluesky

# Install dependencies
uv sync

# Run tests
uv run pytest

# Run with local changes
uv run mastodon-to-bluesky --help

Project Structure

mastodon-to-bluesky/
├── src/mastodon_to_bluesky/
│   ├── __init__.py
│   ├── cli.py          # Command-line interface
│   ├── mastodon.py     # Mastodon API client
│   ├── bluesky.py      # Bluesky API client
│   ├── models.py       # Data models
│   └── transfer.py     # Transfer logic
├── tests/              # Test files
├── pyproject.toml      # Project configuration
└── README.md           # This file

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

License

This project is licensed under the MIT License - see the LICENSE file for details.

Changelog

See CHANGELOG.md for a list of changes in each version.

Acknowledgments

  • Thanks to the Mastodon and Bluesky communities
  • Built with atproto for Bluesky integration
  • Uses BeautifulSoup for HTML parsing
  • CLI powered by Click and Rich

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mastodon_to_bluesky-1.0.0.tar.gz (58.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mastodon_to_bluesky-1.0.0-py3-none-any.whl (22.0 kB view details)

Uploaded Python 3

File details

Details for the file mastodon_to_bluesky-1.0.0.tar.gz.

File metadata

  • Download URL: mastodon_to_bluesky-1.0.0.tar.gz
  • Upload date:
  • Size: 58.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for mastodon_to_bluesky-1.0.0.tar.gz
Algorithm Hash digest
SHA256 2b58928d61e97106dfd26d916a71a7e9bb2780b1ec299ca2f474f5e0afa86a0e
MD5 22b855e7867161c45331568e45dc871b
BLAKE2b-256 1249b73603cd5e1381f2ce925e5430fb332fcaca3672f04da469a6eb98516326

See more details on using hashes here.

Provenance

The following attestation bundles were made for mastodon_to_bluesky-1.0.0.tar.gz:

Publisher: publish.yml on jonatkinson/mastodon-to-bluesky

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mastodon_to_bluesky-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for mastodon_to_bluesky-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 901dec4a17a86f172c7dd7d7c46b5eabf8980be86f53da5153bea6240edd98f7
MD5 e772f3603c06e18d3c36400c1f51c0df
BLAKE2b-256 812e400c114323583cbc8d053c36f51e2eba0a0533f4b4889e3dd0434900148e

See more details on using hashes here.

Provenance

The following attestation bundles were made for mastodon_to_bluesky-1.0.0-py3-none-any.whl:

Publisher: publish.yml on jonatkinson/mastodon-to-bluesky

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page