Skip to main content

Migrate X (Twitter) lists and follows between accounts

Project description

x-migrate

PyPI version CI Python 3.11+ License: MIT

Migrate X (Twitter) lists and follows between accounts.

Extract members from any X list or following page, then follow them or add them to a list on your destination account — with automatic rate-limit recovery, progress tracking, and a Rich TUI.

Requirements

  • Python 3.11+
  • Google Chrome installed

Installation

pip install x-migrate
playwright install chromium
Install from source
git clone https://github.com/tongliuTL/x-migrate
cd x-migrate
pip install -e .
playwright install chromium

Quick Start

Tip: All commands support the short alias xm — use it instead of x-migrate to save typing.

1. Run setup wizard (first time only)

xm setup

Creates ~/.x-migrate/config.toml with your source and destination Chrome profile paths and daily follow limit.

2. Extract members from an X list

xm extract --source list --url "https://x.com/i/lists/YOUR_LIST_ID"

The /members suffix is added automatically if omitted.

Or extract from someone's following list:

xm extract --source following --account "@handle"

3. Follow those members from your destination account

# Follow up to 20 members (default) with an interactive login prompt:
xm follow

# Increase the daily cap:
xm follow --limit 50

# Unattended mode — skips login prompts (requires a saved browser session):
xm follow --auto

# Auto-resume after a rate-limit hit, fully unattended:
xm follow --auto --backoff 2h

# Walk away and let it finish overnight:
xm follow --auto --limit 400 --backoff 3h

# Preview who would be followed without opening a browser:
xm follow --dry-run

4. Add to a list instead of following

xm list-add --list-name "My List Name"

5. Check progress

xm report

Shows migration progress from local data (no browser needed). To cross-check against your live following list:

xm report --verify

Rate Limits

X typically allows ~400 follows per day. x-migrate detects rate limiting automatically and can either stop (default) or sleep and retry:

Behaviour Command
Stop on rate limit, re-run manually next day xm follow
Stop on rate limit, skip login prompt on re-run xm follow --auto
Auto-retry after 2 hours, fully unattended xm follow --auto --backoff 2h

Accepted backoff formats: 2h, 90m, 3600s. Progress is saved after every follow — it is always safe to Ctrl-C mid-run.

The --limit cap is the total for the entire invocation, across all retry sessions.

Configuration

~/.x-migrate/config.toml:

source_profile = "/path/to/source/profile"
dest_profile   = "/path/to/dest/profile"
daily_limit    = 20       # default for --limit when not specified
active_job     = "a1b2c3d4e5f6"   # auto-set by xm extract

Data Storage

All data is stored under ~/.x-migrate/:

Path Contents
config.toml Settings — profiles, daily limit, active job
profile_source/ Chrome profile for source account (saved login session)
profile_dest/ Chrome profile for destination account
progress/ Per-job JSON files tracking follow status per user

Commands

Command Description
xm setup Create or update ~/.x-migrate/config.toml
xm extract Extract members from a list or following page
xm follow Follow extracted members on destination account
xm list-add Add extracted members to a named list
xm report Show local progress; --verify cross-checks live data

All commands also work as x-migrate <command>.

xm follow options

Flag Default Description
--limit N daily_limit from config Maximum follows for this invocation
--auto off Skip login prompts (uses saved browser session)
--backoff DURATION 0 (disabled) Sleep duration after a rate limit before retrying
--dry-run off Print the follow plan without opening a browser

Development

git clone https://github.com/tongliuTL/x-migrate
cd x-migrate
pip install -e ".[dev]"
pytest

See CONTRIBUTING.md for guidelines on submitting changes.

Releasing a new version

  1. Update version in pyproject.toml
  2. Add a ## [X.Y.Z] — YYYY-MM-DD section to CHANGELOG.md
  3. Commit and tag:
    git commit -m "chore: bump version and changelog (vX.Y.Z)"
    git tag vX.Y.Z
    git push && git push --tags
    
  4. GitHub Actions runs tests, builds the wheel, publishes a GitHub Release, and pushes to PyPI automatically.

Pre-releases (e.g. v0.2.0-beta.1) are automatically marked as pre-release on GitHub.

Contributing

Bug reports, feature requests, and pull requests are welcome — see CONTRIBUTING.md.

License

MIT

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

x_migrate-0.2.0.tar.gz (34.5 kB view details)

Uploaded Source

Built Distribution

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

x_migrate-0.2.0-py3-none-any.whl (20.3 kB view details)

Uploaded Python 3

File details

Details for the file x_migrate-0.2.0.tar.gz.

File metadata

  • Download URL: x_migrate-0.2.0.tar.gz
  • Upload date:
  • Size: 34.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for x_migrate-0.2.0.tar.gz
Algorithm Hash digest
SHA256 e474d7f4708cacbaabe2784aec7511813f870082ab8be3c0c55946a4ba00f40c
MD5 e0f104cf3adbaf9e4bcbeb7a525795f3
BLAKE2b-256 ff6192deb4140bd57b716b6bf55a3910de0fe7479c6d63185d4f40f6ce52fb2a

See more details on using hashes here.

Provenance

The following attestation bundles were made for x_migrate-0.2.0.tar.gz:

Publisher: release.yml on tongliuTL/x-migrate

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

File details

Details for the file x_migrate-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: x_migrate-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 20.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for x_migrate-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3eb33ab02f529e7d6ec37ca3fa96e8a9c92296ee3a91e2a5c364624b3a0ec7ae
MD5 6cf6601a221e01e1d0e7ba5bcf6ae596
BLAKE2b-256 651fcb7863c015c5e87b9d9e22f9ec37b2821c2231b9c4d1d77e4ae7838b07b4

See more details on using hashes here.

Provenance

The following attestation bundles were made for x_migrate-0.2.0-py3-none-any.whl:

Publisher: release.yml on tongliuTL/x-migrate

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