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 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 ofx-migrateto 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
/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) 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
- Update
versioninpyproject.toml - Add a
## [X.Y.Z] — YYYY-MM-DDsection toCHANGELOG.md - Commit and tag:
git commit -m "chore: bump version and changelog (vX.Y.Z)" 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.
Contributing
Bug reports, feature requests, and pull requests are welcome — see CONTRIBUTING.md.
License
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.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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e474d7f4708cacbaabe2784aec7511813f870082ab8be3c0c55946a4ba00f40c
|
|
| MD5 |
e0f104cf3adbaf9e4bcbeb7a525795f3
|
|
| BLAKE2b-256 |
ff6192deb4140bd57b716b6bf55a3910de0fe7479c6d63185d4f40f6ce52fb2a
|
Provenance
The following attestation bundles were made for x_migrate-0.2.0.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.2.0.tar.gz -
Subject digest:
e474d7f4708cacbaabe2784aec7511813f870082ab8be3c0c55946a4ba00f40c - Sigstore transparency entry: 1436075283
- Sigstore integration time:
-
Permalink:
tongliuTL/x-migrate@095ab6dd7960c0988ecab5cb4254f50d919d0276 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/tongliuTL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@095ab6dd7960c0988ecab5cb4254f50d919d0276 -
Trigger Event:
push
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3eb33ab02f529e7d6ec37ca3fa96e8a9c92296ee3a91e2a5c364624b3a0ec7ae
|
|
| MD5 |
6cf6601a221e01e1d0e7ba5bcf6ae596
|
|
| BLAKE2b-256 |
651fcb7863c015c5e87b9d9e22f9ec37b2821c2231b9c4d1d77e4ae7838b07b4
|
Provenance
The following attestation bundles were made for x_migrate-0.2.0-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.2.0-py3-none-any.whl -
Subject digest:
3eb33ab02f529e7d6ec37ca3fa96e8a9c92296ee3a91e2a5c364624b3a0ec7ae - Sigstore transparency entry: 1436075289
- Sigstore integration time:
-
Permalink:
tongliuTL/x-migrate@095ab6dd7960c0988ecab5cb4254f50d919d0276 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/tongliuTL
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@095ab6dd7960c0988ecab5cb4254f50d919d0276 -
Trigger Event:
push
-
Statement type: