Migrate X (Twitter) lists and follows between accounts
Project description
x-migrate
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 rate-limit detection, progress tracking, and a Rich TUI.
Requirements
- Python 3.11+
- Google Chrome installed
Installation
From PyPI (recommended)
pip install x-migrate
playwright install chromium
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 ofx-migrateto save typing.
1. Run setup wizard (first time only)
xm setup
This 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
/memberssuffix 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):
xm follow
Increase the limit:
xm follow --limit 50
Preview who would be followed without launching the 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. The script detects rate limiting and stops automatically. Re-run the next day — your progress is saved in ~/.x-migrate/progress/.
Configuration
Configuration is stored in ~/.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 extract
Data Storage
All data is stored in ~/.x-migrate/:
config.toml— settings (profiles, daily limit)profile_source/— Chrome profile for source account (contains login session)profile_dest/— Chrome profile for destination accountprogress/— per-job progress files (JSON format, automatically managed)
Development
Install with dev dependencies:
pip install -e ".[dev]"
Run tests:
pytest
Releasing a new version
- Update
versioninpyproject.toml - Add a
## [X.Y.Z] — YYYY-MM-DDsection toCHANGELOG.md - Commit:
git commit -m "Release vX.Y.Z" - Tag and push:
git tag vX.Y.Z git push && git push --tags
- 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.
Commands
xm setup— Create or update configurationxm extract— Extract members from a list or following listxm follow— Follow extracted members on destination accountxm list-add— Add extracted members to a listxm report— Show progress from local data; add--verifyto scrape live following list
All commands also work as
x-migrate <command>if you prefer the full name.
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file x_migrate-0.1.2.tar.gz.
File metadata
- Download URL: x_migrate-0.1.2.tar.gz
- Upload date:
- Size: 29.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4c00efbed88c90d565528c4393afb07c32d009644b8a561ed5ed353a6f35f5a3
|
|
| MD5 |
0f33193d7283d073e1ba0c8533a99815
|
|
| BLAKE2b-256 |
fcf225fbbb8dcb1c83c0f430f7aed0200b4fc18499a1cbd14e551f1af0cad8b4
|
Provenance
The following attestation bundles were made for x_migrate-0.1.2.tar.gz:
Publisher:
release.yml on tongliuTL/x-migrate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
x_migrate-0.1.2.tar.gz -
Subject digest:
4c00efbed88c90d565528c4393afb07c32d009644b8a561ed5ed353a6f35f5a3 - Sigstore transparency entry: 1154605178
- Sigstore integration time:
-
Permalink:
tongliuTL/x-migrate@51c4f21de927f60c58fbff7dd7935a2c3ec74d33 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/tongliuTL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@51c4f21de927f60c58fbff7dd7935a2c3ec74d33 -
Trigger Event:
push
-
Statement type:
File details
Details for the file x_migrate-0.1.2-py3-none-any.whl.
File metadata
- Download URL: x_migrate-0.1.2-py3-none-any.whl
- Upload date:
- Size: 19.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1cae6c1a5b82dac45316ceb1223f96cbd31179043306e7482115816ef451ea33
|
|
| MD5 |
14377e712265f7bbf488b60521e49f90
|
|
| BLAKE2b-256 |
3b35f0b48185275317406af4611dffc071adad3724130ec4c20e52a21d5fea63
|
Provenance
The following attestation bundles were made for x_migrate-0.1.2-py3-none-any.whl:
Publisher:
release.yml on tongliuTL/x-migrate
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
x_migrate-0.1.2-py3-none-any.whl -
Subject digest:
1cae6c1a5b82dac45316ceb1223f96cbd31179043306e7482115816ef451ea33 - Sigstore transparency entry: 1154605182
- Sigstore integration time:
-
Permalink:
tongliuTL/x-migrate@51c4f21de927f60c58fbff7dd7935a2c3ec74d33 -
Branch / Tag:
refs/tags/v0.1.2 - Owner: https://github.com/tongliuTL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@51c4f21de927f60c58fbff7dd7935a2c3ec74d33 -
Trigger Event:
push
-
Statement type: