BrowserGym Core

Gymnasium environment for building and evaluating LLM-driven web agents in a real Chromium browser.

Framework
PyPI
v0.14.3
1,334stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
57/100Fair
Development Activity32
Maintenance48
Community60
Maturity48
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
71/100Good
Architecture80
Code Quality68
Innovation62
Learning Curve75

browsergym-core is the foundational package of BrowserGym, ServiceNow Research’s framework for training and evaluating web agents. It wraps Playwright-driven Chromium browsing in a Gymnasium-compatible environment (BrowserEnv), exposing page state as a marked DOM snapshot, merged accessibility tree, and screenshot, and accepting either a configurable high-level action set (click, fill, scroll, tab management, drag-and-drop) or raw Python code that agents can address by stable element bid.

Installed standalone, browsergym-core only registers the openended task — an agent-driven browsing session that starts at a given URL and optionally exposes a chat interface. The benchmark-specific packages in the same monorepo (browsergym-miniwob, browsergym-webarena, browsergym-workarena, browsergym-visualwebarena, browsergym-assistantbench) build on top of it by subclassing AbstractBrowserTask and calling register_task(), so every benchmark shares one observation format, one action space, and one Playwright browser-lifecycle implementation.

What You Get

  • A Gymnasium-compatible BrowserEnv that manages a headless (or headed) Playwright Chromium browser end-to-end: launch, context, page, and teardown.
  • Structured per-step observations: marked DOM snapshot, merged accessibility tree with element bids, screenshot, focused element, and chat history.
  • A high-level action set (click, fill, scroll, hover, drag-and-drop, tab/window management, keyboard input) plus a raw Python-code action escape hatch.
  • The openended task out of the box — point an agent at any starting URL with an optional interactive chat loop.
  • An AbstractBrowserTask base class and register_task() helper for turning new benchmarks into first-class Gym environments.
  • A built-in MCP server (browsergym.utils.mcp_server) for exposing the browser environment to MCP-speaking clients.

Common Use Cases

  • Training or evaluating an LLM-based web agent against a live, real browser instead of a scripted mock.
  • Building a new benchmark by subclassing AbstractBrowserTask and reusing the observation/action machinery.
  • Running an interactive, chat-driven open-ended browsing session to debug an agent’s action policy step by step.
  • Powering downstream BrowserGym packages (MiniWoB++, WebArena, VisualWebArena, WorkArena, AssistantBench) that only add task definitions on top of this core runtime.

Under The Hood

Architecture BrowserEnv (env.py, ~690 lines) is the central Gymnasium gym.Env subclass, orchestrating a global sync_playwright() instance (browsergym/core/init.py) into a browser to context to page pipeline; each reset() launches the task via a task_entrypoint (an AbstractBrowserTask subclass frozen with kwargs by register_task() in registration.py) which calls setup(page) to navigate and return a goal, and each step() executes an agent’s action, either through the configurable HighLevelActionSet in action/highlevel.py, mapped to Python via execute_python_code in action/base.py and action/python.py, or a raw callable, before running the observation pipeline (_pre_extract/_post_extract, extract_merged_axtree, extract_dom_snapshot, extract_screenshot in observation.py) and delegating pass/fail scoring back to the task’s validate(). Task definition, environment orchestration, action parsing, and observation extraction sit in clearly separated modules behind a narrow AbstractBrowserTask contract that every sibling benchmark package in the monorepo depends on without touching env.py directly.

Tech Stack browsergym-core targets Python 3.9+ and is built with hatchling plus hatch-requirements-txt (pyproject.toml), pinning playwright==1.44 for browser automation, gymnasium>=0.27 for the RL-style env interface, numpy for array-typed observation spaces (spaces.py’s AnyBox/Anything/Float/Unicode), beautifulsoup4 and lxml for auxiliary DOM parsing, Pillow for screenshot handling, pyparsing for the action-set docstring parser (action/parsers.py), and mcp[cli] to expose a Model Context Protocol server (utils/mcp_server.py). The package ships no web framework of its own — its “server” is a live headless-Chromium instance controlled directly via Playwright’s sync API — and is versioned dynamically via hatch’s version hook pointing at src/browsergym/core/init.py.

Code Quality Tests live under tests/core/ (test_task.py, test_observation.py, test_actions_python.py, test_actions_highlevel.py, test_gym_envs.py, test_registration.py) and run in CI via pytest against a real Playwright-launched Chromium, alongside a dedicated black-formatting check job, signalling a genuine testing culture built on real-browser integration tests rather than pure mocks. Core modules use type hints and docstrings throughout (env.py, task.py, observation.py), dataclasses in action/highlevel.py, and custom exceptions such as MarkingError in observation.py rather than swallowing errors silently. No mypy/pyright configuration was found, so type checking stays documentation-level rather than enforced, and there is no dedicated linter beyond black formatting.

API Design The public surface is intentionally narrow: implement AbstractBrowserTask’s setup/validate (and optional cheat/teardown), call register_task(), and the task becomes a standard gym.make()-able environment with no further wiring. The HighLevelActionSet exposes browser actions as plain, docstring-annotated Python functions an agent can call directly or express as parsed text, which keeps the action interface consistent across every benchmark package while still allowing raw Python/Playwright code as an escape hatch for edge cases the high-level API doesn’t cover.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search