# gsd-browser Batch Registration Pattern > **Class:** bulk-account-registration > **Tool:** gsd-browser MCP (68 tools) > **Why:** One `browser_batch` call replaces 10+ sequential Playwright steps. Semantic intents survive DOM changes. ## Batch Structure Template ```json { "session": "reg-wave-1", "steps": [ {"action": "navigate", "url": "https://target.com/signup"}, {"action": "act", "intent": "accept_cookies"}, {"action": "fill_form", "values": { "Email": "user+alias@gmail.com", "Password": "SecurePass123!", "Username": "gen_user_001" }}, {"action": "act", "intent": "submit_form"}, {"action": "wait_for", "condition": "url_contains", "value": "verify"}, {"action": "screenshot", "name": "post-reg-state"}, {"action": "save_state", "name": "session-reg-001"} ], "stop_on_failure": true, "summary_only": false } ``` ## Registration Pipeline (gsd-browser version) ### 0. Pre-check ```bash # Verify Chrome/gsd-browser available gsd-browser mcp --session health-check <<< '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' ``` ### 1. Vault Setup (one-time) ```bash # Save credentials for reuse across reg sessions # Interactive: gsd-browser vault save --profile github --url https://github.com --username your-login # MCP: browser_vault_save(profile="target-service", url="https://target.com/login", username="user", password="pass") ``` Requires `GSD_BROWSER_VAULT_KEY` env var set at daemon launch time. ### 2. Batch Registration ``` browser_batch → navigate + fill_form + submit + wait + screenshot + save_state ``` ### 3. Poll for OTP (parallel) Run temp.coda.ink / IMAP polling in parallel with the browser session. Extract OTP, then: ``` browser_batch → navigate(vrfy) → fill_form(otp) → submit → wait(welcome) → save_state ``` ### 4. Post-Reg Session Save `browser_save_state(name="session-XXXX")` persists cookies + localStorage. Restore with `browser_restore_state(name="session-XXXX")` for instant login on next run. ## Session Isolation Use `--session ` flag (or `session` field in batch) for isolated browser instances: ``` --session reg-wave-1 # browser context 1 (cookies: A, B) --session reg-wave-2 # browser context 2 (cookies: C, D) ``` Each context has independent cookies, localStorage, cache. Like separate anonymous profiles. ## Key Tools for Registration | Tool | When | |------|------| | `browser_navigate` | Start of every flow | | `browser_act` (intent=`accept_cookies`) | First step on any new site | | `browser_act` (intent=`fill_email`) | When only email field needed | | `browser_fill_form` | Full form with 3+ fields | | `browser_act` (intent=`submit_form`) | After form fill | | `browser_act_instruction` | Complex UX (`"enter 'user@x.com' into email field"`) | | `browser_wait_for` (condition=`url_contains`,`selector_visible`,`text_visible`) | After submission | | `browser_assert` (checks=`url_contains`,`text_visible`) | Verify success | | `browser_save_state` / `browser_restore_state` | Session persistence | | `browser_vault_save` / `browser_vault_login` | Credential management | | `browser_screenshot` (name=...) | Evidence capture | | `browser_extract` (schema=...) | Post-reg data extraction | | `browser_save_pdf` | Full page evidence | | `browser_debug_bundle` | Failure diagnosis | ## Pitfalls - **gsd-browser daemon needs Chrome** — `browser_navigate` fails with "daemon exited during startup" if no Chrome binary found. Set `GSD_BROWSER_BROWSER_PATH` env var or pass `--browser-path`. - **save_state is per-session** — If you use `--session reg-1`, restore with same session name. Cross-session restore not supported. - **vault key at launch time** — `GSD_BROWSER_VAULT_KEY` must be set BEFORE daemon starts. Cannot be set after. - **batch stop_on_failure=true** — If any step fails, batch stops. Check `summary` field for which step failed and why. - **act_intent may miss on custom UX** — If `submit_form` intent doesn't find the button, fall back to `browser_act_instruction(instruction="click the Sign Up button")` or manual `browser_snapshot` → `browser_click_ref`. - **fill_form keys are label/placeholder text** — The values dict keys must match visible labels or placeholders, NOT `name`/`id` attributes. "Email" matches "Email" label, not `name="email"`. - **wait_for timeout default 10s** — Increase to 30s for slow sites: `timeout: 30000`. - **Vault profiles persist across sessions** — Use distinct profile names: `profile="target-reg-001"`.