---
name: Form Filling
slug: form-filling
category: Automation
description: Form Filling automates web forms, logins, registrations, checkouts, and multi-step wizards with browser code execution. Use it when you need to enter data, submit a form, or reuse an authenticated session.
github: "https://github.com/billy-enrizky/openbrowser-ai/tree/main/plugin/skills/form-filling"
language: Python
stars: 241
forks: 21
install: "npx degit https://github.com/billy-enrizky/openbrowser-ai/tree/main/plugin/skills/form-filling ~/.claude/skills/form-filling"
installs_to: ~/.claude/skills/form-filling
source_path: plugin/skills/form-filling/SKILL.md
collection_size: 7
category_size: 1648
collection_url: "https://dirskills.com/collections/billy-enrizky/openbrowser-ai"
added: 2026-09-02T05:21:55.116Z
last_synced: 2026-09-02T05:21:55.116Z
canonical_url: "https://dirskills.com/skills/form-filling"
---

# Form Filling

Form Filling automates web forms, logins, registrations, checkouts, and multi-step wizards with browser code execution. Use it when you need to enter data, submit a form, or reuse an authenticated session.

**Install:**

```bash
npx degit https://github.com/billy-enrizky/openbrowser-ai/tree/main/plugin/skills/form-filling ~/.claude/skills/form-filling
```

## README

# Form Filling

Automate filling web forms including login, registration, checkout, and multi-step form wizards using Python code execution.

All code runs via `openbrowser-ai -c`. The daemon starts automatically and persists variables across calls. All browser functions are async -- use `await`.

The CLI daemon also persists cookies and login state in `~/.config/openbrowser/profiles/daemon/storage_state.json`, so authenticated sessions can be reused across later runs.

## Setup

Before running, verify openbrowser-ai is installed:

```bash
openbrowser-ai --help
```

If not found, install:

```bash
# macOS/Linux
curl -fsSL https://raw.githubusercontent.com/billy-enrizky/openbrowser-ai/main/install.sh | sh

# Windows (PowerShell)
irm https://raw.githubusercontent.com/billy-enrizky/openbrowser-ai/main/install.ps1 | iex
```

## Workflow

### Step 1 -- Navigate to the form page

```bash
openbrowser-ai -c - <<'EOF'
await navigate("https://example.com/login")
state = await browser.get_browser_state_summary()
print(f"Page: {state.title} ({state.url})")
print(f"Interactive elements: {len(state.dom_state.selector_map)}")
EOF
```

### Step 2 -- Discover form fields

```bash
openbrowser-ai -c - <<'EOF'
# List all interactive elements with their indices
state = await browser.get_browser_state_summary()
for index, element in state.dom_state.selector_map.items():
    tag = element.tag_name
    text = element.get_all_children_text(max_depth=2)[:60]
    placeholder = element.attributes.get("placeholder", "")
    input_type = element.attributes.get("type", "")
    name = element.attributes.get("name", "")
    print(f"[{index}] <{tag}> type={input_type} name={name} placeholder=\"{placeholder}\" text=\"{text}\"")
EOF
```

### Step 3 -- Fill text inputs

```bash
openbrowser-ai -c - <<'EOF'
# Fill fields using their indices from Step 2
await input_text(index=5, text="user@example.com")
await input_text(index=7, text="secure-password")
EOF
```

For fields that need clearing first:

```bash
openbrowser-ai -c - <<'EOF'
await click(index=5)
await evaluate("document.activeElement.select()")
await input_text(index=5, text="new-value")
EOF
```

### Step 4 -- Handle dropdowns

Standard HTML select elements:

```bash
openbrowser-ai -c - <<'EOF'
await select_dropdown(index=12, text="United States")
EOF
```

To see available options first:

```bash
openbrowser-ai -c - <<'EOF'
options = await dropdown_options(index=12)
print(options)
EOF
```

Custom dropdown components:

```bash
openbrowser-ai -c - <<'EOF'
await evaluate("""
(function(){
  const select = document.querySelector("select#country");
  select.value = "US";
  select.dispatchEvent(new Event("change", { bubbles: true }));
})()
""")
EOF
```

### Step 5 -- Handle checkboxes and radio buttons

```bash
openbrowser-ai -c - <<'EOF'
await click(index=15)  # Click checkbox/radio

# Verify state
checked = await evaluate("""document.querySelector("input[name=agree]").checked""")
print(f"Checkbox checked: {checked}")
EOF
```

### Step 6 -- Submit the form

```bash
openbrowser-ai -c - <<'EOF'
await click(index=20)  # Click submit button
await wait(2)

# Verify submission
state = await browser.get_browser_state_summary()
print(f"After submit: {state.url}")
EOF
```

Or submit via JavaScript:

```bash
openbrowser-ai -c - <<'EOF'
await evaluate("document.querySelector(\"form\").submit()")
EOF
```

### Step 7 -- Verify submission result

```bash
openbrowser-ai -c - <<'EOF'
# Check for success/error messages
result = await evaluate("""
(function(){
  const success = document.querySelector(".success, .alert-success, [role=\"alert\"]");
  const error = document.querySelector(".error, .alert-danger, .validation-error");
  return {
    success: success?.textContent?.trim(),
    error: error?.textContent?.trim(),
    url: window.location.href
  };
})()
""")
print(result)
EOF
```

### Step 8 -- Handle multi-step forms

```bash
openbrowser-ai -c - <<'EOF'
for step in range(1, 5):
    # Discover fields for current step
    state = await browser.get_browser_state_summary()
    print(f"Step {step}: {len(state.dom_state.selector_map)} elements")

    # Fill fields (indices vary per step)
    # ... fill fields here ...

    # Click Next/Continue
    # Find the next button
    for idx, el in state.dom_state.selector_map.items():
        text = el.get_all_children_text(max_depth=1).lower()
        if "next" in text or "continue" in text:
            await click(index=idx)
            await wait(2)
            break
EOF
```

## Tips

- Code is piped via stdin using heredoc (`-c - <<'EOF'`), so all Python syntax works without shell escaping issues.
- Always discover fields with `browser.get_browser_state_summary()` before typing -- do not guess element indices.
- For sensitive data (passwords, tokens), confirm with the user before entering values.
- Use `evaluate()` to bypass custom components that do not respond to standard click/type.
- Variables persist between `-c` calls while the daemon is running, so you can store field indices in one call and use them in the next.
- Check for CAPTCHA or bot detection; notify the user if manual intervention is needed.

## Cleanup

This step is **mandatory**. Run it after the form submission finishes, whether the submit succeeded or the form rejected the input. Without it, the daemon keeps Chrome running until its 10-minute idle timeout, leaving a stale browser process, a locked profile, and (on macOS/Linux desktop) a visible window with the form still on screen.

Stop the daemon, then verify it is gone:

```bash
openbrowser-ai daemon stop
openbrowser-ai daemon status
```

`daemon stop` closes every tab, exits Chrome, flushes saved cookies/login state to the profile (so the next run reuses the login), and shuts down the daemon process. `daemon status` should report the daemon is not running. If it still reports running, the daemon is wedged, force-kill it:

```bash
pkill -f 'openbrowser.*daemon' || true
```

Form runs can fail mid-workflow (validation error, CAPTCHA, network drop). Guarantee cleanup with a shell trap so a half-filled form never leaks a browser:

```bash
trap 'openbrowser-ai daemon stop >/dev/null 2>&1 || true' EXIT
# ... openbrowser-ai -c calls here ...
```

Do not rely on the idle timeout. Do not call `done()` as a substitute, `done()` only marks the task complete inside the agent loop, it does not close the browser.
