This guide walks you through using k6’s browser testing capabilities to automate and load-test web applications in a real Chromium browser. You’ll learn how to set up the environment, write a browser test script, run it, and interpret the results, including how to handle common pitfalls.
What You’ll Need
- k6 installed – Download and install the latest k6 binary from the official website or via your package manager (e.g.,
brew install k6on macOS,choco install k6on Windows). - Node.js (optional) – Only if you plan to use the k6 Studio or the experimental browser module with a bundler. For the standard approach, k6’s built-in browser module works without Node.
- A test website – Use a public site like
https://test.k6.ioor your own local development server. - Basic JavaScript knowledge – k6 scripts are written in JavaScript, so familiarity with async/await and selectors is helpful.
Step-by-Step
- Create a new JavaScript file for your test, e.g.,
browser-test.js. This is where you’ll write the browser automation and load test logic. - Import the browser module at the top of your script:
import { browser } from 'k6/experimental/browser';This module provides a Playwright-like API for controlling Chromium.
- Define the test options – Configure the load profile and browser-specific settings. For example:
export const options = { scenarios: { ui: { executor: 'shared-iterations', options: { browser: { type: 'chromium', }, }, exec: 'browserTest', vus: 1, iterations: 1, }, }, };Here,
vusanditerationscontrol the number of virtual users and how many times each runs. For browser testing, start with 1 VU and 1 iteration to validate the script. - Write the browser test function – Create a function (e.g.,
browserTest) that uses thebrowserobject to open a page, interact with elements, and assert behavior. A minimal example:export async function browserTest() { const page = await browser.newPage(); try { await page.goto('https://test.k6.io'); await page.waitForSelector('h1'); console.log('Page title:', await page.title()); } finally { await page.close(); } }The
try/finallyensures the page is closed even if an assertion fails. - Add interactions and assertions – Use Playwright-style methods like
page.click(),page.fill(), andpage.waitForNavigation(). For example, to fill a form and submit:await page.fill('#username', 'testuser'); await page.fill('#password', 'secret'); await Promise.all([ page.waitForNavigation(), page.click('button[type="submit"]'), ]);Always wait for navigation after a click that triggers a page load.
- Run the test – Execute the script with the command:
k6 run browser-test.jsk6 will launch a headless Chromium browser, run your script, and output metrics to the terminal.
- View the results – After the run, k6 prints summary metrics like
browser_http_req_duration(request latency) andbrowser_web_vital_fcp(First Contentful Paint). These help you assess performance. For a detailed report, you can output to JSON or use k6 Cloud.
Common Mistakes
- Not closing pages – Leaving pages open can cause memory leaks and affect test results. Always use
try/finallyorpage.close(). - Using incorrect selectors – Overly brittle selectors (e.g., CSS paths with dynamic IDs) break easily. Prefer stable attributes like
data-testidor text-based selectors. - Ignoring wait conditions – Failing to wait for elements to appear before interacting leads to flaky tests. Use
waitForSelector()orwaitForNavigation(). - Setting too many VUs – Running many concurrent browser instances consumes significant CPU and memory. Start with 1–2 VUs, then scale up gradually.
- Mixing browser and non-browser code – The browser module cannot be used in the same iteration as regular HTTP requests without careful setup. Keep browser scenarios separate.
Tips
- Use the browser recorder – k6 Studio (formerly k6 Recorder) can generate a script from your interactions in a real browser. This saves time and provides a solid starting point.
- Leverage environment variables – For credentials or URLs, use
__ENVto avoid hardcoding sensitive data:const url = __ENV.BASE_URL || 'https://test.k6.io'; - Add thresholds – Define pass/fail criteria in
options.thresholds, e.g.,thresholds: { 'browser_web_vital_fcp': ['p(95) < 2500'] }to fail the test if the 95th percentile FCP exceeds 2.5 seconds. - Run locally first – Always test with a single VU to ensure the script is stable before running a full load test.
- Check the official examples – The k6 documentation has a repository of browser test examples covering common scenarios like login flows and single-page apps.
Troubleshooting
- Browser not launching – Ensure you have the latest k6 version (browser support is experimental but stable in recent releases). If you're on Linux, you may need to install Chromium dependencies:
sudo apt-get install -y chromium-browseror equivalent. - Script fails with 'browser is not defined' – This usually means you're trying to use the browser module outside a browser scenario. Make sure your function is referenced in the
execfield of a scenario withtype: 'chromium'. - Timeout errors on
page.goto()– Increase the default timeout by passing options:await page.goto(url, { timeout: 60000 }). Also check network connectivity and that the site is accessible. - Element not found even though it exists – The element may be inside an iframe or shadow DOM. Use
page.frames()to switch to the correct frame, or usepage.$(selector)with a shadow-piercing selector if supported. - Memory usage spikes – Close pages after each iteration and consider reducing the number of VUs. Also, avoid taking screenshots in every iteration unless needed.
Frequently Asked Questions
Do I need to install a separate browser?
No, k6 with the browser module downloads and manages its own Chromium instance automatically. You don't need to install Chrome or Chromium separately.
Can I use k6 browser testing for load testing with many virtual users?
Yes, but each VU runs a full browser instance, which is resource-intensive. For realistic load testing, it's common to use a few browser VUs for critical user journeys and supplement with protocol-level VUs (HTTP requests) for scale.
How do I take a screenshot or record video?
Use page.screenshot({ path: 'screenshot.png' }) for a screenshot. For video, you need to set recordVideo: { dir: 'videos' } in the browser scenario options.
What metrics does k6 browser testing provide?
It provides browser-specific metrics like browser_http_req_duration (HTTP request latency), browser_web_vital_fcp (First Contentful Paint), browser_web_vital_lcp (Largest Contentful Paint), and browser_web_vital_cls (Cumulative Layout Shift).
Can I use k6 browser testing for single-page applications (SPAs)?
Yes, the browser module supports client-side routing. Use page.waitForNavigation() or page.waitForSelector() after clicking links or buttons that change the view without a full page reload.
Is the browser module stable for production use?
As of the latest k6 releases, the browser module is considered stable enough for most testing scenarios, but it's still marked as 'experimental' in the import path. Always test on your target site and keep k6 updated.
Related
General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.
More in this bed
- How to Cool Down an Overheating Laptop
- Good Password: How to Create One
- Remove Write Protection on External Hard Drive
- How to Disable Chkdsk at Windows Startup
- Restore WiFi and Secure Your Netgear Router After Reset
- Fix Error 0x80004005: Top Easy Ways That Work