VicroCode
Make Code Create Value
VicroCode is a lightweight online platform for publishing, running, sharing, and monetizing code projects. Launch HTML, Python, SQLite, AI agents, management tools, games, and more without server setup.
Please wait while VicroCode loads. You can also explore the AI programming guide
Loading...

AI MARKET GUIDE

Building a Python Browser Automation Agent with Full DOM Action Logging

A reproducible approach to browser automation: parse user intent, execute Playwright commands, and write every DOM action to SQLite for audit and replay.

What DomA actually does

DomA is a browser extension that turns natural language requests into browser actions. You tell it to organize tabs, download a video, or fill out a form, and it reads the page, figures out what to click, and does it. The execution model is straightforward: parse intent, translate to DOM operations, perform them, log them.

The logging piece matters. Every action—click, scroll, input—gets written somewhere. That audit trail becomes the foundation for replay, debugging, and compliance in contexts where you need to prove what happened.

The reproducible version on VicroCode

You can build a similar automation agent with the tools already available: run Python online for the orchestration layer, Playwright or Selenium for browser control, and a SQLite editor for persistent action logs.

The flow is direct. A Python script accepts a user command, translates it into a sequence of browser operations, executes them via Playwright, and writes each step to SQLite. The database becomes both the audit log and the replay source.

Playwright runs headless by default, but you can configure it to show the browser for manual verification. The action log includes timestamps, selectors, input values, and success status. If something breaks, you replay from the log. If compliance asks what happened, you export the table.

What gets logged

Every interaction that changes page state goes into the database:

  • Navigation events with full URL and timestamp
  • Click actions with the CSS selector and element text
  • Text input with field name and entered value
  • Scroll operations with coordinates
  • Screenshot captures at decision points
  • Error states and retry attempts

The schema is simple: action_id, timestamp, action_type, selector, value, status. You can extend it with session_id if running multiple tasks in parallel, or parent_action_id if you want to represent nested workflows.

Intent parsing without inventing capabilities

You need a way to turn "download the current page video" into Playwright commands. The simplest approach uses a small language model to map user intent to a predefined action template. You define templates for common operations—navigate, click, wait for element, extract attribute—and the model selects the right one and fills in parameters.

This constrains what the agent can do, which is actually useful. A fixed set of action primitives makes the system predictable and the logs readable. You avoid the problem of an LLM inventing operations that don't exist or hallucinating selectors.

If you need AI agent development with more adaptive behavior, you can route to Model Center APIs for intent understanding and keep the execution layer strictly template-based. The model decides what to do; the Python script decides how.

Replay from the log

The SQLite log is both archive and executable. You can rerun a sequence by reading the action_type and parameters from the database and feeding them back into Playwright. This works for regression testing, incident reconstruction, or user-reported issues where you need to see exactly what the agent did.

Replay is not the same as recording. A screen recording shows what happened visually; a structured log shows what the code executed and lets you re-execute it with modifications. You can skip steps, inject different data, or branch at any point.

Real-world friction

Browser automation breaks when pages change structure. A selector that worked yesterday returns null today. The fix is usually to add fallback selectors or switch to more stable attributes like data-testid or aria-label. The action log tells you which selectors failed most often, so you know where to add redundancy.

Anti-bot measures are another constraint. Many sites block headless browsers or rate-limit automated requests. Playwright's stealth mode helps, but it's not foolproof. For high-value workflows, you may need to run in headed mode and let the user solve CAPTCHAs manually, logging the pause and resumption.

Timing is harder than it looks. Elements load asynchronously, and waiting for a fixed duration is fragile. Playwright's wait_for_selector with a condition is more reliable, but you still need retry logic. The log should capture how many retries each action required, because excessive retries signal a page compatibility issue.

What this approach does not cover

This is not a general web scraping tool. It automates interactions on pages with known structure. If you need to scrape thousands of product listings or parse arbitrary HTML, a different architecture—probably one that pre-fetches and parses in bulk—makes more sense.

It also does not handle real-time decision trees where each action depends on unpredictable branching. If the workflow is "click button A, then depending on what loads, click either B or C, then depending on that result, navigate to one of five pages," you need more sophisticated state management than a linear action log provides.

Finally, this setup runs single-threaded. If you need to automate 50 tasks in parallel, you'll need a task queue and worker pool, which adds complexity beyond what the basic Python-and-SQLite stack handles cleanly.

When to use this pattern

This architecture fits when:

  • You need an audit trail for compliance or debugging
  • The workflows are repetitive but not identical (same steps, different data)
  • You want to iterate on automation logic without losing historical context
  • Replay matters—either for testing or for reproducing user-reported failures
  • You're prototyping an automation agent and need to understand how often each operation type fails

It doesn't fit when you need distributed execution, real-time branching, or scale beyond a few dozen daily tasks. For those, you're looking at a message queue, containerized workers, and a more opinionated orchestration layer.

Build cost and iteration speed

The base implementation is under 300 lines of Python: intent parser, Playwright wrapper, SQLite writer, and a CLI or simple web frontend. You can get a working prototype in an afternoon. The iteration cost is low because the action log gives you immediate feedback on what broke and where.

Adding new action types means defining a new template and extending the database schema. Testing a change means running the script against a test page and checking the log. You don't need a staging environment or deployment pipeline; the whole thing runs locally or in a single VicroCode project.

The trade-off you're actually making

You're trading flexibility for transparency. A fully autonomous agent can handle arbitrary web tasks, but you lose visibility into what it did and why. This approach locks you into predefined operations, but every decision is logged and reproducible.

For most automation work—form filling, data extraction, workflow testing—that trade-off is correct. The agent does less, but you understand it completely.