Skip to content

Multi-Account Management

Manage multiple X/Twitter accounts safely with XTools session isolation.

Account Manager Setup

from dataclasses import dataclass
from xtools import XTools

@dataclass
class Account:
    username: str
    cookies_path: str
    proxy: str = None
    active: bool = True

class AccountManager:
    def __init__(self, accounts: list[Account]):
        self.accounts = {acc.username: acc for acc in accounts}
        self.clients: dict[str, XTools] = {}

    async def get_client(self, username: str) -> XTools:
        if username not in self.clients:
            account = self.accounts[username]
            client = XTools(headless=True, proxy=account.proxy)
            await client.auth.load_cookies(account.cookies_path)
            self.clients[username] = client
        return self.clients[username]

    async def close_all(self):
        for client in self.clients.values():
            await client.close()
        self.clients.clear()

Use Separate Proxies

Each account should use a different proxy/IP to avoid association and mass bans.

Configuration File

# accounts.yaml
accounts:
  - username: "account1"
    cookies_path: "sessions/account1.json"
    proxy: "http://proxy1:8080"
    tags: ["main", "engagement"]
  - username: "account2"
    cookies_path: "sessions/account2.json"
    proxy: "http://proxy2:8080"
    tags: ["scraping"]
import yaml

def load_accounts(config_path: str) -> list[Account]:
    with open(config_path) as f:
        config = yaml.safe_load(f)
    return [Account(**acc) for acc in config["accounts"]]

accounts = load_accounts("accounts.yaml")
manager = AccountManager(accounts)

Round-Robin Operations

from itertools import cycle

async def distributed_scrape(usernames: list[str]):
    """Distribute scraping across multiple accounts."""
    accounts = load_accounts("accounts.yaml")
    scraping_accounts = [a for a in accounts if "scraping" in a.get("tags", [])]
    account_cycle = cycle(scraping_accounts)

    results = []
    for username in usernames:
        account = next(account_cycle)
        async with XTools(proxy=account.proxy) as x:
            await x.auth.load_cookies(account.cookies_path)
            profile = await x.scrape.profile(username)
            results.append(profile)
        await asyncio.sleep(2)
    return results

Tag Accounts by Purpose

Use tags to separate accounts for different tasks (scraping, engagement, posting).

Account Health Monitoring

from datetime import datetime

@dataclass
class AccountHealth:
    username: str
    is_active: bool
    is_suspended: bool
    last_checked: datetime

async def check_account_health(account: Account) -> AccountHealth:
    try:
        async with XTools(proxy=account.proxy) as x:
            await x.auth.load_cookies(account.cookies_path)
            await x.scrape.profile(account.username)
            return AccountHealth(account.username, True, False, datetime.now())
    except Exception as e:
        return AccountHealth(
            account.username, False, "suspended" in str(e).lower(), datetime.now()
        )

async def monitor_all_accounts():
    accounts = load_accounts("accounts.yaml")
    health_reports = await asyncio.gather(
        *[check_account_health(acc) for acc in accounts]
    )
    for report in health_reports:
        status = "🟢" if report.is_active else "🔴"
        print(f"{status} @{report.username}")

Suspended Account Detection

Regularly check account health and remove suspended accounts from rotation.

Concurrent Multi-Account Operations

async def parallel_engagement(tweet_url: str, accounts: list[Account]):
    """Like a tweet from multiple accounts with staggered timing."""
    async def like_from_account(account: Account, delay: int):
        await asyncio.sleep(delay)
        async with XTools(proxy=account.proxy) as x:
            await x.auth.load_cookies(account.cookies_path)
            await x.engage.like(tweet_url)
        return account.username

    tasks = [like_from_account(acc, i * 5) for i, acc in enumerate(accounts)]
    return await asyncio.gather(*tasks, return_exceptions=True)

Session Persistence

async def refresh_all_sessions():
    """Refresh and save sessions for all accounts."""
    accounts = load_accounts("accounts.yaml")
    for account in accounts:
        try:
            async with XTools(proxy=account.proxy) as x:
                await x.auth.load_cookies(account.cookies_path)
                await x.scrape.profile(account.username)
                await x.auth.save_cookies(account.cookies_path)
                print(f"✓ Refreshed: @{account.username}")
        except Exception as e:
            print(f"✗ Failed: @{account.username} - {e}")