---
title: "Authentication for Lighthouse Scans · Unlighthouse"
meta:
  "og:description": "Scan password-protected websites with Unlighthouse. Configure basic auth, cookies, headers, localStorage, and programmatic login flows."
  "og:title": "Authentication for Lighthouse Scans · Unlighthouse"
  description: "Scan password-protected websites with Unlighthouse. Configure basic auth, cookies, headers, localStorage, and programmatic login flows."
---

**Guides**

# **Authentication for Lighthouse Scans**

[Copy for LLMs](https://unlighthouse.dev/guide/guides/authentication.md)

Need to scan pages behind a login? Unlighthouse supports every common auth pattern. Find yours below.

## [Quick Reference](#quick-reference)

| **Auth Type** | **Best For** | **Config Key** |
| --- | --- | --- |
| Basic Auth | Staging environments with HTTP basic auth | `auth` |
| Cookies | Session tokens, JWTs in cookies | `cookies` |
| Headers | Bearer tokens, API keys | `extraHeaders` |
| localStorage | SPAs storing tokens in localStorage | `localStorage` |
| Programmatic | Complex login flows, 2FA | `hooks.authenticate` |

## [Basic Auth](#basic-auth)

For sites using HTTP Basic Authentication (the browser popup):

```
export default defineUnlighthouseConfig({
  auth: {
    username: process.env.AUTH_USER,
    password: process.env.AUTH_PASS,
  },
})
```

Or via CLI:

```
unlighthouse --site staging.example.com --auth admin:secretpass
```

## [Cookies](#cookies)

Most common for session-based auth. Grab your session cookie from browser DevTools (Application → Cookies):

```
export default defineUnlighthouseConfig({
  cookies: [
    {
      name: 'session_id',
      value: 'abc123...',
      domain: 'example.com', // Must match your site
      path: '/',
    },
  ],
})
```

**Getting the cookie value:**

1. Log into your site in Chrome
2. Open DevTools → Application → Cookies
3. Copy the session cookie value
4. Paste into config (or use environment variable)

CLI shorthand:

```
unlighthouse --site example.com --cookies "session_id=abc123"

# Multiple cookies
unlighthouse --site example.com --cookies "session_id=abc123;csrf_token=xyz789"
```

## [Headers (Bearer Tokens, API Keys)](#headers-bearer-tokens-api-keys)

For APIs or sites expecting `Authorization` headers:

```
export default defineUnlighthouseConfig({
  extraHeaders: {
    Authorization: \`Bearer ${process.env.API_TOKEN}\`,
  },
})
```

CLI:

```
unlighthouse --site api.example.com --extra-headers "Authorization:Bearer abc123"
```

## [Query Params](#query-params)

Some staging environments use URL tokens:

```
export default defineUnlighthouseConfig({
  defaultQueryParams: {
    access_token: process.env.STAGING_TOKEN,
  },
})
```

Every scanned URL will include `?access_token=...`

## [localStorage (SPAs)](#localstorage-spas)

For React/Vue/Angular apps storing auth tokens in localStorage:

```
export default defineUnlighthouseConfig({
  localStorage: {
    auth_token: process.env.AUTH_TOKEN,
    user_id: '12345',
  },
})
```

Unlighthouse sets these before each page loads.

## [Programmatic Login (Complex Flows)](#programmatic-login-complex-flows)

For login forms, OAuth flows, or anything the simpler methods can't handle:

```
export default defineUnlighthouseConfig({
  hooks: {
    async authenticate({ page }) {
      // Navigate to login
      await page.goto('https://example.com/login')

      // Fill form
      await page.type('input[name="email"]', 'test@example.com')
      await page.type('input[name="password"]', process.env.PASSWORD)

      // Submit and wait for redirect
      await Promise.all([
        page.click('button[type="submit"]'),
        page.waitForNavigation(),
      ])
    },
  },
})
```

This runs once before scanning starts. The session persists for all pages.

## [Auth Not Sticking?](#auth-not-sticking)

If authentication isn't persisting between page scans:

```
export default defineUnlighthouseConfig({
  puppeteerOptions: {
    userDataDir: './.unlighthouse-session', // Persist browser data
  },
  lighthouseOptions: {
    disableStorageReset: true, // Don't clear storage between pages
    skipAboutBlank: true,
  },
})
```

## [Debugging Auth Issues](#debugging-auth-issues)

Can't tell if auth is working? Watch it happen:

```
export default defineUnlighthouseConfig({
  debug: true,
  puppeteerOptions: {
    headless: false, // See the browser
    slowMo: 100, // Slow it down
  },
  puppeteerClusterOptions: {
    maxConcurrency: 1, // One at a time
  },
})
```

Now you can watch the browser and see exactly where auth fails.

See the [**Debugging Guide**](https://unlighthouse.dev/guide/guides/debugging) for more techniques.

[Edit this page](https://github.com/harlan-zw/unlighthouse/edit/main/docs/1.guide/guides/authentication.md)

[Markdown For LLMs](https://unlighthouse.dev/guide/guides/authentication.md)

**Did this page help you? **

Anything that could be done better? :)

Help us improve this page. You can [edit this page](https://github.com/harlan-zw/unlighthouse/edit/main/docs/1.guide/guides/authentication.md) on GitHub or provide anonymous feedback below.

[**Debugging** Debug and troubleshoot Unlighthouse scans using logging, browser inspection, and diagnostic tools.](https://unlighthouse.dev/guide/guides/debugging) [**Chrome Dependency** Configure Chrome browser settings for Unlighthouse scanning, including system Chrome usage and custom installations.](https://unlighthouse.dev/guide/guides/chrome-dependency)

**On this page **

- [Quick Reference](#quick-reference)
- [Basic Auth](#basic-auth)
- [Cookies](#cookies)
- [Headers (Bearer Tokens, API Keys)](#headers-bearer-tokens-api-keys)
- [Query Params](#query-params)
- [localStorage (SPAs)](#localstorage-spas)
- [Programmatic Login (Complex Flows)](#programmatic-login-complex-flows)
- [Auth Not Sticking?](#auth-not-sticking)
- [Debugging Auth Issues](#debugging-auth-issues)