How do I get started with Lightpanda locally and expose a CDP server for my existing Playwright/Puppeteer scripts?
Headless Browser Infrastructure

How do I get started with Lightpanda locally and expose a CDP server for my existing Playwright/Puppeteer scripts?

11 min read

Most teams hit the same wall the moment they try to run Playwright or Puppeteer at scale in the cloud: Headless Chrome was built for humans and UI, not for thousands of short‑lived machine sessions. Cold starts stack into minutes, memory peaks kill density, and shared browser state quietly becomes a security risk.

Lightpanda exists to solve that exact failure mode. It’s a headless browser built from scratch in Zig, with no rendering baggage, instant startup, and a dramatically smaller memory footprint—while still exposing a Chrome DevTools Protocol (CDP) server so your existing Playwright/Puppeteer code can keep working.

This guide walks you through getting started with Lightpanda locally and exposing a CDP server for your existing Playwright and Puppeteer scripts, step by step.


Quick Answer: The best overall choice for fast, low‑overhead local CDP development is Lightpanda Local via lightpanda.serve(). If your priority is drop‑in remote scalability for many concurrent test or scraping workers, Lightpanda Cloud CDP endpoints are often a stronger fit. For mixed workloads that occasionally hit edge‑case sites or need full Chrome rendering, consider a hybrid: Lightpanda + managed Headless Chrome.

At-a-Glance Comparison

RankOptionBest ForPrimary StrengthWatch Out For
1Lightpanda Local (lightpanda.serve)Local dev + CI running existing Playwright/Puppeteer codeInstant startup and ~9× lower memory vs Headless Chrome on typical automation flowsYou manage the binary lifecycle and local resources
2Lightpanda Cloud CDP endpointsScaling many workers in the cloud with minimal opsNo cold starts, tokenized CDP endpoints, regioned, proxy-capableRequires network connectivity and token management
3Hybrid: Lightpanda + ChromeEdge‑case sites needing full Chrome rendering“Lightpanda innovation, Chrome reliability” for tricky pagesSlightly more routing logic: you decide which browser to use per task

Comparison Criteria

We evaluated each option against the following criteria to keep the decision grounded in reality:

  • Startup & execution time: How fast you can create a fresh browser session and complete a typical script. Lightpanda’s own Puppeteer benchmark (100 pages on AWS EC2 m5.large) hits ~2.3s vs 25.2s with Headless Chrome—about 11× faster.
  • Memory footprint & isolation: Peak memory per session and how cleanly you can isolate state. Lightpanda sits around 24MB vs 207MB for Chrome in that same benchmark—~9× lower, which compounds heavily when you run hundreds of workers.
  • Integration friction: How much code you need to change in existing Playwright/Puppeteer projects. The bar here is “swap the browser endpoint, keep the rest of your script identical.”

Detailed Breakdown

1. Lightpanda Local (lightpanda.serve)

(Best overall for fast, low‑overhead local CDP automation with existing scripts)

Lightpanda Local ranks as the top choice because it gives you instant, isolated CDP sessions on your machine while letting your existing Playwright/Puppeteer code connect via the standard browserWSEndpoint/endpointURL pattern.

You start a headless browser process locally via Node (using the @lightpanda/browser helper), expose a CDP server on 127.0.0.1:9222 (or any port you choose), and then connect with puppeteer-core or Playwright’s chromium.connectOverCDP.

What it does well

  • Instant startup & low memory (11× faster / 9× lighter benchmark):
    In the 100‑page Puppeteer test on an AWS EC2 m5.large:

    • Headless Chrome: ~25.2s runtime, ~207MB memory peak
    • Lightpanda: ~2.3s runtime, ~24MB memory peak

    On a developer laptop, that translates into “feels instant,” especially when you’re spinning up and tearing down dozens of sessions in CI or during tight feedback loops.

  • Minimal code changes to existing scripts:
    The connection pattern is familiar:

    • For Puppeteer: pass browserWSEndpoint
    • For Playwright: pass endpointURL to connectOverCDP

    The rest of your script—page navigation, selectors, waitForSelector, evaluation logic—remains the same because Lightpanda just exposes a standard CDP surface.

    Example: Puppeteer + Lightpanda Local

    'use strict';
    
    import { lightpanda } from '@lightpanda/browser';
    import puppeteer from 'puppeteer-core';
    
    const lpdopts = { host: '127.0.0.1', port: 9222 };
    
    const puppeteeropts = {
      browserWSEndpoint: 'ws://' + lpdopts.host + ':' + lpdopts.port,
    };
    
    (async () => {
      // Start Lightpanda browser in a separate process with a CDP server.
      const proc = await lightpanda.serve(lpdopts);
    
      // Connect Puppeteer to Lightpanda over CDP.
      const browser = await puppeteer.connect(puppeteeropts);
      const page = await browser.newPage();
    
      // Do your magic ✨
      await page.goto('https://news.ycombinator.com', { waitUntil: 'networkidle2' });
      console.log('CDP connection is working');
    
      // Cleanly disconnect Puppeteer.
      await page.close();
      await browser.close();
    
      // Stop Lightpanda browser process.
      proc.stdout.destroy();
      proc.stderr.destroy();
      proc.kill();
    })();
    

    Example: Playwright + Lightpanda Local

    import { lightpanda } from '@lightpanda/browser';
    import { chromium } from 'playwright-core';
    
    const lpdopts = { host: '127.0.0.1', port: 9222 };
    
    const playwrightopts = {
      endpointURL: 'ws://' + lpdopts.host + ':' + lpdopts.port,
    };
    
    (async () => {
      // Start Lightpanda browser.
      const proc = await lightpanda.serve(lpdopts);
    
      // Connect using Playwright's Chromium driver over CDP.
      const browser = await chromium.connectOverCDP(playwrightopts);
      const context = await browser.newContext({});
      const page = await context.newPage();
    
      // Go to Hacker News home page.
      await page.goto('https://news.ycombinator.com', { waitUntil: 'networkidle' });
      console.log('CDP connection is working');
    
      // Disconnect Playwright.
      await page.close();
      await context.close();
      await browser.close();
    
      // Stop Lightpanda process.
      proc.stdout.destroy();
      proc.stderr.destroy();
      proc.kill();
    })();
    

Tradeoffs & Limitations

  • You own the local runtime:
    You’re responsible for:

    • Installing/updating the Lightpanda binary
    • Managing ports (9222 or another)
    • Ensuring you don’t overload your own machine or CI agent

    For most teams, this is trivial for development and single‑host CI, but you will eventually hit limits when scaling out to dozens of machines.

Decision Trigger

Choose Lightpanda Local if you want:

  • The fastest possible local feedback loop
  • A drop‑in replacement for local Headless Chrome in Playwright/Puppeteer
  • Full control over runtime flags (e.g., --obey_robots, proxies via --http_proxy)

and you prioritize instant startup and low resource usage on individual hosts.


2. Lightpanda Cloud CDP endpoints

(Best for scalable, many‑worker cloud automation without managing a browser fleet)

Lightpanda Cloud is the strongest fit when you’re past the laptop stage and need to run hundreds or thousands of concurrent scripts across regions. Instead of starting lightpanda.serve() yourself, you connect directly to managed CDP endpoints with a tokenized wss:// URL.

The experience is intentionally familiar: your Playwright/Puppeteer code still calls connect/connectOverCDP with an endpoint URL—the only difference is that the endpoint is now a Cloud URL instead of ws://127.0.0.1:9222.

What it does well

  • Zero cold‑start management in the cloud:
    Lightpanda’s machine‑first design is especially visible at scale:

    • You avoid per‑container Chrome startup delays.
    • You don’t have to pre‑warm Chrome pools or implement “browser keep‑alive” hacks.
    • Each worker can request a fresh, isolated Lightpanda session almost instantly.
  • Region, proxy, and security controls baked in:
    Cloud endpoints are:

    • Regioned (e.g., euwest, uswest) so traffic stays where you need it
    • Tokenized over wss:// so you control access from each worker
    • Configurable via query parameters for proxy selection (e.g., datacenter + country)

    From your script’s perspective, it’s still just:

    const browser = await chromium.connectOverCDP({
      endpointURL: 'wss://<region>.lightpanda.io/cdp?token=<YOUR_TOKEN>',
    });
    

Tradeoffs & Limitations

  • Requires network connectivity/Cloud account:
    • You depend on network latency to the Lightpanda region.
    • You need to manage tokens and possibly VPC/firewall rules.
    • For fully air‑gapped environments, on‑prem or local is more appropriate.

Decision Trigger

Choose Lightpanda Cloud CDP endpoints if you want:

  • To run tens/hundreds of concurrent Playwright/Puppeteer workers in the cloud
  • To avoid babysitting Chrome fleets, image sizes, and cold starts
  • To configure region and proxy behavior centrally

and you prioritize operational simplicity and scale over owning every detail of the runtime yourself.


3. Hybrid: Lightpanda + Chrome

(Best for edge‑case pages that occasionally require full Chrome rendering)

The hybrid approach stands out for teams that need both sides: Lightpanda for the bulk of workloads, and Chrome for tricky, high‑fidelity pages that rely on behaviors not yet supported by a headless‑first engine.

The model is simple:

  • Default to Lightpanda for most CDP sessions (scraping, crawling, tests).
  • Route a minority of tasks through a managed Chrome instance when you detect or pre‑classify edge‑case sites.

What it does well

  • “Lightpanda innovation, Chrome reliability” combination:
    You preserve all the Lightpanda benefits (instant startup, low memory, isolation) for the majority of sessions, while keeping Chrome around as a safety net. That can be especially valuable when you:

    • Inherit legacy test suites written assuming full Chrome behavior
    • Crawl long‑tail sites where some rely on niche browser features
    • Need pixel‑perfect rendering for specific flows (e.g., visual regression tests)
  • Incremental migration path:
    You don’t have to flip your entire infrastructure at once. Instead:

    • Move a subset of workers to Lightpanda.
    • Gradually expand coverage as you gain confidence.
    • Keep a small Chrome pool for fallback only.

Tradeoffs & Limitations

  • Slightly more routing logic in your infra:
    • You’ll maintain logic to decide which browser to use per task.
    • Metrics and logging are spread across two browser types.
    • You’ll still pay Chrome’s cost profile on the subset of jobs that use it.

Decision Trigger

Choose Hybrid: Lightpanda + Chrome if you want:

  • To cut cost and latency on the majority of automation workloads
  • To retain Chrome for edge cases without blocking migration
  • To de‑risk adoption in large, heterogeneous test or scraping stacks

and you prioritize flexibility and gradual migration over having exactly one browser everywhere.


How to Get Started Locally: Step-by-Step

Below is a concise runbook to get Lightpanda running locally and expose a CDP server for your existing Playwright/Puppeteer scripts.

Step 1: Install Lightpanda and dependencies

  1. Install Node.js (if you haven’t already).

  2. Add the Lightpanda helper and your automation client:

    npm install @lightpanda/browser puppeteer-core
    # or, for Playwright:
    npm install @lightpanda/browser playwright-core
    
  3. Download or install the Lightpanda binary appropriate for your OS (from the official GitHub / distribution channel). Make sure it is available on your PATH or point @lightpanda/browser to it if needed.

Step 2: Start a local CDP server with lightpanda.serve()

Create index.js and wire up Lightpanda:

Puppeteer variant

'use strict';

import { lightpanda } from '@lightpanda/browser';
import puppeteer from 'puppeteer-core';

const lpdopts = {
  host: '127.0.0.1',
  port: 9222, // You can change this if needed.
};

const puppeteeropts = {
  browserWSEndpoint: 'ws://' + lpdopts.host + ':' + lpdopts.port,
};

(async () => {
  // Start Lightpanda with a CDP server on host:port.
  const proc = await lightpanda.serve(lpdopts);

  // Connect Puppeteer over CDP.
  const browser = await puppeteer.connect(puppeteeropts);
  const page = await browser.newPage();

  // Do your magic ✨
  await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
  console.log(await page.title());

  // Clean up.
  await page.close();
  await browser.close();
  proc.stdout.destroy();
  proc.stderr.destroy();
  proc.kill();
})();

Run it:

node index.js

You should see output similar to:

$ node index.js
🐼 Running Lightpanda's CDP server...
{ pid: 4084512 }
Example Domain

Step 3: Playwright variant (if you prefer Playwright)

If you prefer Playwright, switch your script to:

import { lightpanda } from '@lightpanda/browser';
import { chromium } from 'playwright-core';

const lpdopts = {
  host: '127.0.0.1',
  port: 9222,
};

const playwrightopts = {
  endpointURL: 'ws://' + lpdopts.host + ':' + lpdopts.port,
};

(async () => {
  const proc = await lightpanda.serve(lpdopts);

  const browser = await chromium.connectOverCDP(playwrightopts);
  const context = await browser.newContext({});
  const page = await context.newPage();

  await page.goto('https://example.com', { waitUntil: 'networkidle' });
  console.log(await page.title());

  await page.close();
  await context.close();
  await browser.close();

  proc.stdout.destroy();
  proc.stderr.destroy();
  proc.kill();
})();

Again:

node index.js

The important integration detail: only the connection layer changes. Your tests, locators, and business logic remain untouched.

Step 4: Add runtime flags (robots.txt, proxies, telemetry)

Lightpanda is a browser for machines, so operational flags are first‑class.

Typical flags:

  • --obey_robots – Fetch and obey robots.txt for pages you request. This is the default recommendation for responsible crawling and scraping.
  • --http_proxy – Route traffic through a proxy.

You can pass these flags via lightpanda.serve() configuration or when invoking the binary directly (e.g., ./lightpanda serve --obey_robots --http_proxy=http://user:pass@host:port).

For privacy‑conscious environments, you can disable telemetry:

export LIGHTPANDA_DISABLE_TELEMETRY=true

This keeps runtime behavior explicit and transparent, which matters when you’re running millions of page loads a day.


Final Verdict

If you just want your existing Playwright or Puppeteer scripts to stop dragging Chrome’s cold‑start and memory baggage into every run, the fastest path is:

  • Use Lightpanda Local (lightpanda.serve) in development and early CI.
  • Expose a CDP server on 127.0.0.1:9222.
  • Update only the CDP connection in your code (browserWSEndpoint or endpointURL), leaving the rest of your automation logic intact.

As you scale, moving those same scripts to Lightpanda Cloud CDP endpoints gives you the same integration surface with better density and lower operational friction across regions. For the last 5–10% of edge‑case sites, keep a small Chrome pool in reserve and route selectively, rather than forcing all workloads through a heavyweight UI browser designed for humans.

Cold‑start time and memory peak are now explicit knobs in your stack—not hidden costs inside a black‑box browser.

Next Step

Get Started