---
title: "Troubleshooting Playwright Lighthouse Integration"
description: "Fix common issues when running Lighthouse with Playwright: port conflicts, authentication problems, flaky scores, and Chrome version mismatches."
canonical_url: "https://unlighthouse.dev/learn-lighthouse/playwright/troubleshooting"
last_updated: "2026-07-05T10:28:14.024Z"
---

Common issues and solutions when integrating Lighthouse with [Playwright](https://playwright.dev).

## Port Already in Use

**Error**: `Error: listen EADDRINUSE: address already in use :::9222`

The debugging port is already occupied, usually from a previous run that didn't close properly.

**Solution**: Kill existing Chrome processes or use a different port:

```bash
# Kill process on port 9222
lsof -ti:9222 | xargs kill -9

# Or use a different port
const PORT = 9223
```

For CI environments, use proper cleanup:

```js
async function audit() {
  let browser
  try {
    browser = await chromium.launch({
      args: [`--remote-debugging-port=${PORT}`],
    })
    // ... audit logic
  }
  finally {
    if (browser)
      await browser.close()
  }
}
```

## Authentication State Lost

**Symptom**: Lighthouse audits a login page instead of the authenticated page.

**Cause**: Lighthouse opens a new page context, losing cookies/session.

**Solution**: Use `disableStorageReset: true`:

```js
const result = await lighthouse(url, {
  port: PORT,
  disableStorageReset: true, // Prevents Lighthouse from clearing storage
})
```

See [Authentication Guide](/learn-lighthouse/playwright/authentication) for complete examples.

## Flaky or Inconsistent Scores

**Symptom**: Performance scores vary significantly between runs (±10-20 points).

**Causes**:

- Network variability
- CPU load on the machine
- Shared CI runners
- Third-party script timing

**Solutions**:

1. **Run multiple audits and use median**:

```js
const runs = 3
const scores = []
for (let i = 0; i < runs; i++) {
  const result = await lighthouse(url, { port: PORT })
  scores.push(result.lhr.categories.performance.score)
}
scores.sort((a, b) => a - b)
const median = scores[Math.floor(scores.length / 2)]
```

1. **Disable throttling for consistent local results**:

```js
const result = await lighthouse(url, {
  port: PORT,
  throttling: {
    cpuSlowdownMultiplier: 1,
    throughputKbps: 0,
    requestLatencyMs: 0,
  },
})
```

1. **Use dedicated CI runners** instead of shared ones.

## Chrome/Chromium Version Mismatch

**Error**: `Protocol error` or `Target closed` or `Cannot find context with specified id`

**Cause**: Lighthouse and Playwright bundled Chromium versions are incompatible.

**Solution**: Use the same Chrome for both:

```js
// Use Playwright's bundled Chromium path
import { chromium } from 'playwright'

const browserPath = chromium.executablePath()
console.log('Using Chrome at:', browserPath)

const browser = await chromium.launch({
  executablePath: browserPath,
  args: [`--remote-debugging-port=${PORT}`],
})
```

Or install a specific Chrome version:

```bash
npx playwright install chrome  # Installs stable Chrome, not Chromium
```

## Timeout Errors

**Error**: `Lighthouse timeout` or `Navigation timeout exceeded`

**Causes**:

- Page takes too long to load
- `waitUntil: 'networkidle'` waiting for never-ending requests
- Large pages with many resources

**Solutions**:

1. **Increase Lighthouse timeout**:

```js
const result = await lighthouse(url, {
  port: PORT,
  maxWaitForLoad: 60000, // 60 seconds (default is 45s)
})
```

1. **Use different wait strategy**:

```js
// Instead of networkidle, wait for specific element
await page.goto(url)
await page.waitForSelector('#main-content')
```

1. **Check for infinite polling requests** (analytics, websockets).

## Sandbox Errors

**Error**: `No usable sandbox!` or `Running as root without --no-sandbox is not supported`

**Cause**: Chrome sandboxing issues, common in Docker/CI.

**Solution**: Disable sandbox (only in trusted CI environments):

```js
const browser = await chromium.launch({
  args: [
    `--remote-debugging-port=${PORT}`,
    '--no-sandbox',
    '--disable-setuid-sandbox',
  ],
})
```

<warning>

Only disable sandbox in controlled CI environments, never in production or when processing untrusted URLs.

</warning>

## Multiple Concurrent Audits Fail

**Error**: Audits interfere with each other or return incorrect results.

**Cause**: Multiple Lighthouse instances trying to use the same debugging port.

**Solution**: Use different ports for parallel audits:

```js
async function auditWithDynamicPort(url) {
  const port = 9222 + Math.floor(Math.random() * 1000)
  const browser = await chromium.launch({
    args: [`--remote-debugging-port=${port}`],
  })
  // ... use `port` variable
}
```

Or run audits sequentially with a single worker:

```bash
# Playwright Test
npx playwright test --workers=1
```

## Lighthouse Reports Show Wrong Page

**Symptom**: Report shows homepage or login page instead of target URL.

**Causes**:

- Redirects before audit runs
- Authentication issues
- URL mismatch between Playwright navigation and Lighthouse call

**Solution**: Verify URL after navigation:

```js
await page.goto(targetUrl, { waitUntil: 'networkidle' })

// Check actual URL
const actualUrl = page.url()
if (actualUrl !== targetUrl) {
  console.warn(`Redirected from ${targetUrl} to ${actualUrl}`)
}

// Use actual URL for Lighthouse
const result = await lighthouse(actualUrl, { port: PORT })
```

## Empty or Incomplete Reports

**Symptom**: Lighthouse report missing metrics or categories.

**Causes**:

- Page not fully loaded
- JavaScript errors on page
- Missing viewport settings

**Solution**: Check page readiness:

```js
await page.goto(url, { waitUntil: 'networkidle' })

// Wait for critical content
await page.waitForSelector('[data-testid="main-content"]')

// Check for console errors
page.on('console', (msg) => {
  if (msg.type() === 'error')
    console.warn('Page error:', msg.text())
})
```

## CI-Specific Issues

### GitHub Actions: Chrome Not Found

```yaml
- name: Install Chrome
  run: npx playwright install chromium --with-deps
```

The `--with-deps` flag installs system dependencies required by Chromium.

### Docker: Missing Dependencies

Add to Dockerfile:

```dockerfile
RUN apt-get update && apt-get install -y \
    libnss3 \
    libatk1.0-0 \
    libatk-bridge2.0-0 \
    libcups2 \
    libdrm2 \
    libxkbcommon0 \
    libxcomposite1 \
    libxdamage1 \
    libxrandr2 \
    libgbm1 \
    libasound2
```

Or use Playwright's [Docker](https://docker.com) image:

```dockerfile
FROM mcr.microsoft.com/playwright:v1.40.0-jammy
```

**Crash / Target Closed in Docker**:
If Chrome crashes with "Target closed" or "Page crashed", it's often due to small shared memory `/dev/shm`. Add this flag:

```js
const browser = await chromium.launch({
  args: [
    `--remote-debugging-port=${PORT}`,
    '--disable-dev-shm-usage', // Critical for Docker
  ],
})
```

## Visual Debugging

Use Playwright's [Inspector](https://playwright.dev/docs/debug#playwright-inspector) to pause execution right before the Lighthouse audit to verify the page state.

```bash
# Run with Inspector
PWDEBUG=1 npx playwright test
```

When paused:

1. Check that the page has logged you in (if expected).
2. Verify the browser has fully loaded the DOM.
3. Check for any overlay/modals that might block Lighthouse.

## Still Stuck?

- Check [Lighthouse GitHub Issues](https://github.com/GoogleChrome/lighthouse/issues)
- Check [Playwright GitHub Issues](https://github.com/microsoft/playwright/issues)
- For site-wide auditing without these integration headaches, try [Unlighthouse](/guide/getting-started/installation)
