Skip to main content
You can’t launch a local Chromium binary inside Vercel’s serverless functions. Use Playwright’s connectOverCDP to connect to a hosted browser (Kernel) and keep your code and API routes on Vercel.

The Error

If you’re seeing this error on Vercel:
Error: Executable doesn't exist at /var/task/.next/server/chunks/playwright/chromium-1091/chrome-linux/headless_shell
Or similar variations like:
browserType.launch: Executable doesn't exist
Failed to launch browser
This happens because Vercel’s serverless environment doesn’t include the Chromium binary that Playwright needs.

The Solution

Instead of launching a local browser, connect to a remote browser via CDP (Chrome DevTools Protocol):
// pages/api/scrape.ts
import { chromium } from 'playwright-core';
import { Kernel } from '@onkernel/sdk';

export default async function handler(req, res) {
  const kernel = new Kernel({ apiKey: process.env.KERNEL_API_KEY });
  const kernelBrowser = await kernel.browsers.create();
  
  const browser = await chromium.connectOverCDP({
    wsEndpoint: kernelBrowser.cdp_ws_url
  });
  
  const context = browser.contexts()[0];
  const page = context.pages()[0];
  
  await page.goto(req.query.url || 'https://example.com');
  const title = await page.title();
  const html = await page.content();
  
  await browser.close();
  await kernel.browsers.deleteByID(kernelBrowser.session_id);
  
  return res.json({ title, html });
}

Environment Variables

Add your Kernel API key to Vercel:
# Get your API key from https://dashboard.onkernel.com/settings/api-keys
vercel env add KERNEL_API_KEY
Set the value to your Kernel API key and select all environments (Production, Preview, Development).

Toggle Between Local and Remote

For local development, you can use local Playwright. For production on Vercel, use Kernel:
import { chromium } from 'playwright-core';
import { Kernel } from '@onkernel/sdk';

const isProduction = process.env.VERCEL_ENV === 'production';

async function getBrowser() {
  if (isProduction || process.env.USE_KERNEL) {
    // Use Kernel on Vercel
    const kernel = new Kernel({ apiKey: process.env.KERNEL_API_KEY });
    const kb = await kernel.browsers.create();
    return {
      browser: await chromium.connectOverCDP({ wsEndpoint: kb.cdp_ws_url }),
      sessionId: kb.session_id,
      kernel
    };
  } else {
    // Use local Playwright in development
    return {
      browser: await chromium.launch(),
      sessionId: null,
      kernel: null
    };
  }
}

// Usage
const { browser, sessionId, kernel } = await getBrowser();
// ... use browser ...
await browser.close();
if (kernel && sessionId) {
  await kernel.browsers.deleteByID(sessionId);
}

Why This Works

Vercel’s serverless functions have limitations:
  • No filesystem for binaries: Chromium requires ~300MB of binaries that can’t be bundled
  • Cold start constraints: Functions need to start in <10s
  • Read-only filesystem: Can’t install or cache browser binaries at runtime
Kernel provides browsers in the cloud that you connect to via WebSocket, bypassing all these constraints.

Native Vercel Integration

For a seamless setup, install Kernel from the Vercel Marketplace. This provides:
  • One-click API key provisioning
  • Automatic QA checks on every deployment
  • Configuration management via Vercel dashboard
See the Vercel integration guide for details.

FAQ

Can I run Playwright on Vercel?

You cannot launch a local Chromium binary inside Vercel’s serverless functions. However, you can use Playwright’s connectOverCDP method to connect to a remote browser hosted by Kernel. Your Playwright code runs on Vercel; the browser runs on Kernel.

Do I need to change my existing Playwright code?

Minimal changes. Replace browser.launch() with chromium.connectOverCDP() and connect to Kernel’s CDP endpoint. The rest of your Playwright code (page navigation, selectors, actions) remains identical.

What about playwright install?

You don’t need to run playwright install on Vercel. Use playwright-core (which doesn’t include browser binaries) and connect to Kernel’s hosted browsers instead.

Does this work with Puppeteer too?

Yes! Puppeteer also supports CDP connections:
import puppeteer from 'puppeteer-core';
const browser = await puppeteer.connect({
  browserWSEndpoint: kernelBrowser.cdp_ws_url
});

How much does it cost?

Kernel charges per-minute of active browser time. See pricing for details. Most API routes run in seconds, costing fractions of a cent per request.

Troubleshooting

Still seeing errors? Check:
  1. KERNEL_API_KEY is set in Vercel environment variables
  2. Using playwright-core (not playwright) in package.json
  3. Using chromium.connectOverCDP() (not chromium.launch())
  4. Awaiting the connection before using the browser
Need help? Join our Discord or check the troubleshooting hub.
I