How to Run Lighthouse Audits with Puppeteer and GitHub Actions CI
What if you could automatically run Lighthouse audits for pages after login — not just for your public site?
If you’re working on web apps, you know most critical journeys are behind authentication. This guide shows you how to combine Puppeteer and Lighthouse, automate login, and run full performance audits — all in your CI/CD pipeline with GitHub Actions!
Why Do This?
- Lighthouse is great — but limited to public pages by default.
- Many bugs and slowdowns happen after login: dashboards, user portals, and more.
- Using Puppeteer, you can automate any browser action (like logging in), then run Lighthouse on the actual logged-in experience.
What You’ll Build
- A simple HTML login demo app
- A Node.js script to automate login and trigger Lighthouse
- A GitHub Actions CI workflow to run audits on every push or PR
🧑💻 Step 1: Build a Minimal Test App
Create these two files in your repo:
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login Demo</title>
</head>
<body>
<h2>Login Page</h2>
<form id="login-form" action="home.html" method="get">
<label>Username: <input type="text" name="username" id="username" required></label><br>
<label>Password: <input type="password" name="password" id="password" required></label><br>
<button type="submit" id="login-btn">Login</button>
</form>
</body>
</html>home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home Page</title>
</head>
<body>
<h2>Welcome Home!</h2>
<p>You are now logged in.</p>
</body>
</html>Tip: These files simulate login flow; you can extend with your real app and selectors later.
🚀 Step 2: Write a Puppeteer + Lighthouse Script
Save this as login-lighthouse.mjs:
import puppeteer from 'puppeteer';
import lighthouse from 'lighthouse';
import fs from 'fs';
const LOGIN_URL = 'http://localhost:8080/login.html';
const browser = await puppeteer.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--remote-debugging-port=9222'
],
defaultViewport: { width: 1280, height: 900 }
});
const page = await browser.newPage();
await page.goto(LOGIN_URL, { waitUntil: 'networkidle0' });
await page.type('#username', 'demo');
await page.type('#password', 'demo123');
await Promise.all([
page.click('#login-btn'),
page.waitForNavigation({ waitUntil: 'networkidle0' })
]);
console.log('Current page URL after login:', await page.url());
if (!(await page.url()).includes('home.html')) {
console.error('Login did not redirect to home.html!');
await browser.close();
process.exit(1);
}
const { lhr, report } = await lighthouse(page.url(), {
port: 9222,
output: 'html',
onlyCategories: ['performance', 'accessibility', 'best-practices', 'seo'],
});
fs.writeFileSync('home-lighthouse-report.html', report);
console.log(`Lighthouse Performance Score: ${lhr.categories.performance.score * 100}`);
console.log('Lighthouse report saved as home-lighthouse-report.html');
await browser.close();🏃 Step 3: Test Locally
Install dependencies:
npm install puppeteer lighthouse serveStart the static server:
npx serve . -l 8080Run your script:
node login-lighthouse.mjsYou should see the login automation, and a file home-lighthouse-report.html generated in your project folder!
🤖 Step 4: Automate with GitHub Actions CI
Create .github/workflows/lighthouse-ci.yml in your repo:
name: Lighthouse Home Page Audit
on:
push:
branches: [main]
pull_request:
jobs:
lighthouse-test:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 18
- name: Install dependencies
run: |
npm install puppeteer lighthouse serve
- name: Start local server
run: |
npx serve . -l 8080 > server.log 2>&1 &
sleep 3
- name: Run Lighthouse directly on home page
run: npx lighthouse http://localhost:8080/home.html --output html --output-path=home-lighthouse-report.html --chrome-flags="--headless=new --no-sandbox --disable-gpu --disable-dev-shm-usage"
- name: List files for debug
run: ls -l
- name: Upload Lighthouse report
uses: actions/upload-artifact@v4
with:
name: lighthouse-report
path: home-lighthouse-report.htmlKey points:
- Headless flags make Chrome work in CI!
- Artifact upload makes your report downloadable from the Actions UI.
🎯 Step 5: See It in Action
- Push to GitHub (main or PR).
- GitHub Actions will:
- Spin up a Node environment
- Serve your static app
- Run Lighthouse in headless mode
- Upload the HTML report as an artifact
Go to the Actions tab in your repo, pick the workflow run, and download your lighthouse-report artifact for the results.
💡 Tips & Extensions
- Test real apps: Swap out HTML and selectors for your production app and login workflow.
- Audit multiple flows: Repeat the process for each page or flow you want.
- Fail builds for low scores: Parse the Lighthouse JSON and fail if performance drops!
- Send reports to Slack, Teams, or email: Artifacts can be sent or visualized as part of your team’s workflow.
🏁 Conclusion
With this setup, you can run Lighthouse audits on any part of your app — including private, authenticated states — and automate it in CI with every push or PR.
Now, your team can catch performance or accessibility regressions before they hit production!
Resources
If you enjoyed this, follow me for more on testing, APIs, CI/CD, and dev automation!
I have created a project on GitHub and added the code here.
Feel free to hit clap if you like the content. Happy Automation Testing :) Cheers. 👏
If you’d like to support my work, please leave a good rating for my Chrome plugin here and my Firefox plugin here.
I have created a test automation framework for API and UI for the QA community. If you found this helpful, leave a ⭐ on GitHub or try contributing to any feature.
