How do I connect Puppeteer to Lightpanda Cloud using browserWSEndpoint, and how do I set the region?
Headless Browser Infrastructure

How do I connect Puppeteer to Lightpanda Cloud using browserWSEndpoint, and how do I set the region?

8 min read

Most teams hit the same wall the moment they try to run Puppeteer at scale in the cloud: Headless Chrome is slow to cold-start, heavy on memory, and painful to operate when you’re fanning out across hundreds of containers. Lightpanda Cloud exists to remove that bottleneck, while still letting you keep your existing Puppeteer code and connect over browserWSEndpoint.

Below is a step‑by‑step guide to:

  • Connect Puppeteer to Lightpanda Cloud using browserWSEndpoint
  • Choose and set the Cloud region (euwest or uswest)
  • Pass your token safely
  • Sanity‑check that everything is actually talking to the right region

Quick Answer:
Use puppeteer.connect with a browserWSEndpoint pointing to Lightpanda Cloud:

const browser = await puppeteer.connect({
  browserWSEndpoint: 'wss://euwest.cloud.lightpanda.io/ws?token=YOUR_TOKEN',
});

Swap euwest for uswest to change the region. The rest of your script remains the same.


At-a-Glance Comparison

If you’re deciding how to wire Puppeteer to Lightpanda Cloud for different deployment scenarios, here’s the ranking of the three main connection patterns I see in practice.

RankOptionBest ForPrimary StrengthWatch Out For
1Direct puppeteer.connect to CloudMost CI/CD and serverless workloadsMinimal changes: just swap browserWSEndpointHard‑coding tokens/regions if you don’t use env vars
2Env‑driven region & tokenMulti‑region deployments & secrets‑managed setupsClean config: LPD_REGION / LPD_TOKEN per environmentSlightly more boilerplate to resolve URLs
3Local CDP proxy to CloudAdvanced routing / debugging setupsCentral point for proxying, logging, IP policyMore moving parts; not needed for 90% of use cases

Comparison Criteria

We evaluate these integration patterns on three simple axes:

  • Integration friction: How many changes do you have to make to an existing Puppeteer script?
  • Operational clarity: How obvious is it which region and token a given run is using?
  • Scalability & safety: How well does the pattern scale across environments without leaking tokens or misrouting traffic?

Detailed Breakdown

1. Direct puppeteer.connect to Lightpanda Cloud (Best overall for straightforward adoption)

This is the pattern I recommend if you just want your existing Puppeteer scripts to stop paying the cold‑start tax of Headless Chrome.

You replace puppeteer.launch with puppeteer.connect and point the browserWSEndpoint at Lightpanda Cloud:

import puppeteer from 'puppeteer-core'; // or 'puppeteer'

(async () => {
  const browser = await puppeteer.connect({
    browserWSEndpoint: 'wss://euwest.cloud.lightpanda.io/ws?token=YOUR_TOKEN',
  });

  const page = await browser.newPage();
  await page.goto('https://example.com', { waitUntil: 'networkidle2' });

  // … your usual Puppeteer logic …

  await browser.close();
})();

What it does well:

  • Minimal code changes:
    In many scripts, this is literally a one‑line swap:

    // Before (Chrome):
    const browser = await puppeteer.launch({ headless: 'new' });
    
    // After (Lightpanda Cloud):
    const browser = await puppeteer.connect({
      browserWSEndpoint: 'wss://euwest.cloud.lightpanda.io/ws?token=YOUR_TOKEN',
    });
    

    Everything else (newPage, goto, evaluate, etc.) continues to work as before because Lightpanda exposes a Chrome DevTools Protocol (CDP) server.

  • Immediate performance win:
    Under the same Puppeteer script and AWS EC2 m5.large, we typically see:

    • ~2.3s execution vs 25.2s for Headless Chrome on a 100‑page test
    • ~24 MB peak memory vs ~207 MB

    That delta matters a lot once you’re at any real concurrency.

Tradeoffs & limitations:

  • Token & region baked into the string:
    If you drop the full URL + token directly in your code, it’s fast to get started but messy for production. You’ll want to move region and token into environment variables before this script touches CI or shared repos.

Decision Trigger:
Use this pattern when you want a fast cut‑over from Chrome to Lightpanda Cloud and you’re still iterating locally. Once you’re happy with the behavior, refactor the URL into env‑driven configuration (next option).


2. Env-driven region and token (Best for multi-environment & multi-region setups)

If you deploy across different regions or environments (dev/staging/prod), hard‑coding euwest and a token isn’t tenable. Instead, build the browserWSEndpoint from environment variables.

Example using LPD_REGION and LPD_TOKEN:

import puppeteer from 'puppeteer-core';

const region = process.env.LPD_REGION || 'euwest'; // default to euwest
const token = process.env.LPD_TOKEN;

if (!token) {
  throw new Error('Missing LPD_TOKEN environment variable');
}

const browserWSEndpoint = `wss://${region}.cloud.lightpanda.io/ws?token=${token}`;

(async () => {
  const browser = await puppeteer.connect({ browserWSEndpoint });

  const page = await browser.newPage();
  await page.goto('https://example.com');

  // … your scenario …

  await browser.close();
})();

Choosing the region:

Lightpanda Cloud currently exposes at least these two canonical endpoints:

  • wss://euwest.cloud.lightpanda.io/ws
  • wss://uswest.cloud.lightpanda.io/ws

Pick the region closest to your workloads or targets to reduce latency:

  • If your jobs run in EU AWS regions (e.g., eu-west-1), prefer euwest.
  • If your jobs run in US West (e.g., us-west-2), prefer uswest.

What it does well:

  • Operational clarity:
    You can glance at environment config and immediately see:

    • which region a given environment is using (LPD_REGION)
    • which token is loaded (LPD_TOKEN via your secret manager)
  • Easy to fan out:
    You can run the same code with different regions simply by adjusting env vars per deployment, without branching the script.

Tradeoffs & limitations:

  • Slightly more boilerplate:
    You add a few lines of config building instead of a single hard‑coded URL. In return, you get something that won’t surprise you six months from now.

Decision Trigger:
Use this pattern when you’re moving beyond a single laptop or one‑off script and expect to run Puppeteer + Lightpanda Cloud in CI/CD, Kubernetes, or serverless across more than one region or environment.


3. Local CDP proxy / wrapper (Best for advanced routing & debugging)

Some teams want more control: logging all CDP traffic, routing via custom egress policies, or dynamically switching upstream regions. In that case, you can insert a local CDP proxy and still keep the Puppeteer browserWSEndpoint pointing to ws://127.0.0.1:PORT.

Conceptually:

  1. Your script connects Puppeteer to ws://127.0.0.1:9222
  2. Your local process forwards that CDP stream to wss://euwest.cloud.lightpanda.io/ws?token=… or wss://uswest.cloud.lightpanda.io/ws?token=…
  3. Region selection happens inside your proxy based on rules (geo, tenant, feature flags, etc.)

In code terms on the Puppeteer side, it looks like the local case from the docs:

import puppeteer from 'puppeteer-core';

(async () => {
  const browser = await puppeteer.connect({
    browserWSEndpoint: 'ws://127.0.0.1:9222',
  });

  // The rest of your script remains the same.
})();

Your proxy process (not shown here) is responsible for:

  • Establishing the upstream wss://<region>.cloud.lightpanda.io/ws?token=…
  • Passing CDP messages back and forth
  • Potentially logging/inspecting for debugging

What it does well:

  • Centralized control:
    Good fit if you operate very large fleets and want to keep credentials and routing logic centralized rather than embedding Cloud URLs everywhere.

  • Debug capability:
    You can introspect CDP messages locally without instrumenting every script.

Tradeoffs & limitations:

  • More moving parts:
    You own the reliability of this proxy. For the majority of users, direct Cloud connections are simpler and safer.

Decision Trigger:
Reach for this only if you already have a need for CDP‑level routing/inspection or you have very strict networking constraints. Otherwise, use the direct Cloud pattern.


How to verify you’re connected to the right Lightpanda Cloud region

Once you’ve wired browserWSEndpoint, it’s worth doing a quick sanity check.

1. Log the endpoint at startup

Always print the resolved browserWSEndpoint before connecting:

console.log('Connecting to Lightpanda at', browserWSEndpoint);
const browser = await puppeteer.connect({ browserWSEndpoint });

For example:

  • wss://euwest.cloud.lightpanda.io/ws?token=…
  • wss://uswest.cloud.lightpanda.io/ws?token=…

This makes debugging misconfigured env vars trivial.

2. Run a simple smoke test

Use a single page visit as a health check:

const page = await browser.newPage();
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
console.log(await page.title());

If this succeeds, your CDP connection to the chosen region is working.

3. Use separate tokens per environment when possible

Even though the mechanics are the same (?token=YOUR_TOKEN in the query string), I strongly recommend:

  • One token per environment (dev/staging/prod)
  • Optionally, one token per region per environment

That way, a misrouted deployment shows up quickly (wrong token / wrong region), rather than silently mixing concerns.


Responsible automation with Lightpanda Cloud

Once your Puppeteer scripts are running faster and cheaper, it becomes easy to accidentally overload a target site. The same numbers that make Lightpanda attractive (instant startup, low memory) also mean you can scale CDP sessions very aggressively.

When you’re building crawlers or scrapers on top of Lightpanda Cloud via Puppeteer:

  • Respect robots.txt:
    If you switch to the open‑source CLI for some workloads, you can enforce this with --obey_robots. Even in Cloud, aim to mirror that behavior in your scheduling logic.

  • Throttle concurrency and rate:
    A small mistake in your queueing logic can become a DDOS‑style incident quickly when all your browsers start in milliseconds instead of seconds. Build in rate limits and backoff.


Final Verdict

If your question is simply “How do I connect Puppeteer to Lightpanda Cloud using browserWSEndpoint, and how do I set the region?”, the practical answer is:

  • Use puppeteer.connect with browserWSEndpoint set to
    wss://<REGION>.cloud.lightpanda.io/ws?token=YOUR_TOKEN
  • Choose REGION from:
    • euwestwss://euwest.cloud.lightpanda.io/ws
    • uswestwss://uswest.cloud.lightpanda.io/ws
  • Drive region and token from environment variables for anything beyond local experiments.

From there, the rest of your Puppeteer code stays exactly the same, but your cold‑starts and memory peak stop being the limiting factor.

Next Step

Get Started