Skip to content

Python Scripts for Multilogin X

Full Python examples for common Multilogin X API operations.

Complete Authentication + Profile Workflow

python
import requests
import time

BASE_URL = "https://api.multilogin.com"
LAUNCHER_URL = "https://launcher.mlx.yt:45001"

class MultiloginClient:
    def __init__(self, email, password):
        self.email = email
        self.password = password
        self.token = None
        self.token_time = None

    def signin(self):
        """Authenticate and get bearer token."""
        resp = requests.post(f"{BASE_URL}/user/signin", json={
            "email": self.email,
            "password": self.password
        })
        resp.raise_for_status()
        data = resp.json()
        self.token = data["data"]["token"]
        self.token_time = time.time()
        return self.token

    def refresh_token(self):
        """Refresh token before 30-minute expiry."""
        resp = requests.post(f"{BASE_URL}/user/refresh_token",
            headers=self._headers())
        resp.raise_for_status()
        self.token = resp.json()["data"]["token"]
        self.token_time = time.time()

    def ensure_token(self):
        """Auto-refresh if token is older than 25 minutes."""
        if self.token is None:
            self.signin()
        elif time.time() - self.token_time > 1500:  # 25 min
            self.refresh_token()

    def _headers(self):
        return {
            "Authorization": f"Bearer {self.token}",
            "Content-Type": "application/json"
        }

    def create_profile(self, name, folder_id, browser_type="mimic",
                       os_type="windows"):
        """Create a new browser profile."""
        self.ensure_token()
        resp = requests.post(f"{BASE_URL}/profile/create",
            headers=self._headers(),
            json={
                "name": name,
                "browser_type": browser_type,
                "os_type": os_type,
                "folder_id": folder_id,
                "parameters": {
                    "fingerprint": {
                        "flags": {
                            "audio_masking": "mask",
                            "fonts_masking": "mask",
                            "media_devices_masking": "mask",
                            "screen_masking": "real",
                            "graphics_masking": "mask",
                            "graphics_noise": "mask",
                            "webrtc_masking": "mask",
                            "geolocation_masking": "mask",
                            "timezone_masking": "mask",
                            "locale_masking": "mask"
                        }
                    },
                    "storage": {"is_local": False},
                    "proxy": {"type": "none"}
                }
            })
        resp.raise_for_status()
        return resp.json()["data"]["ids"][0]

    def start_profile(self, folder_id, profile_id,
                      automation_type="selenium"):
        """Start a browser profile and return the automation port."""
        self.ensure_token()
        url = (f"{LAUNCHER_URL}/api/v1/profile/f/{folder_id}"
               f"/p/{profile_id}/start"
               f"?automation_type={automation_type}")
        resp = requests.get(url, headers=self._headers())
        resp.raise_for_status()
        return resp.json()["status"]["message"]  # port number

    def stop_profile(self, profile_id):
        """Stop a running browser profile."""
        self.ensure_token()
        resp = requests.get(
            f"{LAUNCHER_URL}/api/v1/profile/stop/p/{profile_id}",
            headers=self._headers())
        resp.raise_for_status()

    def list_profiles(self, limit=50, offset=0):
        """List profiles in workspace."""
        self.ensure_token()
        resp = requests.get(
            f"{BASE_URL}/workspace/profiles",
            headers=self._headers(),
            params={"limit": limit, "offset": offset})
        resp.raise_for_status()
        return resp.json()["data"]


# Usage
if __name__ == "__main__":
    client = MultiloginClient("you@example.com", "your-password")
    client.signin()

    # List profiles
    profiles = client.list_profiles()
    print(f"Found {profiles['total']} profiles")

    # Create a profile
    profile_id = client.create_profile("test-profile", "FOLDER_UUID")
    print(f"Created profile: {profile_id}")

    # Start with Selenium
    port = client.start_profile("FOLDER_UUID", profile_id)
    print(f"Selenium port: {port}")

    # ... automate with Selenium ...

    # Stop
    client.stop_profile(profile_id)

Bulk Profile Creation

python
def create_bulk_profiles(client, folder_id, count=10, prefix="profile"):
    """Create multiple profiles in bulk."""
    profile_ids = []
    for i in range(count):
        name = f"{prefix}-{i+1:03d}"
        pid = client.create_profile(name, folder_id)
        profile_ids.append(pid)
        print(f"Created: {name} -> {pid}")
    return profile_ids
python
COOKIES_URL = "https://cookies.multilogin.com"

def apply_cookies(client, profile_id, target="google"):
    """Apply pre-made cookies to a profile."""
    client.ensure_token()
    resp = requests.post(f"{COOKIES_URL}/api/v1/cookies/apply",
        headers={
            "Authorization": f"Bearer {client.token}",
            "Content-Type": "application/json"
        },
        json={
            "profile_id": profile_id,
            "target_website": target
        })
    resp.raise_for_status()
    print(f"Cookies applied: {target} -> {profile_id}")

Error Handling

python
def safe_api_call(func, *args, max_retries=3, **kwargs):
    """Retry API calls with exponential backoff."""
    for attempt in range(max_retries):
        try:
            return func(*args, **kwargs)
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 429:
                wait = 2 ** attempt
                print(f"Rate limited. Waiting {wait}s...")
                time.sleep(wait)
            elif e.response.status_code == 401:
                print("Token expired, re-authenticating...")
                # Re-auth logic here
                raise
            else:
                raise
    raise Exception(f"Failed after {max_retries} retries")