---
title: "Lighthouse CI Configuration Reference"
description: "Complete guide to lighthouserc.js configuration options. Covers collect, assert, upload, and server settings for @lhci/cli."
canonical_url: "https://unlighthouse.dev/learn-lighthouse/lighthouse-ci/configuration"
last_updated: "2026-07-05T10:28:37.095Z"
---

Lighthouse CI uses configuration files to define how it collects audits, evaluates assertions, and uploads results.

## Configuration File Formats

Lighthouse CI supports multiple configuration file formats, checked in priority order:

1. `.lighthouserc.js` - JavaScript module (supports dynamic config)
2. `lighthouserc.js`
3. `.lighthouserc.cjs` - CommonJS explicit
4. `lighthouserc.cjs`
5. `.lighthouserc.json` - JSON format
6. `lighthouserc.json`
7. `.lighthouserc.yml` - YAML format
8. `lighthouserc.yml`
9. `.lighthouserc.yaml`
10. `lighthouserc.yaml`

### JavaScript Config

```js
// lighthouserc.js
export default {
  ci: {
    collect: {
      url: ['https://example.com/', 'https://example.com/about'],
      numberOfRuns: 3,
    },
    assert: {
      preset: 'lighthouse:recommended',
    },
    upload: {
      target: 'temporary-public-storage',
    },
  },
}
```

### JSON Config

```json
{
  "ci": {
    "collect": {
      "url": ["https://example.com/"],
      "numberOfRuns": 5
    },
    "assert": {
      "preset": "lighthouse:recommended"
    }
  }
}
```

### Using CLI Flag

Override the default config file location:

```bash
lhci autorun --config=custom-config.js
```

## Environment Variables

All configuration options can be set via environment variables using the `LHCI_` prefix and double underscores for nesting:

```bash
# Equivalent to ci.collect.numberOfRuns
LHCI_COLLECT__NUMBER_OF_RUNS=5

# Equivalent to ci.upload.serverBaseUrl
LHCI_UPLOAD__SERVER_BASE_URL=https://lhci.example.com

# Equivalent to ci.upload.token
LHCI_UPLOAD__TOKEN=your-secret-token
```

Environment variables override config file values.

## Collect Options

The `collect` configuration controls how Lighthouse audits are run.

### Basic Collection

```js
const config2 = {
  ci: {
    collect: {
      // URLs to audit (required)
      url: [
        'https://example.com/',
        'https://example.com/products',
        'https://example.com/about',
      ],

      // Number of times to audit each URL (default: 3)
      // 5 runs = 2x more stable than 1 run (Google research)
      // 3 runs = 37% variance reduction (DebugBear analysis)
      numberOfRuns: 5,

      // Lighthouse settings object
      settings: {
        preset: 'desktop',
        onlyCategories: ['performance', 'accessibility'],
      },
    },
  },
}
```

### Static Site Collection

For auditing static builds before deployment:

```js
const config3 = {
  ci: {
    collect: {
      // Path to built static files
      staticDistDir: './dist',

      // URLs to audit (relative to staticDistDir)
      url: [
        'http://localhost/index.html',
        'http://localhost/about/index.html',
      ],

      numberOfRuns: 3,
    },
  },
}
```

### Server Command

Start a local server before collection:

```js
const config4 = {
  ci: {
    collect: {
      startServerCommand: 'npm run serve',
      startServerReadyPattern: 'Server listening on',
      startServerReadyTimeout: 10000, // ms

      url: ['http://localhost:8080/'],
      numberOfRuns: 3,
    },
  },
}
```

The server process is automatically killed after collection completes.

### Chrome Options

```js
const config5 = {
  ci: {
    collect: {
      // Path to Chrome executable
      chromePath: '/usr/bin/google-chrome',

      // Chrome launch flags
      chromeFlags: '--no-sandbox --disable-gpu',

      // Puppeteer script for authentication/setup
      puppeteerScript: './scripts/puppeteer-script.js',

      // Puppeteer launch options
      puppeteerLaunchOptions: {
        headless: true,
      },
    },
  },
}
```

### Puppeteer Script

For authenticated pages or complex setup:

```js
// scripts/puppeteer-script.js
export default async (browser, context) => {
  const page = await browser.newPage()
  await page.goto('https://example.com/login')
  await page.type('#username', 'user')
  await page.type('#password', 'pass')
  await page.click('#submit')
  await page.waitForNavigation()
}
```

### Advanced Settings

```js
const config6 = {
  ci: {
    collect: {
      // Disable headless mode for debugging
      headful: false,

      // Preserve previous collection data instead of replacing
      additive: false,

      // Maximum wait time for page load
      maxWaitForLoad: 45000, // ms

      // Lighthouse settings override
      // Note: simulated throttling (default) provides lowest variance
      // See: https://github.com/GoogleChrome/lighthouse/blob/main/docs/throttling.md
      settings: {
        throttling: {
          rttMs: 40,
          throughputKbps: 10240,
          cpuSlowdownMultiplier: 1,
        },
        screenEmulation: {
          mobile: false,
          width: 1350,
          height: 940,
          deviceScaleFactor: 1,
        },
      },
    },
  },
}
```

## Assert Options

The `assert` configuration defines performance budgets and quality gates.

### Presets

Three built-in presets provide baseline assertions:

```js
const config7 = {
  ci: {
    assert: {
      // All Lighthouse audits must pass
      preset: 'lighthouse:all',

      // OR recommended audits only
      // preset: 'lighthouse:recommended',

      // OR recommended excluding PWA audits
      // preset: 'lighthouse:no-pwa',
    },
  },
}
```

### Custom Assertions

Override preset or define custom assertions:

```js
const config8 = {
  ci: {
    assert: {
      preset: 'lighthouse:recommended',
      assertions: {
        // Category scores (0-1)
        'categories:performance': ['error', { minScore: 0.9 }],
        'categories:accessibility': ['warn', { minScore: 0.95 }],
        'categories:seo': ['error', { minScore: 1 }],

        // Specific audit scores
        'first-contentful-paint': ['error', { maxNumericValue: 2000 }],
        'largest-contentful-paint': ['error', { maxNumericValue: 2500 }],
        'cumulative-layout-shift': ['error', { maxNumericValue: 0.1 }],
        'total-blocking-time': ['error', { maxNumericValue: 300 }],

        // Resource budgets
        'resource-summary:script:size': ['error', { maxNumericValue: 300000 }],
        'resource-summary:image:size': ['error', { maxNumericValue: 500000 }],
        'resource-summary:document:size': ['error', { maxNumericValue: 50000 }],

        // Pass/fail audits
        'uses-http2': 'error',
        'uses-long-cache-ttl': 'warn',
        'offscreen-images': 'off',
      },
    },
  },
}
```

**Category assertions** cover different audit groups: [Performance](/learn-lighthouse/core-web-vitals) evaluates speed metrics, [Accessibility](/learn-lighthouse/accessibility) checks usability standards, [SEO](/learn-lighthouse/seo) validates search optimization, and [Best Practices](/learn-lighthouse/best-practices) validates modern web standards.

**Core Web Vitals assertions** target key user experience metrics. When these fail, see metric-specific guides: [LCP](/learn-lighthouse/lcp), [CLS](/learn-lighthouse/cls), [INP](/learn-lighthouse/inp).

### Assertion Levels

- `'error'` - Fails the build
- `'warn'` - Logs warning but doesn't fail
- `'off'` - Disables the assertion

### Aggregation Methods

Choose how Lighthouse CI combines multiple runs:

```js
const config9 = {
  ci: {
    assert: {
      // How to aggregate multiple runs
      // 'optimistic' (default), 'median', 'pessimistic', 'median-run'
      aggregationMethod: 'median',

      assertions: {
        'first-contentful-paint': ['error', {
          maxNumericValue: 2000,
          aggregationMethod: 'pessimistic', // Override for this audit
        }],
      },
    },
  },
}
```

- `median` - Middle value across runs (recommended for stability)
- `optimistic` - Best value across runs (preset default)
- `pessimistic` - Worst value across runs (strictest)
- `median-run` - All values from the median run

<note type="info">

**Why median?** Since the performance score is already a weighted average, taking the mean of scores compounds outlier effects. [Lighthouse CI calculates median](https://github.com/GoogleChrome/lighthouse/blob/main/core/lib/median-run.js) by finding the run closest to median FCP **and** median TTI (earliest + latest page lifecycle moments), not just the score.

</note>

<warning>

**Never run concurrent Lighthouse audits** on the same machine. [Concurrent runs skew results](https://github.com/GoogleChrome/lighthouse/blob/main/docs/variability.md) due to resource contention.

</warning>

### Assertion Syntax

```js
const config10 = {
  assertions: {
    // Boolean pass/fail
    'audit-id': 'error',

    // Score threshold
    // 'audit-id': ['error', { minScore: 0.9 }],

    // Numeric threshold
    // 'audit-id': ['warn', { maxNumericValue: 1000 }],

    // Both score and numeric
    // 'audit-id': ['error', {
    //   minScore: 0.8,
    //   maxNumericValue: 2000,
    // }],

    // Custom aggregation
    // 'audit-id': ['error', {
    //   maxNumericValue: 2000,
    //   aggregationMethod: 'pessimistic',
    // }],
  }
}
```

For detailed budget examples, see [Performance Budgets](/learn-lighthouse/lighthouse-ci/budgets).

## Upload Options

The `upload` configuration controls where Lighthouse CI stores audit results.

### Temporary Public Storage

Free temporary storage hosted by Google (7 days retention):

```js
const config11 = {
  ci: {
    upload: {
      target: 'temporary-public-storage',
    },
  },
}
```

Returns a public URL to view results.

### LHCI Server

Upload to your own Lighthouse CI server:

```js
const config12 = {
  ci: {
    upload: {
      target: 'lhci',
      serverBaseUrl: 'https://lhci.example.com',
      token: process.env.LHCI_TOKEN, // Build token from server

      // Optional: ignore status code failures
      ignoreDuplicateBuildFailure: true,
    },
  },
}
```

See [LHCI Server Setup](/learn-lighthouse/lighthouse-ci/server) for server configuration.

### Filesystem

Save results to local files:

```js
const config13 = {
  ci: {
    upload: {
      target: 'filesystem',
      outputDir: './lhci-reports',

      // Optional: report formats
      reportFilenamePattern: '%%PATHNAME%%-%%DATETIME%%-report.%%EXTENSION%%',
    },
  },
}
```

### Multiple Targets

Upload to multiple destinations:

```js
const config14 = {
  ci: {
    upload: {
      target: ['lhci', 'filesystem'],
      serverBaseUrl: 'https://lhci.example.com',
      token: process.env.LHCI_TOKEN,
      outputDir: './lhci-reports',
    },
  },
}
```

## Server Options

Configuration for running your own LHCI server.

### Basic Server

```js
const config15 = {
  ci: {
    server: {
      port: 9001,
      storage: {
        sqlDialect: 'SQLite',
        sqlDatabasePath: './lhci.db',
      },
    },
  },
}
```

### PostgreSQL Storage

```js
const config16 = {
  ci: {
    server: {
      port: 9001,
      storage: {
        sqlDialect: 'postgres',
        sqlConnectionUrl: 'postgresql://user:pass@localhost:5432/lhci',

        // Optional: SSL configuration
        sqlConnectionSsl: true,
        sqlDialectOptions: {
          ssl: {
            rejectUnauthorized: false,
          },
        },
      },
    },
  },
}
```

### MySQL Storage

```js
const config17 = {
  ci: {
    server: {
      port: 9001,
      storage: {
        sqlDialect: 'MySQL',
        sqlConnectionUrl: 'mysql://user:pass@localhost:3306/lhci',
      },
    },
  },
}
```

### Basic Authentication

```js
const config18 = {
  ci: {
    server: {
      port: 9001,
      basicAuth: {
        username: 'admin',
        password: process.env.LHCI_ADMIN_PASSWORD,
      },
      storage: {
        sqlDialect: 'SQLite',
        sqlDatabasePath: './lhci.db',
      },
    },
  },
}
```

## Build Context

Lighthouse CI can automatically detect CI environment information. Override or supplement with environment variables:

```bash
# Git branch
LHCI_BUILD_CONTEXT__CURRENT_BRANCH=main

# Commit hash
LHCI_BUILD_CONTEXT__COMMIT_SHA=abc123

# Commit message
LHCI_BUILD_CONTEXT__COMMIT_MESSAGE="feat: add new feature"

# Author information
LHCI_BUILD_CONTEXT__AUTHOR=user@example.com

# Avatar URL
LHCI_BUILD_CONTEXT__AVATAR_URL=https://github.com/user.png

# PR or build number
LHCI_BUILD_CONTEXT__EXTERNAL_BUILD_URL=https://github.com/org/repo/pull/123

# GitHub repository slug
LHCI_BUILD_CONTEXT__GITHUB_REPO_SLUG=org/repo
```

Auto-detected in:

- GitHub Actions
- Travis CI
- CircleCI
- GitLab CI
- Jenkins
- AppVeyor
- Azure Pipelines

## Configuration Examples

### Single Page App

```js
const config19 = {
  ci: {
    collect: {
      staticDistDir: './build',
      URL: ['http://localhost/index.html'],
      numberOfRuns: 5,
    },
    assert: {
      preset: 'lighthouse:no-pwa',
      assertions: {
        'categories:performance': ['error', { minScore: 0.9 }],
        'first-contentful-paint': ['error', { maxNumericValue: 2000 }],
        'speed-index': ['error', { maxNumericValue: 3000 }],
      },
    },
    upload: {
      target: 'temporary-public-storage',
    },
  },
}
```

These assertions measure initial load speed. For optimization strategies, see the [FCP](/glossary/fcp) and [Speed Index](/glossary/speed-index) definitions.

### Multi-Page Site

```js
const config20 = {
  ci: {
    collect: {
      startServerCommand: 'npm run serve',
      URL: [
        'http://localhost:8080/',
        'http://localhost:8080/products',
        'http://localhost:8080/about',
        'http://localhost:8080/contact',
      ],
      numberOfRuns: 3,
      settings: {
        preset: 'desktop',
      },
    },
    assert: {
      preset: 'lighthouse:recommended',
      assertions: {
        'categories:performance': ['warn', { minScore: 0.85 }],
        'categories:accessibility': ['error', { minScore: 0.95 }],
        'categories:SEO': ['error', { minScore: 1 }],
      },
    },
    upload: {
      target: 'lhci',
      serverBaseUrl: process.env.LHCI_SERVER_URL,
      token: process.env.LHCI_TOKEN,
    },
  },
}
```

### Production Site Monitoring

```js
const config21 = {
  ci: {
    collect: {
      URL: ['https://example.com/'],
      numberOfRuns: 5,
      settings: {
        preset: 'desktop',
        throttling: {
          rttMs: 40,
          throughputKbps: 10240,
          cpuSlowdownMultiplier: 1,
        },
      },
    },
    assert: {
      assertions: {
        'categories:performance': ['error', { minScore: 0.95 }],
        'first-contentful-paint': ['error', { maxNumericValue: 1500 }],
        'largest-contentful-paint': ['error', { maxNumericValue: 2000 }],
        'cumulative-layout-shift': ['error', { maxNumericValue: 0.05 }],
        'total-blocking-time': ['error', { maxNumericValue: 200 }],
      },
      aggregationMethod: 'pessimistic',
    },
    upload: {
      target: ['lhci', 'filesystem'],
      serverBaseUrl: process.env.LHCI_SERVER_URL,
      token: process.env.LHCI_TOKEN,
      outputDir: './reports',
    },
  },
}
```

Strict production budgets require optimization across all [Core Web Vitals](/learn-lighthouse/core-web-vitals). Target values: [LCP](/learn-lighthouse/lcp) under 2.5s, [CLS](/learn-lighthouse/cls) under 0.1, [TBT](/glossary/tbt) under 200ms.

### Authenticated Pages

```js
// lighthouserc.js
const config22 = {
  ci: {
    collect: {
      URL: [
        'http://localhost:3000/dashboard',
        'http://localhost:3000/profile',
      ],
      startServerCommand: 'npm start',
      puppeteerScript: './scripts/login.js',
      numberOfRuns: 3,
    },
    assert: {
      preset: 'lighthouse:recommended',
    },
    upload: {
      target: 'temporary-public-storage',
    },
  },
}
```

```js
// scripts/login.js
export default async (browser, context) => {
  const page = await browser.newPage()
  await page.goto('http://localhost:3000/login')
  await page.type('#email', 'test@example.com')
  await page.type('#password', 'password123')
  await page.click('button[type="submit"]')
  await page.waitForNavigation()
}
```

## CI Integration

### GitHub Actions

```yaml
- name: Run Lighthouse CI
  run: |
    [npm](https://npmjs.com) install -g @lhci/cli
    lhci autorun
  env:
    LHCI_GITHUB_APP_TOKEN: ${{ secrets.LHCI_GITHUB_APP_TOKEN }}
    LHCI_TOKEN: ${{ secrets.LHCI_TOKEN }}
```

See [GitHub Actions Integration](/learn-lighthouse/lighthouse-ci/github-actions).

### GitLab CI

```yaml
lighthouse:
  script:
    - npm install -g @lhci/cli
    - lhci autorun
  variables:
    LHCI_TOKEN: $LHCI_TOKEN
```

See [GitLab CI Integration](/learn-lighthouse/lighthouse-ci/gitlab-ci).

## Next Steps

- [Performance Budgets](/learn-lighthouse/lighthouse-ci/budgets) - Deep look at assertion strategies
- [LHCI Server Setup](/learn-lighthouse/lighthouse-ci/server) - Self-host result storage
- [GitHub Actions](/learn-lighthouse/lighthouse-ci/github-actions) - CI/CD integration
- [GitLab CI](/learn-lighthouse/lighthouse-ci/gitlab-ci) - [GitLab](https://gitlab.com) integration
