Getting Started with WebBrowserBot
In This Guide
Requirements
WebBrowserBot is a Python project. You need:
- Python 3.9 or later
- The
playwrightpackage with its Chromium browser installed - The
playwright-stealthpackage for anti-detection patches - The
aiohttppackage, used by the viewer server for HTTP and WebSocket
It runs on Linux, macOS, and Windows. A server without a display works fine, the browser runs headless by default and the live viewer streams frames to your own browser instead.
Installation
Install the Python dependencies, then let Playwright download its browser build:
pip install playwright playwright-stealth aiohttp
playwright install chromium
On a fresh Linux server, Playwright can also install the system libraries the browser needs:
playwright install --with-deps chromium
Then place the WebBrowserBot files in a directory of your choice. The tool keeps everything it creates next to its own files: profiles in profiles/, proxy providers in providers/, and screenshots in sessions/screenshots/.
The Three Run Modes
There are three ways to run the bot, all speaking the same command protocol:
- Viewer server (recommended).
python3 viewer_server.pystarts one process that owns all sessions, accepts automation commands on a localhost socket (port 8771), and serves the live viewer UI (port 8770). Sessions opened here are visible in the UI, where a human can watch or take control. - Standalone socket.
python3 bot_async.py --port 8771runs just the command socket with no UI. - Stdin mode.
python3 bot_async.pyreads one JSON command per line from stdin and writes one JSON response per line to stdout, which is handy for piping from another process.
Use the viewer server whenever the UI matters. The command vocabulary and response shape are identical in all three modes, so callers never change.
Configuration
The viewer server reads an optional config.json next to it:
{
"password": "choose-your-own-password",
"http_port": 8770,
"cmd_port": 8771,
"screenshot_retention_days": 7
}
passwordprotects the viewer UI. Always set your own. The environment variableVIEWER_PASSWORDoverrides it.http_portandcmd_portmove the two listeners, withVIEWER_HTTP_PORTandVIEWER_CMD_PORTas environment overrides.screenshot_retention_dayscontrols how long saved screenshots are kept.
Both ports bind to 127.0.0.1 only. Nothing is exposed to the network until you deliberately put a TLS reverse proxy in front of the viewer, which is covered in the live viewer guide.
Your First Session
With the viewer server running, connect to the command socket at 127.0.0.1:8771 and send one JSON object per line. Each request gets exactly one JSON response line back, always in the same envelope:
{"success": bool, "session_id": str|null, "data": object|null, "error": str|null}
Open a session under a profile (the profile is created on first use), load a page, and read its text:
-> {"command": "new_session", "profile": "work"}
<- {"success": true, "session_id": "a1b2c3d4", "data": {"profile": "work", "provider": null}, "error": null}
-> {"command": "goto", "session_id": "a1b2c3d4", "url": "https://example.com"}
<- {"success": true, "session_id": "a1b2c3d4", "data": {"title": "Example Domain", "url": "https://example.com/", "html": "..."}, "error": null}
-> {"command": "text", "session_id": "a1b2c3d4"}
<- {"success": true, "session_id": "a1b2c3d4", "data": {"title": "Example Domain", "url": "https://example.com/", "text": "Example Domain ..."}, "error": null}
-> {"command": "close_session", "session_id": "a1b2c3d4"}
<- {"success": true, "session_id": "a1b2c3d4", "data": {"closed": true}, "error": null}
A few rules that apply to everything you do from here:
- Every per-session command needs the
session_idreturned bynew_session. - Omit
providerto run without a proxy, which is the default. Pass"provider": "name"to use a proxy provider file, covered in Profiles and Proxies. - While your session is open, it is visible in the viewer UI, and a human can take control of it at any time. Your code should expect the
paused_for_takeoverrefusal described in the live viewer guide.
From Python, the whole exchange is a few lines:
import json, socket
def cmd(payload):
with socket.create_connection(("127.0.0.1", 8771)) as s:
s.sendall((json.dumps(payload) + "\n").encode())
return json.loads(s.makefile().readline())
resp = cmd({"command": "new_session", "profile": "work"})
sid = resp["session_id"]
cmd({"command": "goto", "session_id": sid, "url": "https://example.com"})
print(cmd({"command": "text", "session_id": sid})["data"]["text"])
cmd({"command": "close_session", "session_id": sid})
Next Steps
Browse the full command reference for everything the bot can do, set up the live viewer to watch your sessions, and read Profiles and Proxies to understand how fingerprints and proxy rotation work.