Browser Management
This guide covers launching, configuring, and managing Chrome instances.
Launching Chrome
Basic Launch
var browser = try cdp.Browser.launch(.{
.allocator = allocator,
.io = init.io,
});
defer browser.close();Headless Modes
Chrome offers multiple headless modes:
// New headless (Chrome 112+) - recommended
var browser = try cdp.Browser.launch(.{
.headless = .new,
.allocator = allocator,
.io = init.io,
});
// Old headless mode
var browser = try cdp.Browser.launch(.{
.headless = .old,
// ...
});
// GUI mode (visible browser)
var browser = try cdp.Browser.launch(.{
.headless = .off,
// ...
});| Mode | Description |
|---|---|
.new | Chrome 112+ headless, better compatibility |
.old | Legacy headless, faster but less accurate |
.off | Visible browser window |
Custom Chrome Path
var browser = try cdp.Browser.launch(.{
.executable_path = "/path/to/chrome",
.allocator = allocator,
.io = init.io,
});Window Size
var browser = try cdp.Browser.launch(.{
.window_size = .{
.width = 1920,
.height = 1080,
},
.allocator = allocator,
.io = init.io,
});User Data Directory
Persist browser data between sessions:
var browser = try cdp.Browser.launch(.{
.user_data_dir = "/path/to/profile",
.allocator = allocator,
.io = init.io,
});Debug Port
// Specific port
var browser = try cdp.Browser.launch(.{
.port = 9222,
.allocator = allocator,
.io = init.io,
});
// Random available port (default)
var browser = try cdp.Browser.launch(.{
.port = 0, // auto-assigned
.allocator = allocator,
.io = init.io,
});Security Options
var browser = try cdp.Browser.launch(.{
.ignore_certificate_errors = true, // Skip HTTPS errors
.no_sandbox = true, // Required in containers
.disable_gpu = true, // Recommended for headless
.allocator = allocator,
.io = init.io,
});Extra Arguments
Pass additional Chrome flags:
var browser = try cdp.Browser.launch(.{
.extra_args = &[_][]const u8{
"--proxy-server=localhost:8080",
"--disable-web-security",
"--lang=en-US",
},
.allocator = allocator,
.io = init.io,
});Connecting to Existing Chrome
Start Chrome with Debugging
# Windows
chrome.exe --remote-debugging-port=9222
# macOS
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222
# Linux
google-chrome --remote-debugging-port=9222Connect
var browser = try cdp.Browser.connect(
"ws://127.0.0.1:9222/devtools/browser/abc123",
allocator,
init.io,
);
defer browser.close();TIP
Get the WebSocket URL from http://127.0.0.1:9222/json/version
Chrome Inspect-Based Debugging (Chrome 136+)
Chrome 136+ supports debugging via chrome://inspect/#remote-debugging. This method exposes CDP over WebSocket without the standard HTTP endpoints (/json/version and /json/list return 404).
zchrome automatically handles this by falling back to a direct WebSocket connection when HTTP endpoints are unavailable:
# 1. Open chrome://inspect in your browser
# 2. Enable "Discover network targets" and configure the port
# 3. Connect with zchrome
zchrome connect --port 9222The CLI will:
- Try the standard
/json/versionendpoint - If that fails (404), attempt direct WebSocket connection to
ws://127.0.0.1:<port>/devtools/browser - Verify the connection by sending a CDP command
WARNING
Prompt Limitation: Inspect-based debugging shows an "Allow Remote Debugging" prompt on each connection. This is a Chrome security feature that cannot be bypassed.
For automation without prompts, use --remote-debugging-port instead:
chrome --remote-debugging-port=9222Browser Information
Version Info
var version = try browser.version();
defer version.deinit(allocator);
std.debug.print("Protocol: {s}\n", .{version.protocol_version});
std.debug.print("Product: {s}\n", .{version.product});
std.debug.print("Revision: {s}\n", .{version.revision});
std.debug.print("User Agent: {s}\n", .{version.user_agent});
std.debug.print("JS Version: {s}\n", .{version.js_version});WebSocket URL
const ws_url = browser.getWsUrl();
std.debug.print("WebSocket URL: {s}\n", .{ws_url});Page Management
Create New Page
var session = try browser.newPage();
defer session.detach() catch {};List All Pages
const pages = try browser.pages();
defer {
for (pages) |*p| {
p.deinit(allocator);
}
allocator.free(pages);
}
for (pages) |p| {
std.debug.print("{s}: {s}\n", .{p.target_id, p.title});
}Close Page
try browser.closePage(target_id);Cleanup
Always close the browser when done:
var browser = try cdp.Browser.launch(.{ ... });
defer browser.close(); // Sends Browser.close, closes connection, terminates processThe close() method:
- Sends
Browser.closeCDP command - Closes the WebSocket connection
- Terminates the Chrome process (if launched)
- Cleans up temp directories
Error Handling
var browser = cdp.Browser.launch(.{ ... }) catch |err| switch (err) {
error.ChromeNotFound => {
std.debug.print("Chrome not found. Install Chrome or specify path.\n", .{});
return;
},
error.LaunchFailed => {
std.debug.print("Failed to start Chrome process.\n", .{});
return;
},
error.StartupTimeout => {
std.debug.print("Chrome didn't start in time.\n", .{});
return;
},
else => return err,
};Chrome Auto-Discovery
zchrome searches these paths automatically:
Windows
C:\Program Files\Google\Chrome\Application\chrome.exeC:\Program Files (x86)\Google\Chrome\Application\chrome.exeC:\Program Files\Chromium\Application\chrome.exe
macOS
/Applications/Google Chrome.app/Contents/MacOS/Google Chrome/Applications/Chromium.app/Contents/MacOS/Chromium
Linux
/usr/bin/google-chrome/usr/bin/google-chrome-stable/usr/bin/chromium/usr/bin/chromium-browser/snap/bin/chromium