Files

6.9 KiB

gsd-browser Gmail Auto-Registration Pattern

Skill: bulk-account-registration Tool: gsd-browser (68 MCP tools) Alternative to: Playwright-based flow (references/gmail-playwright-flow.md) Discovered: 2026-06-23 — gsd-browser installed at C:\Users\User\.openagents\nodejs\gsd-browser.cmd

Why gsd-browser over raw Playwright

Factor Playwright gsd-browser
Lines of code 500+ Python (stealth, behavior, signup, proxy) 1 JSON browser_batch call
DOM resilience Selectors break when Google updates UI Semantic intents (fill_form, act) survive DOM changes
Session isolation Manual browser.new_context() --session reg-1 flag, built-in
Credential storage Manual JSON file Encrypted vault (browser_vault_save + GSD_BROWSER_VAULT_KEY)
Anti-detection Manual JS injection + launch args Built-in (patched Chromium, fingerprint rotation)
Parallel batches Manual threading --session per worker, isolated cookies

Core Pattern: Gmail Signup as a Single browser_batch

{
  "session": "gmail-wave-1",
  "steps": [
    {"action": "navigate", "url": "https://accounts.google.com/signup/v2/webcreateaccount?hl=en&flowName=GlifWebSignIn&flowEntry=SignUp"},
    {"action": "wait_for", "condition": "selector_visible", "value": "input[name='firstName']", "timeout": 15000},

    {"action": "fill_form", "values": {
      "First name": "John",
      "Last name": "Smith"
    }},
    {"action": "act", "intent": "click_next_button"},

    {"action": "wait_for", "condition": "selector_visible", "value": "select[name='month']"},
    {"action": "fill_form", "values": {
      "Month": "February",
      "Day": "4",
      "Year": "1990",
      "Gender": "Male"
    }},
    {"action": "act", "intent": "click_next_button"},

    {"action": "wait_for", "condition": "text_visible", "value": "Create your own Gmail address"},
    {"action": "act", "intent": "click_element", "element": "Create your own Gmail address"},
    {"action": "fill_form", "values": {
      "Username": "johnsmith7894"
    }},
    {"action": "act", "intent": "click_next_button"},

    {"action": "wait_for", "condition": "selector_visible", "value": "input[type='password']"},
    {"action": "fill_form", "values": {
      "Password": "Str0ngP@ss!2024",
      "Confirm": "Str0ngP@ss!2024"
    }},
    {"action": "act", "intent": "click_next_button"},

    {"action": "wait_for", "condition": "any", "values": [
      {"text_visible": "Welcome"},
      {"text_visible": "Verify your phone number"},
      {"text_visible": "Privacy and Terms"}
    ], "timeout": 20000},

    {"action": "screenshot", "name": "post-signup-state"},
    {"action": "extract", "schema": {
      "type": "object",
      "properties": {
        "on_welcome": {"type": "boolean"},
        "phone_required": {"type": "boolean"},
        "url": {"type": "string"}
      }
    }},
    {"action": "save_state", "name": "session-johnsmith7894"}
  ],
  "stop_on_failure": true,
  "summary_only": false
}

Phone Bypass Strategy Branches

After the password step, Google may or may not show phone verification. The wait_for with condition: "any" handles the fork:

Branch A: No phone (ideal)

Google routes straight to Terms → "I Agree" → Welcome. Account created.

Branch B: Skip button visible

{"action": "act", "intent": "click_element", "element": "Skip"},
{"action": "wait_for", "condition": "text_visible", "value": "Privacy and Terms"}

Branch C: Phone required, 5sim available

{"action": "act", "intent": "fill_phone_number", "value": "${5SIM_PHONE}"},
{"action": "act", "intent": "click_next_button"},
{"action": "wait_for", "condition": "text_visible", "value": "Enter verification code", "timeout": 120000},
{"action": "fill_form", "values": {"Verification code": "${5SIM_CODE}"}},
{"action": "act", "intent": "click_verify_button"}

Note: 5sim phone purchase + SMS polling happens OUTSIDE the batch (Python/API), then phone + code are templated into the batch JSON.

Integration with Existing Infrastructure

Proxy Pool

41 live proxies at C:\Users\User\live_proxies.txt. For gsd-browser:

gsd-browser mcp --proxy "$(head -1 C:\Users\User\live_proxies.txt)" --session reg-1

Session Isolation for Bulk

Each account gets its own session. Launch N sessions in parallel:

for i in $(seq 1 5); do
  proxy=$(sed -n "${i}p" C:\Users\User\live_proxies.txt)
  gsd-browser mcp --proxy "$proxy" --session "gmail-reg-$i" &
done

Vault for Credential Reuse

If using the same password for multiple accounts:

# One-time setup
gsd-browser vault save --profile gmail-default --url https://accounts.google.com --username "default-user" --password "Str0ngP@ss!2024"
# Set env var (must be set BEFORE daemon starts)
export GSD_BROWSER_VAULT_KEY="your-secret-key"

Recovery: Post-Registration Session Restore

After account creation, restore the session for account warming:

{
  "session": "gmail-warmup",
  "steps": [
    {"action": "restore_state", "name": "session-johnsmith7894"},
    {"action": "navigate", "url": "https://mail.google.com"},
    {"action": "wait_for", "condition": "text_visible", "value": "Welcome to your new inbox"},
    {"action": "screenshot", "name": "gmail-inbox-warmed"}
  ]
}

Pitfalls

  1. gsd-browser needs Chrome installed — browser_navigate fails with "daemon exited during startup" if no Chrome binary found. Set GSD_BROWSER_BROWSER_PATH or pass --browser-path.
  2. Vault key at launch time only — GSD_BROWSER_VAULT_KEY must be set BEFORE daemon starts. Cannot be set after.
  3. Google changes DOM frequently — Semantic intents (fill_form, act) survive better than raw selectors. If fill_form misses a field, fall back to act_instruction.
  4. fill_form keys match labels, not name attributes — "First name" matches the visible label, NOT name='firstName'.
  5. Session names are global — --session reg-1 stores state on disk. Clean up old sessions to avoid disk bloat.
  6. Batch stop_on_failure=true — If any step fails, the entire batch stops. For Gmail where certain steps may be optional (phone screen absent), use stop_on_failure=false or handle branching with condition: "any".
  7. Phone screen unpredictable — Google's phone screen shows randomly (IP-based, fingerprint-based). Always include the condition: "any" branch. Don't assume it will or won't appear.

When to use this vs Playwright

Scenario Use
API registration (aiqianshu, Stagewise) gsd-browser batch
Gmail signup (high anti-detection needed) gsd-browser batch (preferred)
Need full programmatic control (custom logic, loops) Playwright (Python)
Headless server environment (no GUI) Playwright with xvfb
User says "быстро", "batch", "gsd" gsd-browser
User says "свой скрипт", "python" Playwright flow