Skip to content

Lightpanda CDP Support: Full Puppeteer and Playwright Compatibility

The Problem: Browser Automation Compatibility

I had a bunch of Puppeteer scripts for web scraping and testing, and I wanted to switch to Lightpanda for its speed and lightweight nature. But my first question was: will my existing automation scripts even work?

When you’ve built automation workflows with Puppeteer or Playwright, switching browsers feels risky. These tools rely on CDP (Chrome DevTools Protocol) to communicate with the browser. If a new browser doesn’t speak the same protocol, your scripts break.

I needed to know: does Lightpanda support the CDP domains my scripts use?

What is CDP Anyway?

CDP is the wire protocol that lets tools like Puppeteer, Playwright, and Chrome DevTools control a browser. When you write:

example-puppeteer.js
await page.goto('https://example.com');
await page.screenshot({ path: 'screenshot.png' });

Behind the scenes, Puppeteer sends CDP commands like Page.navigate and Page.captureScreenshot. The browser responds with results, and your script continues.

If a browser implements these CDP domains, your automation code should work without modification.

Lightpanda’s CDP Implementation

Looking at Lightpanda’s source code in src/cdp/cdp.zig, I found 17 CDP domains implemented:

DomainWhat It Does
PageNavigation, screenshots, lifecycle events
DOMQuery selectors, node inspection
RuntimeJavaScript execution, console API
NetworkRequest/response handling, headers
TargetBrowser contexts, page creation
BrowserVersion info, browser-level screenshots
StorageCookies, localStorage, sessionStorage
SecurityCertificate handling
EmulationDevice emulation
InspectorDebugging support
FetchRequest interception and modification
InputMouse, keyboard, touch events
LogConsole messages
PerformanceMetrics collection
AccessibilityAccessibility tree
CSSStylesheet manipulation
LPLightpanda custom extensions

Testing Puppeteer Compatibility

I tried running a simple Puppeteer script against Lightpanda:

test-puppeteer.mjs
import puppeteer from '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');
const title = await page.title();
console.log('Page title:', title);
await page.screenshot({ path: 'screenshot.png' });
await browser.close();

It worked. The Page, Target, and Browser domains handled the navigation, page creation, and screenshot correctly.

Where I Hit Snags

Not everything worked out of the box. Here’s what I discovered:

Playwright’s Dynamic Detection: Playwright dynamically detects browser features, and some of its assumptions about Chrome don’t match Lightpanda yet. Basic scripts work, but features that rely on specific Chrome internals might fail.

Advanced Network Features: While basic request interception works through the Fetch domain, some advanced network manipulation features I use in other projects need more work.

Performance Metrics: The Performance domain is implemented, but not all metrics available in Chrome are exposed yet.

The WebSocket Connection

Lightpanda exposes CDP through a WebSocket server. This is the standard approach, matching how Chrome and other CDP-compatible browsers work:

Start Lightpanda with debugging port
./lightpanda serve --host 127.0.0.1 --port 9222
WebSocket endpoint
# WebSocket endpoint available at:
ws://127.0.0.1:9222

Your Puppeteer or Playwright scripts connect to this WebSocket endpoint the same way they connect to Chrome’s.

How Domains Work Together

Let me show you what happens when you run a simple script:

automation-flow.mjs
// When you call:
await page.evaluate(() => document.querySelector('h1').textContent);
// Lightpanda processes this through multiple domains:
// 1. Runtime domain - executes the JavaScript
// 2. DOM domain - queries the selector
// 3. Page domain - manages the execution context

Each CDP command triggers handlers in the relevant domain. The domains coordinate through Lightpanda’s internal message routing.

Browser Context Support

One feature I needed was browser contexts for isolated sessions. Lightpanda handles this through the Target domain:

browser-contexts.mjs
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({
browserWSEndpoint: "ws://127.0.0.1:9222",
});
// Create isolated context
const context = await browser.createIncognitoBrowserContext();
const page = await context.newPage();
// This session has its own cookies and storage
await page.goto('https://example.com');

The Storage domain manages cookies and localStorage separately for each context.

What’s Not Implemented

For transparency, here’s what you might find missing:

  • Some advanced CSS domain methods
  • Complete coverage of all Network event types
  • Some Emulation features for mobile testing

The team is actively working on these. Check the GitHub issues for current status.

When to Use Lightpanda vs Chrome

Lightpanda shines for:

  • CI/CD pipelines: Smaller container images, faster startup
  • Serverless functions: Lower memory footprint
  • High-volume scraping: Less overhead per instance

Stick with Chrome for:

  • Complex JavaScript applications with newer APIs
  • Sites that specifically target Chrome
  • Features requiring full CDP coverage

Summary

In this post, I showed how Lightpanda implements 17 CDP domains for Puppeteer and Playwright compatibility. The key points are:

  • 17 CDP domains cover core automation needs
  • Puppeteer scripts work without modification in most cases
  • Playwright support has caveats due to dynamic feature detection
  • WebSocket endpoint matches Chrome’s standard CDP interface
  • Browser contexts supported for isolated sessions

If you’re considering the switch, start by testing your existing scripts against Lightpanda’s CDP endpoint. Most likely, they’ll just work.

Final Words + More Resources

My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me

Here are also the most important links from this article along with some further resources that will help you in this scope:

Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!

Comments