
How do I get started with Lightpanda locally and expose a CDP server for my existing Playwright/Puppeteer scripts?
Most scraping and testing stacks today are bottlenecked by one thing: Headless Chrome cold starts in the cloud. Every new container or lambda spins up a full UI browser stack you never render, burns 200+ MB of RAM, and takes seconds to become usable. When you do this hundreds or thousands of times in parallel, cost and latency explode.
Lightpanda exists to fix that: an AI-native, headless-first browser built from scratch for machines, not humans. It speaks Chrome DevTools Protocol (CDP), so you can keep your existing Playwright or Puppeteer scripts and just point them at a different browser endpoint.
This guide walks you through running Lightpanda locally and exposing a CDP server so your existing Playwright/Puppeteer code “just connects” — with instant startup and a fraction of the memory footprint.
Why swap Chrome for Lightpanda in your CDP stack?
Before we touch commands, it’s worth being explicit about what changes when you put Lightpanda under your existing CDP scripts:
-
Instant startup instead of multi‑second cold starts
In our Puppeteer 100‑page benchmark on an AWS EC2 m5.large, Lightpanda completed the run in ~2.3s vs 25.2s for Headless Chrome — roughly 11× faster. -
Minimal memory instead of 200+ MB per browser
The same test showed a memory peak of ~24 MB vs 207 MB for Headless Chrome — around 9× less memory per process. -
Headless‑only, purpose‑built for automation
No rendering stack, no UI baggage, no decades of desktop browser legacy. Just a machine browser that executes JavaScript and Web APIs, controlled entirely via CDP. -
Drop‑in integration via CDP
Lightpanda exposes a CDP server. You connect with:browserWSEndpointin PuppeteerconnectOverCDP/endpointURLin Playwright
The rest of your script remains the same.
If you already have a CDP stack (Playwright, Puppeteer, chromedp), you don’t need to rewrite flows. You just swap the “browser under the hood.”
What you’ll set up locally
By the end of this guide you will:
- Install the Lightpanda browser locally.
- Start a Lightpanda CDP server on
127.0.0.1:9222. - Connect Puppeteer to that server.
- Connect Playwright to that server.
- Cleanly start/stop the Lightpanda process from your Node.js script.
You’ll be ready to run your existing automation against a browser designed for cloud‑scale workloads.
Step 1 — Install Lightpanda locally
Lightpanda is distributed as a standalone binary and via the @lightpanda/browser helper for Node.js. The Node helper gives you a small API to spawn and manage the Lightpanda process directly from your test/scraping scripts.
- Install the Node helper:
npm install @lightpanda/browser --save-dev
# or
yarn add @lightpanda/browser --dev
- (If needed) Install the binary following the instructions on the Lightpanda site or GitHub. The
@lightpanda/browserpackage expectslightpandato be available on your PATH or will use its embedded binary if shipped for your platform.
Once this is in place, your Node.js script can start a local CDP server with a few lines of code.
Step 2 — Start a local CDP server from Node
The key concept: you don’t launch Playwright/Puppeteer’s bundled browser anymore. You launch Lightpanda, which exposes a CDP server, then connect your existing client to that server.
Lightpanda’s Node API gives you lightpanda.serve(options):
import { lightpanda } from '@lightpanda/browser';
const lpdopts = {
host: '127.0.0.1',
port: 9222,
};
(async () => {
// Start Lightpanda browser in a separate process.
const proc = await lightpanda.serve(lpdopts);
console.log('🐼 Running Lightpanda\'s CDP server...', { pid: proc.pid });
// Do your magic ✨ (CDP client connects here)
// Stop Lightpanda browser process.
proc.stdout.destroy();
proc.stderr.destroy();
proc.kill();
})();
This:
- Starts Lightpanda listening on
ws://127.0.0.1:9222. - Prints the process PID for debugging.
- Gives you full control to cleanly terminate the browser when you’re done.
Now we plug Playwright or Puppeteer into that CDP endpoint.
Step 3 — Connect Puppeteer to the Lightpanda CDP server
If you’re running Puppeteer, you likely use something like puppeteer.launch() today. With Lightpanda, you don’t “launch Chromium” — you connect to an existing CDP endpoint.
3.1. Install puppeteer-core
Use puppeteer-core so you don’t pull in a large Chromium bundle you’re not going to use:
npm install puppeteer-core --save-dev
# or
yarn add puppeteer-core --dev
3.2. Wire Puppeteer to Lightpanda
Create or edit index.js:
'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.
const proc = await lightpanda.serve(lpdopts);
// Connect Puppeteer to the browser.
const browser = await puppeteer.connect(puppeteeropts);
const page = await browser.newPage();
// Do your magic ✨
await page.goto('https://news.ycombinator.com', { waitUntil: 'domcontentloaded' });
console.log('CDP connection is working with Puppeteer + Lightpanda');
// Cleanly disconnect Puppeteer.
await page.close();
await browser.disconnect();
// Stop Lightpanda browser process.
proc.stdout.destroy();
proc.stderr.destroy();
proc.kill();
})();
3.3. Run the script
node index.js
You should see something like:
$ node index.js
🐼 Running Lightpanda's CDP server... { pid: 4084512 }
CDP connection is working with Puppeteer + Lightpanda
Under the hood:
- Puppeteer speaks CDP over
browserWSEndpoint. - Lightpanda executes your navigation and JS in a lightweight, headless‑only runtime.
- You get instant startup and a much smaller memory peak every time this script runs.
If you already have complex Puppeteer flows, the main change is replacing puppeteer.launch() with puppeteer.connect() and pointing at Lightpanda’s browserWSEndpoint.
Step 4 — Connect Playwright to the Lightpanda CDP server
Playwright also has native support for attaching to an existing browser via CDP. Instead of chromium.launch(), you use chromium.connectOverCDP() with Lightpanda’s endpointURL.
4.1. Install playwright-core
You only need playwright-core:
npm install playwright-core --save-dev
# or
yarn add playwright-core --dev
4.2. Wire Playwright to Lightpanda
Create or edit index.js:
'use strict';
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 in a separate process.
const proc = await lightpanda.serve(lpdopts);
// Connect using Playwright's chromium driver to the browser.
const browser = await chromium.connectOverCDP(playwrightopts);
const context = await browser.newContext({});
const page = await context.newPage();
// Do your magic ✨
await page.goto('https://news.ycombinator.com', { waitUntil: 'domcontentloaded' });
console.log('CDP connection is working with Playwright + Lightpanda');
// Disconnect Playwright.
await page.close();
await context.close();
await browser.close();
// Stop Lightpanda browser process.
proc.stdout.destroy();
proc.stderr.destroy();
proc.kill();
})();
4.3. Run the script
node index.js
Expected output:
$ node index.js
🐼 Running Lightpanda's CDP server... { pid: 31371 }
CDP connection is working with Playwright + Lightpanda
Everything else in your Playwright tests — selectors, assertions, fixtures — stays the same. The only structural change is swapping launch() for connectOverCDP() and using Lightpanda as the CDP server.
Step 5 — Controlling behavior via Lightpanda flags
Because Lightpanda is a headless‑only machine browser, the CLI is where you control low‑level behavior relevant to crawling, scraping, and testing at scale.
Some key flags you’ll commonly use when you scale beyond local:
-
--obey_robots
When enabled, Lightpanda will fetch and obeyrobots.txtfor the sites you crawl.Example:
./lightpanda serve --obey_robotsOr via the Node helper (pass flags through your serve options) as your stack evolves.
-
Timeouts and networking behavior
Lightpanda exposes flags to control transfer timeouts (e.g., a default of10000ms;0to never timeout). You’ll typically tune this when running large crawls to balance resilience and cost. -
Proxy configuration
When you move to the cloud or need geo/load distribution, you’ll use HTTP/SOCKS proxy settings (--http_proxyin CLI or proxy parameters in Cloud endpoints). Locally, this is often not needed, but it’s good to design your Playwright/Puppeteer setup so proxy configuration is a single variable, not hard‑coded.
These flags are part of what makes Lightpanda a better primitive for machine workloads: finer control over network behavior without carrying a full UI browser.
Step 6 — Responsible automation: robots.txt and rate limits
Running a browser that can spin up in milliseconds and consume ~24 MB of memory per process is powerful but also dangerous if misused. You can DDoS a target far faster than you might expect if you naively parallelize.
Keep these practices in your stack:
-
Respect
robots.txt
Use--obey_robotswhenever you’re crawling the public web and don’t have an explicit agreement with the site owner. -
Be rate‑aware
Even with instant startup, implement delays and concurrency caps in your Playwright/Puppeteer code. Use queues and jitter backoff, and monitor response codes for throttling. -
Isolate sessions
Instead of reusing a single browser with shared cookies, take advantage of Lightpanda’s low memory to spin up many short‑lived, isolated sessions. This reduces cross‑tenant leakage and makes your system easier to reason about.
The same properties that lower your cloud bill also make high frequency requesting trivial; build guardrails into your code accordingly.
How this maps to your existing Playwright/Puppeteer stack
If you’re migrating an existing codebase, the minimal diff usually looks like:
For Puppeteer
Before (Chrome)
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch({
headless: 'new',
// ...
});
const page = await browser.newPage();
After (Lightpanda via CDP)
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 };
const proc = await lightpanda.serve(lpdopts);
const browser = await puppeteer.connect(puppeteeropts);
const page = await browser.newPage();
Everything past newPage() can remain identical.
For Playwright
Before (Chromium)
import { chromium } from 'playwright';
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext();
const page = await context.newPage();
After (Lightpanda via CDP)
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 };
const proc = await lightpanda.serve(lpdopts);
const browser = await chromium.connectOverCDP(playwrightopts);
const context = await browser.newContext();
const page = await context.newPage();
Again, the rest of your test logic does not need to change.
When you’re ready to move from local to cloud
Running locally is the easiest way to validate compatibility and CDP behavior. Once you’re comfortable:
- Use the same
browserWSEndpoint/endpointURLpattern with Lightpanda Cloud. - Point your clients at region endpoints (e.g.,
wss://euwest.lightpanda.io?token=...). - Configure proxies via query parameters to control datacenter and country where traffic exits.
- Keep the same
connect/connectOverCDPflow; only thews://127.0.0.1:9222URL changes to awss://Cloud endpoint.
Because the local browser and Cloud product both speak CDP and are driven by the same machine‑first design, migration is mostly a matter of swapping connection strings.
Summary
To get started with Lightpanda locally and expose a CDP server for your existing Playwright/Puppeteer scripts:
- Install
@lightpanda/browser(andpuppeteer-coreand/orplaywright-core). - Start Lightpanda with
lightpanda.serve({ host: '127.0.0.1', port: 9222 }). - Connect Puppeteer using
browserWSEndpointor Playwright usingconnectOverCDP/endpointURL. - Keep your test and scraping logic the same; only the browser bootstrapping changes.
- Add flags like
--obey_robotsand timeouts as you scale out, and be deliberate about concurrency.
You end up with the same CDP automation surface, but backed by a browser that was actually designed to run in the cloud — with instant startup, ~9× less memory, and a much simpler operational profile.