Guides

Authentication for Lighthouse Scans

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

Quick Reference

Auth TypeBest ForConfig Key
Basic AuthStaging environments with HTTP basic authauth
CookiesSession tokens, JWTs in cookiescookies
HeadersBearer tokens, API keysextraHeaders
localStorageSPAs storing tokens in localStoragelocalStorage
ProgrammaticComplex login flows, 2FAhooks.authenticate

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

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)

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

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)

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)

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?

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

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 for more techniques.

Did this page help you?