Lightpanda Fetch Mode vs Serve Mode: Understanding the Difference

Fetch mode performs a single-shot page retrieval with optional content dumping to stdout or file, while serve mode launches a persistent Chrome DevTools Protocol (CDP) server that accepts remote WebSocket connections for interactive browser automation.

Lightpanda is a lightweight, headless browser written in Zig designed for high-performance web automation. The src/Config.zig file defines distinct run modes that determine how the browser initializes and executes, with fetch and serve representing two fundamentally different architectural approaches. Understanding these modes ensures you select the appropriate method for one-off data extraction versus long-running automation workflows.

Configuration Architecture

The behavioral differences between fetch and serve mode originate in their respective configuration structures within src/Config.zig.

Fetch Mode Configuration

Config.Fetch (defined at lines 220–227) contains the target URL, dump format options (HTML, markdown, semantic tree), and a shared Common configuration block. This structure supports the single-execution pattern where the process terminates immediately after retrieving and optionally serializing the document.

Serve Mode Configuration

Config.Serve (defined at lines 199–206) specifies network parameters including host, port, timeout settings, and connection limits alongside the Common block. Unlike fetch mode, this configuration supports persistent socket listening and multi-session management required for remote protocol support.

Operational Implementation

The entry points in src/main.zig (around lines 84–105) dispatch to entirely different execution paths based on the selected mode.

Fetch Mode: Single-Shot Execution

When invoked with case .fetch, the application constructs a FetchOpts structure and calls lp.fetch(app, url, fetch_opts). The core implementation in src/lightpanda.zig (lines 52–63 and 104–136) performs the following sequence:

  1. Instantiates a Browser object
  2. Navigates to the specified URL
  3. Waits for page stabilization
  4. Serializes the document or semantic tree if dump mode is enabled
  5. Writes output to the configured writer (stdout or file)
  6. Terminates the process

This mode is ideal for static-site generation, one-off page extraction, or pipeline debugging where no ongoing interaction is required.

Serve Mode: Persistent CDP Server

When invoked with case .serve, the main.zig branch (lines 84–102) initializes a lp.Server instance that implements the Chrome DevTools Protocol. The implementation in src/Server.zig establishes a listening socket and enters a network loop that:

  • Accepts incoming WebSocket connections
  • Dispatches CDP messages to underlying Browser sessions
  • Maintains process longevity until interrupted (SIGTERM, Ctrl-C)

This architecture enables external tools like Puppeteer, Playwright, or chromedp to connect via ws://host:port and control multiple pages programmatically across extended sessions.

Practical Usage Examples

Running Fetch Mode

Execute a one-time page capture with content dumping:


# Dump rendered HTML to file

./lightpanda fetch --dump html https://example.com > page.html

# Extract markdown representation

./lightpanda fetch --dump markdown https://example.com > page.md

# Output JSON-encoded semantic tree to stdout

./lightpanda fetch --dump semantic_tree https://example.com

Running Serve Mode

Start the CDP server for remote automation:


# Default binding (127.0.0.1:9222)

./lightpanda serve

# Custom network interface and port

./lightpanda serve --host 0.0.0.0 --port 8080

Connect programmatically using Puppeteer:

const puppeteer = require('puppeteer-core');
const browser = await puppeteer.connect({
  browserWSEndpoint: 'ws://127.0.0.1:9222',
});
const page = await browser.newPage();
await page.goto('https://example.com');

Summary

  • Fetch mode uses Config.Fetch to execute a single navigation, dump content via lp.fetch() in src/lightpanda.zig, and exit immediately.
  • Serve mode uses Config.Serve to instantiate a persistent CDP server via src/Server.zig, maintaining WebSocket connections for remote automation.
  • Fetch mode directs output to files or stdout, while serve mode communicates exclusively through CDP protocol messages.
  • Fetch mode terminates after page retrieval; serve mode runs indefinitely until signal interruption.

Frequently Asked Questions

When should I use fetch mode instead of serve mode?

Use fetch mode for batch processing, static-site generation, or CI/CD pipelines where you need to extract content from specific URLs without maintaining a persistent browser instance. Use serve mode when integrating with existing automation frameworks like Puppeteer or Playwright that require interactive session management across multiple page navigations.

Can fetch mode handle JavaScript-heavy applications?

Yes, the lp.fetch() implementation in src/lightpanda.zig instantiates a full Browser instance and waits for page stabilization before dumping, ensuring JavaScript execution completes. However, unlike serve mode, you cannot interact with the page after initial load or perform multi-step workflows.

What network protocols does serve mode support?

Serve mode implements the Chrome DevTools Protocol (CDP) over WebSocket connections, as defined in src/Server.zig. This allows compatibility with any tool supporting CDP, including Puppeteer, Playwright, and Selenium ChromeDriver, without requiring proprietary extensions.

How do I limit concurrent connections in serve mode?

The Config.Serve structure in src/Config.zig (lines 199–206) includes connection limit parameters that control the maximum number of simultaneous WebSocket sessions. Configure these via command-line flags when starting the server to prevent resource exhaustion during high-concurrency automation scenarios.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →