How the Playwright Browser Probe Works Across Chrome, Edge, and Chromium Without Node.js
The patent-disclosure-skill repository provides a pure-Python Playwright probe that auto-detects and launches system Chrome, system Edge, or bundled Chromium using only playwright.sync_api—no Node.js runtime required.
This article examines the implementation in handsomestWei/patent-disclosure-skill, specifically how tools/shared/browser.py implements a self-contained browser discovery mechanism. The probe eliminates the traditional Node.js dependency by leveraging Playwright's Python bindings and embedded driver binaries, making it ideal for lightweight Python environments.
Environment-Driven Configuration
The probe respects two environment variables that control its behavior without code changes.
PLAYWRIGHT_HEADED — Display Mode Control
The headed() function parses this flag to determine whether browsers launch in headed or headless mode.
import os
def headed() -> bool:
return os.environ.get("PLAYWRIGHT_HEADED", "").lower() in ("1", "true", "yes", "on")
Source: tools/shared/browser.py, lines 35-39
PATENT_BROWSER_CHANNEL — Force a Specific Browser
The _forced_channel() function reads this optional override, allowing users to bypass auto-detection entirely.
def _forced_channel() -> Optional[str]:
ch = os.environ.get("PATENT_BROWSER_CHANNEL", "").strip().lower()
if ch in ("chrome", "msedge", "chromium"):
return ch
return None
Source: tools/shared/browser.py, lines 61-64
Auto-Detection Priority Order
When no channel is forced, the probe follows a fixed fallback sequence defined in _AUTO_CHANNELS:
_AUTO_CHANNELS: Tuple[str, ...] = ("chrome", "msedge") # None = bundled Chromium
This tuple drives the loop in launch_chromium(), which attempts each candidate in order:
- "chrome" — System-installed Google Chrome
- "msedge" — System-installed Microsoft Edge
None— Playwright's bundled Chromium (downloaded viaplaywright install chromium)
Source: tools/shared/browser.py, lines 31-34
Installation Verification Before Launch
The probe validates that Playwright's Python package is importable before attempting any browser launches. The playwright_installed() function guards against missing dependencies with a clean boolean check.
def playwright_installed() -> bool:
try:
import playwright
return True
except ImportError:
return False
Source: tools/shared/browser.py, lines 43-49
Launch Mechanics: How Node.js Is Bypassed
The core launch logic resides in launch_chromium(). For each candidate channel, the function constructs arguments from LAUNCH_ARGS and calls playwright.chromium.launch() with the channel parameter when applicable.
Launch Arguments Configuration
LAUNCH_ARGS = [
"--disable-blink-features=AutomationControlled",
"--no-sandbox", # Required for Docker/root environments
"--disable-setuid-sandbox",
]
These flags disable automation detection (reducing bot-blocking) and relax sandboxing for portability.
The Launch Loop
def launch_chromium(channel: Optional[str] = None):
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(
headless=not headed(),
args=LAUNCH_ARGS,
channel=channel, # None → bundled Chromium; "chrome"/"msedge" → system install
)
# ... success handling
The channel parameter is the critical mechanism: when set to "chrome" or "msedge", Playwright locates and uses the system browser executable; when None, it falls back to its own Chromium binary.
Source: tools/shared/browser.py, lines 94-106
Success and Failure Handling
Success Path
On first successful launch, the browser closes immediately and returns:
browser.close()
return browser, label # label ∈ {"chrome", "msedge", "chromium"}
Source: tools/shared/browser.py, lines 99-104
Failure Path with Installation Hints
If all candidates fail, install_chromium_hint() generates platform-specific guidance:
def install_chromium_hint() -> str:
return "Playwright Chromium not found. Run: playwright install chromium"
The probe raises RuntimeError with this hint, directing users to resolve the issue without manual troubleshooting.
Source: tools/shared/browser.py, lines 108-110 and install_chromium_hint() implementation
JSON Report Structure
The probe_launch() wrapper returns a machine-parseable dictionary suitable for CI/CD pipelines and health checks:
| Key | Type | Description |
|---|---|---|
playwright |
bool |
Whether the Python package is importable |
channel |
str | None |
Which browser channel was detected/specified |
ok |
bool |
Whether launch succeeded |
error |
str | None |
Exception message if failed |
hint |
str | None |
Installation or remediation guidance |
Source: tools/shared/browser.py, lines 124-140
Command-Line and Programmatic Usage
CLI Probe Mode
# Quick system check — exits 0 on success
python -m tools.shared.browser --probe
stderr output (human-readable):
PROBE: ok=true channel=chrome error=
stdout output (JSON):
{
"playwright": true,
"channel": "chrome",
"ok": true,
"error": null,
"hint": null
}
Source: tools/shared/browser.py, lines 168-176 (main() function)
Programmatic Integration
from tools.shared.browser import probe_launch
result = probe_launch()
if result["ok"]:
print(f"Ready: {result['channel']}")
else:
print(f"Failed: {result['error']}")
print(f"Fix: {result['hint']}")
Force Specific Channel
export PATENT_BROWSER_CHANNEL=msedge
python -m tools.shared.browser --probe
Valid values: chrome, msedge, chromium
Why No Node.js Is Required
Traditional Playwright setups require Node.js for the driver process. This probe avoids that dependency through three design choices:
- Python-native bindings — Uses
playwright.sync_apiexclusively - Embedded driver binaries — The
playwrightPyPI package includes pre-compiled browser drivers - Direct executable discovery — System Chrome/Edge paths are resolved via Playwright's built-in locators, not Node.js path resolution
The bundled Chromium fallback works because playwright install chromium downloads a standalone browser build that communicates via the Python binding's WebSocket protocol—no separate Node.js runtime orchestrates the process.
Summary
- The probe in
tools/shared/browser.pyimplements pure-Python browser discovery using Playwright's sync API - Auto-detection order: system Chrome → system Edge → bundled Chromium, controlled by
_AUTO_CHANNELS - Environment variables
PLAYWRIGHT_HEADEDandPATENT_BROWSER_CHANNELconfigure behavior without code changes - Launch arguments in
LAUNCH_ARGSdisable automation flags and sandboxing for reliability - Node.js elimination relies on Python bindings plus embedded driver binaries, not external runtime
- JSON output from
probe_launch()enables programmatic health checks and CI integration
Frequently Asked Questions
Does this probe work in Docker containers without a display?
Yes. By default, headed() returns False unless PLAYWRIGHT_HEADED is explicitly set, so browsers launch in headless mode. The --no-sandbox flag in LAUNCH_ARGS handles root-privileged containers where standard Chromium sandboxing fails.
What happens if I have both Chrome and Edge installed?
The probe selects Chrome first based on _AUTO_CHANNELS = ("chrome", "msedge"). To override, set PATENT_BROWSER_CHANNEL=msedge before running.
How do I install the bundled Chromium if no system browser exists?
Run playwright install chromium in your environment. The probe's install_chromium_hint() generates this exact command in its error output when detection fails.
Can I extend this to support Firefox or WebKit?
The current implementation is Chromium-specific. Playwright's Python bindings do support Firefox and WebKit via playwright.firefox and playwright.webkit, but browser.py would require modifications to _AUTO_CHANNELS and launch_chromium() to iterate over additional browser types.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →