---
schema_version: 1
route: /t/k6.md
tool: "k6"
---

# sincecutoff.com /t/k6 — k6

- name: k6
- kind: cli
- children: none
- homepage: <https://github.com/grafana/k6>

Changes to the tools coding agents drive, since a model's training cutoff, each linked to its first-party source. Check installed versions and limitations before acting; a cutoff date does not establish what a model knows.
Original editorial content: [Apache 2.0](https://sincecutoff.com/v1/data-license.txt), by [0xPatrick](https://0xpatrick.dev). Preserve applicable license and [NOTICE](https://sincecutoff.com/notice.txt) attribution when redistributing. Third-party source text and examples retain their own rights. [License scope and attribution](https://sincecutoff.com/v1/license.json).
To stay current, read the changes feed: [`/v1/changes.md?tool=k6`](https://sincecutoff.com/v1/changes.md?tool=k6) (or `.json`), adding `since=YYYY-MM-DD` for your training cutoff. Entries for registered children are included; the registry itself is `/v1/tools.json`. How to page and save your place: [llms.txt](https://sincecutoff.com/llms.txt).

### k6 group() preserves metric context across asynchronous calls (2026-09-21)
- slug: k6-group-preserves-metric-context-across-asynchronous-calls-723b94082eb6
- score: 0.96

How to use it:

When an asynchronous test flow needs requests and checks to remain in one group across `await`, run it with the experimental `async-metric-context` feature and use an async `group()` callback. `group_duration` then measures until the callback’s returned promise settles.

Examples:

```
k6 run --features async-metric-context <script.js>
```

```
import { check, group } from 'k6';
import http from 'k6/http';

export default async function () {
  await group('browse', async () => {
    const response = await http.asyncRequest('GET', 'https://test.k6.io/');
    check(response, { 'page loaded': (r) => r.status === 200 });
    await http.asyncRequest('GET', 'https://test.k6.io/contacts.php');
  });
}
```

- why_it_matters: When debugging an asynchronous test flow, keep its requests and checks grouped across awaited calls.
- before: `group()` rejected async functions by default, and promise callbacks could lose the group tag.
- sources: <https://github.com/grafana/k6/releases/tag/v2.3.0>, <https://grafana.com/docs/k6/latest/javascript-api/k6/group/>, <https://grafana.com/docs/k6/latest/javascript-api/k6-http/>
- gotchas: "Version: v2.3.0"; "Availability: experimental; enable the `async-metric-context` feature"; "--features async-metric-context: Enables the experimental feature that permits async `group()` callbacks and propagates metric tags and metadata to asynchronous work. Required to use async callbacks in `group()`; the docs also allow enabling it with `K6_FEATURES=async-metric-context`."; "group(name, fn): name (required): String name of the group."; "group(name, fn): fn (required): Function containing the group body; with the feature enabled it may be async or return a Promise-like value."; "http.asyncRequest(method, url): method (required): Uppercase HTTP method, such as `GET`."; "http.asyncRequest(method, url): url (required): HTTP request URL."; "Prerequisite: Enable the experimental, opt-in `async-metric-context` feature using `--features async-metric-context` or `K6_FEATURES=async-metric-context`."; "Changes inside a group or callback stay local to that work and its asynchronous descendants instead of leaking into unrelated work."; "Custom tags and metadata are preserved across promises, timer callbacks, `k6/websockets` listeners, and gRPC stream listeners."

### k6 JavaScript adds byte, Set, and raw JSON built-ins (2026-09-21)
- slug: k6-javascript-adds-byte-set-and-raw-json-built-ins-6b42457c663f
- score: 0.95

How to use it:

When preparing binary test data or checking response fields, use the documented `Uint8Array` conversions and `Set` operations. To serialize an exact numeric JSON value, pass its decimal text to `JSON.rawJSON()` before `JSON.stringify()`; k6 v2.3.0 release notes document these examples.

Examples:

```
const bytes = Uint8Array.fromHex('6b36');
console.log(bytes.toBase64()); // azY=
```

```
const expected = new Set(['id', 'name', 'email']);
const received = new Set(['id', 'name']);
console.log([...expected.difference(received)]); // ["email"]
```

```
JSON.stringify({ id: JSON.rawJSON('9007199254740993') });
// '{"id":9007199254740993}'
```

- why_it_matters: When writing test data or response assertions, encode binary values, compare sets, or preserve an exact numeric JSON value.
- sources: <https://github.com/grafana/k6/releases/tag/v2.3.0>
- gotchas: "Version: v2.3.0"; "Uint8Array.fromHex(hex) (required): Creates byte data from a hex string; the release example uses `'6b36'`."; "Uint8Array.prototype.toBase64() (required): Converts `Uint8Array` data to base64."; "Set.prototype.difference(other) (required): Returns the set difference; the example finds expected fields absent from the received set."; "Set.prototype.intersection(other): Set operation named in the release notes; parameter details are not stated there."; "Set.prototype.union(other): Set operation named in the release notes; parameter details are not stated there."; "JSON.rawJSON(text) (required): Creates a raw JSON value; the example passes numeric text so it serializes without rounding through a JavaScript `Number`."

### k6 --once runs the configured scenario once (2026-09-21)
- slug: k6-once-runs-the-configured-scenario-once-04c5aa3dee49
- score: 0.98

How to use it:

When debugging a script with at most one configured scenario, run `k6 run --once script.js` to execute its function once with one VU and one iteration while preserving scenario settings, including browser settings.

Examples:

```
k6 run --once <script.js>
```

- why_it_matters: When debugging a script with one configured scenario, run its function once while retaining its browser configuration.
- before: Shortcuts such as `--vus 1 --iterations 1` replaced the script’s scenarios with a default scenario, potentially discarding the selected function and browser options.
- sources: <https://github.com/grafana/k6/releases/tag/v2.3.0>, <https://grafana.com/docs/k6/v2.3.x/using-k6/k6-options/reference/>
- gotchas: "Version: v2.3.0"; "--once (required): Runs one iteration with one VU. For one configured scenario, uses `shared-iterations` and preserves its function and settings; executor timing defaults are applied."; "<script.js> (required): Path to the script to run."; "Supports scripts with at most one scenario."

### k6 Prometheus remote write adds static labels (2026-09-21)
- slug: k6-prometheus-remote-write-adds-static-labels-a13f5889146d
- score: 0.98

How to use it:

When multiple k6 processes send metrics to the same Prometheus endpoint, set `K6_PROMETHEUS_RW_LABELS` to comma-separated `key=value` labels and run with `--out experimental-prometheus-rw` so each process's time series can be distinguished.

Examples:

```
K6_PROMETHEUS_RW_LABELS="environment=production,server=srv1" k6 run --out experimental-prometheus-rw <script.js>
```

- why_it_matters: When running tests from multiple k6 instances that send metrics to the same Prometheus server, label each instance's time series.
- sources: <https://github.com/grafana/k6/releases/tag/v2.3.0>, <https://grafana.com/docs/k6/latest/results-output/real-time/prometheus-remote-write/>
- gotchas: "Version: v2.3.0"; "K6_PROMETHEUS_RW_LABELS: Comma-separated `key=value` pairs of static labels for remote-write time series; defaults to no additional labels."; "--out experimental-prometheus-rw (required): Selects the Prometheus remote write output for the k6 run."; "<script.js> (required): Path to the k6 test script; the docs use `script.js` as the example."; "Prerequisite: Set up a running Prometheus remote-write endpoint and ensure k6 can reach it. For Prometheus 2.x, enable `--web.enable-remote-write-receiver`."; "Prerequisite: The Prometheus remote-write output is experimental."

### k6 run --scenario selects configured workloads (2026-09-21)
- slug: k6-run-scenario-selects-configured-workloads-df5a3289e89c
- score: 0.98

How to use it:

When debugging a script with multiple configured scenarios, run `k6 run --scenario <name> <script.js>` to run only the named workload. Separate multiple scenario names with commas.

Examples:

```
k6 run --scenario homepage script.js
```

```
k6 run --scenario homepage,contacts script.js
```

- why_it_matters: When editing or debugging a script with multiple scenarios, run only the workload under development.
- before: Without `--scenario`, k6 runs all configured scenarios. The release note describes environment-variable selection code or splitting scripts as prior workarounds.
- sources: <https://github.com/grafana/k6/releases/tag/v2.3.0>, <https://grafana.com/docs/k6/v2.3.x/using-k6/scenarios/#run-selected-scenarios>
- gotchas: "Version: v2.3.0"; "--scenario <name>[,<name>...]: Select one or more configured scenarios by name; separate names with commas. Without it, all configured scenarios run. Names must match the configured scenarios."; "<script.js> (required): Script containing the configured scenarios."; "--vus: Load shortcut; cannot be combined with `--scenario`."; "--duration: Load shortcut; cannot be combined with `--scenario`."; "Prerequisite: Use k6 v2.3.0 or later, where `--scenario` was introduced."; "Prerequisite: The script must configure the scenario name or names in its `scenarios` object."; "Scenario names must match configured scenarios."; "Load shortcuts such as `--vus` and `--duration` cannot be combined with selection; configure workload in each scenario instead."; "Selected scenarios retain their executor, load, timing, function, environment, tags, and browser options."; "Without `--scenario`, k6 runs all configured scenarios."; "k6 warns and skips thresholds tagged for configured scenarios that are excluded, while keeping global thresholds and other filters."

### k6 tlsAIAFetch retrieves missing TLS certificates (2026-09-21)
- slug: k6-tlsaiafetch-retrieves-missing-tls-certificates-32cee8d158cf
- score: 0.96

How to use it:

If an HTTPS test fails because the server omits an intermediate certificate, set `tlsAIAFetch: true` in the k6 options to fetch it while verifying the TLS chain.

Examples:

```
export const options = {
  tlsAIAFetch: true,
};
```

- why_it_matters: When debugging an HTTPS test that fails because a server omits an intermediate certificate, configure k6 to fetch the missing certificate.
- sources: <https://github.com/grafana/k6/releases/tag/v2.3.0>, <https://grafana.com/docs/k6/latest/using-k6/k6-options/reference/>
- gotchas: "Version: v2.3.0"; "tlsAIAFetch: Boolean; defaults to `false`. When enabled, follows the certificate’s AIA extension to fetch missing intermediate CA certificates over HTTP. Has no effect when `insecureSkipTLSVerify` is enabled."; "Prerequisite: Introduced in k6 v2.3.0; opt-in."; "Opt-in; works with HTTP and gRPC connections."

### k6 WebSocket exposes ready-state constants (2026-09-21)
- slug: k6-websocket-exposes-ready-state-constants-649fac4310e3
- score: 0.91

How to use it:

When reviewing WebSocket message handling, check the socket state before sending. Send only when `socket.readyState === WebSocket.OPEN`; `OPEN` means the connection is ready to communicate.

Examples:

```
if (socket.readyState === WebSocket.OPEN) {
  socket.send('hello');
}
```

- why_it_matters: When reviewing WebSocket message handling, check a socket's state before sending a message.
- sources: <https://github.com/grafana/k6/releases/tag/v2.3.0>, <https://github.com/grafana/k6/blob/v2.3.0/release%20notes/v2.3.0.md>, <https://grafana.com/docs/k6/latest/javascript-api/k6-websockets/websocket/>, <https://grafana.com/docs/k6/latest/javascript-api/k6-websockets/>
- gotchas: "Version: v2.3.0"; "socket.readyState (required): Current connection state; compare it with a ready-state constant."; "WebSocket.OPEN (required): Constant with value `1`; connection is open and ready to communicate. Constants are read-only and also available on each instance."; "socket.send(data) (required): Sends data through the WebSocket."

### k6/browser chromium.connectOverCDP() attaches to a running browser (2026-08-10)
- slug: k6-browser-chromium-connectovercdp-attaches-to-a-running-browser-9dcfde742a28
- score: 0.95

How to use it:

When a test needs to attach to an existing Chromium-based browser, pass its CDP WebSocket endpoint to `chromium.connectOverCDP()` inside the iteration and use the returned browser. k6 closes the connection at iteration end; call `browser.close()` to close it earlier.

Examples:

```
import { chromium } from 'k6/browser';

export default async function () {
  const browser = await chromium.connectOverCDP('ws://localhost:9222/devtools/browser/<BROWSER_ID>');
  const page = await browser.newPage();
  try {
    await page.goto('https://quickpizza.grafana.com/');
  } finally {
    await page.close();
    await browser.close();
  }
}
```

```
import http from 'k6/http';
import { chromium } from 'k6/browser';

export function setup() {
  const res = http.post('https://provider.example/v1/sessions');
  return { wsURL: res.json().connectUrl };
}

export default async function (data) {
  const browser = await chromium.connectOverCDP(data.wsURL);
  const page = await browser.newPage();
  try {
    await page.goto('https://quickpizza.grafana.com/');
  } finally {
    await page.close();
    await browser.close();
  }
}
```

- why_it_matters: When a browser test needs to attach to an existing Chromium-based browser, connect to its WebSocket endpoint and run the iteration against it.
- sources: <https://github.com/grafana/k6/releases/tag/v2.2.0>, <https://github.com/grafana/k6/blob/v2.2.0/release%20notes/v2.2.0.md>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/chromium/connectovercdp/>
- gotchas: "Version: v2.2.0"; "wsEndpoint (required): String containing the browser's CDP WebSocket endpoint; documentation says it must use `ws` or `wss`."; "browser.close(): Closes the connection early; k6 otherwise closes it at iteration end. Closing the connection does not stop the browser."; "Prerequisite: An existing Chromium-based browser with a CDP WebSocket endpoint. For the local example, start Chrome with `--remote-debugging-port` and read `webSocketDebuggerUrl` from `http://localhost:9222/json/version`."; "Prerequisite: The function connects within an iteration and does not require the `browser` scenario option."; "Attaches to Chromium-based browsers over the Chrome DevTools Protocol."

### k6 cloud load-zone list command (2026-08-10)
- slug: k6-cloud-load-zone-list-command-91d0dd4e6bba
- score: 0.97

How to use it:

When inspecting load zones in a configured Grafana Cloud k6 stack, run `k6 cloud load-zone list`; add `--json` for a JSON array instead of the default table.

Examples:

```
k6 cloud load-zone list
```

```
k6 cloud load-zone list --json
```

- why_it_matters: When inspecting load zones available to a configured Grafana Cloud k6 stack, list them in a human-readable or JSON format.
- sources: <https://github.com/grafana/k6/releases/tag/v2.2.0>, <https://grafana.com/docs/k6/latest/reference/cloud-commands/>
- gotchas: "Version: v2.2.0"; "--json: Output the load zone list as a JSON array; without it, output a human-readable table."; "Prerequisite: Every `k6 cloud` subcommand requires an API token and a configured stack. Authenticate with `k6 cloud login` or set `K6_CLOUD_TOKEN` and `K6_CLOUD_STACK_ID`."; "Lists public and private load zones available in the configured Grafana Cloud k6 stack."

### k6 experimental streams WritableStream and WritableStreamDefaultWriter (2026-08-10)
- slug: k6-experimental-streams-writablestream-and-writablestreamdefaultwriter-ab8ff3865bc1
- score: 0.93

How to use it:

When implementing a writable stream in k6 v2.2.0, import `WritableStream` from `k6/experimental/streams`. Create it with a `write` handler, then call `getWriter()`, `write()`, and `close()` as shown.

Examples:

```
import { WritableStream } from 'k6/experimental/streams';

export default async function () {
  const stream = new WritableStream({
    write(chunk) {
      console.log(`wrote ${chunk}`);
    },
  });

  const writer = stream.getWriter();
  await writer.write('hello');
  await writer.close();
}
```

- why_it_matters: When implementing a writable stream in a k6 script, use the experimental streams module.
- sources: <https://github.com/grafana/k6/releases/tag/v2.2.0>, <https://grafana.com/docs/k6/latest/get-started/write-your-first-test/>
- gotchas: "Version: v2.2.0"; "Availability: Experimental streams module."; "write(chunk): The example’s underlying sink handler receives a chunk and logs it. The release note does not document whether the handler is required."; "writer.write('hello') (required): Writes the `hello` chunk in the documented example."; "writer.close() (required): Closes the writer in the documented example."; "Prerequisite: Use k6 v2.2.0 or later for the release-note implementation described here; the module is experimental."; "Prerequisite: Install k6 to write and execute k6 scripts."; "Implements WritableStream and WritableStreamDefaultWriter following the WHATWG Streams specification."

### k6 TextEncoder and TextDecoder globals (2026-08-10)
- slug: k6-textencoder-and-textdecoder-globals-0a7628d52132
- score: 0.96

How to use it:

When a k6 script must encode or decode text, use the `TextEncoder` and `TextDecoder` globals directly in init or VU code. No import is required.

Examples:

```
const encoded = new TextEncoder().encode('Hello, world!');
const decoded = new TextDecoder().decode(encoded);
```

- why_it_matters: When encoding or decoding text in a k6 script, use the standard encoder and decoder globals in init or VU code.
- sources: <https://github.com/grafana/k6/releases/tag/v2.2.0>
- gotchas: "Version: v2.2.0"; "Prerequisite: Use k6 v2.2.0 or later; the release note says these globals are available in both init and VU contexts."; "Available as globals in both the init and VU contexts."

### k6 browser context proxy option (2026-06-30)
- slug: k6-browser-context-proxy-option-02e783969b7a
- score: 0.97

How to use it:

When a k6 browser script needs to route a context’s traffic through a proxy, pass `proxy` to `browser.newContext` and provide `proxy.server`.

Examples:

```
import { browser } from 'k6/browser';

export const options = {
  scenarios: {
    browser: {
      executor: 'shared-iterations',
      options: { browser: { type: 'chromium' } },
    },
  },
};

export default async function () {
  const context = await browser.newContext({
    proxy: {
      server: 'http://proxy.test:8080',
      bypass: 'localhost,127.0.0.1',
    },
  });
  const page = await context.newPage();
  try {
    await page.goto('https://test.k6.io/');
  } finally {
    await page.close();
  }
}
```

- why_it_matters: Route a browser context's traffic through a proxy while running a k6 browser script.
- before: The v2.1.0 release note says environment proxy variables affected only k6’s DevTools WebSocket connection; routing context traffic required a custom-built binary or another approach.
- sources: <https://github.com/grafana/k6/releases/tag/v2.1.0>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/newcontext/>
- gotchas: "Version: v2.1.0"; "options.proxy: Proxy settings for all pages in the context; when set, `server` is required."; "options.proxy.server (required): Proxy server URL, including scheme and port."; "options.proxy.bypass: Comma-separated hosts to connect to directly, bypassing the proxy."; "Prerequisite: The documented example configures the browser scenario with `type: 'chromium'`."; "`proxy.server` must be provided."

### k6 browser locator.isInViewport method (2026-06-30)
- slug: k6-browser-locator-isinviewport-method-27d939da2b2f
- score: 0.94

How to use it:

When a browser test should interact with an element only if it intersects the viewport, call `locator.isInViewport()` and act on its boolean result. Set `ratio` for a visibility threshold; the check measures once after attachment.

Examples:

```
const button = page.locator('button#submit');
if (await button.isInViewport()) {
  await button.click();
}
```

- why_it_matters: Check whether a browser element is visible in the viewport before interacting with it.
- sources: <https://github.com/grafana/k6/releases/tag/v2.1.0>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/locator/isinviewport/>
- gotchas: "Version: v2.1.0"; "options: Optional options object for the check."; "options.ratio: Minimum element ratio in the viewport, from 0 to 1; default 0 means any visible pixel counts."; "options.timeout: Maximum wait in milliseconds; default 30000. Set 0 to disable; BrowserContext or Page `setDefaultTimeout` overrides the default."; "The call measures the intersection once after the element attaches."

### k6 cloud test list command lists project load tests (2026-06-30)
- slug: k6-cloud-test-list-command-lists-project-load-tests-9d42844ffb73
- score: 0.97

How to use it:

When listing load tests for a Grafana Cloud k6 project, run `k6 cloud test list`; select the project with `--project-id` or configured project settings. Add `--json` for a JSON array; otherwise the command prints a human-readable table.

Examples:

```
k6 cloud test list
```

```
k6 cloud test list --project-id <project-id>
```

```
k6 cloud test list --json
```

- why_it_matters: List load tests for a Grafana Cloud k6 project.
- sources: <https://github.com/grafana/k6/releases/tag/v2.1.0>, <https://grafana.com/docs/k6/latest/reference/cloud-commands/>
- gotchas: "Version: v2.1.0"; "--project-id <project-id>: Project ID to list tests for; takes precedence over the configured project."; "K6_CLOUD_PROJECT_ID / cloud config `projectID`: Selects the project when `--project-id` is not provided."; "configured stack default project: Used when neither the flag nor configured project resolves; populated by `k6 cloud login`."; "--json: Output the test list as a JSON array; without it, output is a human-readable table."; "Prerequisite: Authenticate and configure a stack with `k6 cloud login`, or set `K6_CLOUD_TOKEN` and `K6_CLOUD_STACK_ID`; every `k6 cloud` subcommand requires an API token and configured stack."

### k6 run and cloud run support feature flags and native histograms (2026-06-30)
- slug: k6-run-and-cloud-run-support-feature-flags-and-native-histograms-76324fc7450d
- score: 0.96

How to use it:

When running a k6 script with native histograms, enable the experimental `native-histograms` feature on `k6 run` or `k6 cloud run` so it is propagated with the run. Use `k6 features` to check available flags and their lifecycle.

Examples:

```
k6 run --features native-histograms <script.js>
```

```
K6_FEATURES=native-histograms k6 run <script.js>
```

```
k6 features --json
```

- why_it_matters: Run a k6 script with experimental native histograms and ensure the flag is applied consistently wherever the run executes.
- sources: <https://github.com/grafana/k6/releases/tag/v2.1.0>
- gotchas: "Version: v2.1.0"; "Availability: `native-histograms` is experimental; feature flags are opt-in for trialing new, not-yet-stable behavior."; "--features: Enables feature flags on `k6 run` and `k6 cloud run`; accepts comma-separated or repeated flags."; "K6_FEATURES: Environment variable for enabling feature flags."; "features: `config.json` key for enabling feature flags; documented value format and sub-keys not found."; "native-histograms: Experimental flag that makes k6 use native histograms for trend metrics."; "--json: Requests JSON output from `k6 features`; output fields not described."; "Prerequisite: Use k6 v2.1.0 or later for the feature-flag mechanism described here."; "`--features` accepts comma-separated or repeated flags."

### k6 x lists available subcommands (2026-06-30)
- slug: k6-x-lists-available-subcommands-9f3b6f07ce07
- score: 0.96

How to use it:

When selecting a k6 extension subcommand for a repository workflow, run `k6 x` to list built-in and catalog-advertised subcommands. Tab completion shows the catalog entries after a prior `k6 x` run caches the catalog locally.

Examples:

```
k6 x
```

- why_it_matters: Discover available k6 extension subcommands before selecting one for a repository workflow.
- before: The release note says k6 previously had no way to introspect which extension subcommands were available.
- sources: <https://github.com/grafana/k6/releases/tag/v2.1.0>, <https://grafana.com/docs/k6/latest/extensions/create/subcommand-extensions/>
- gotchas: "Version: v2.1.0"; "Prerequisite: For tab completion to show catalog entries, run `k6 x` first to cache the catalog locally."; "Tab completion surfaces the same set only once the catalog has been cached locally by a prior `k6 x` run."

### k6 cloud lists projects with `k6 cloud project list` (2026-05-11)
- slug: k6-cloud-lists-projects-with-k6-cloud-project-list-bacdc431de3f
- score: 0.95

How to use it:

When inspecting Grafana Cloud k6 projects, run `k6 cloud project list`; add `--json` for a JSON array. The command lists projects in the configured stack.

Examples:

```
k6 cloud project list
```

```
k6 cloud project list --json
```

- why_it_matters: Inspect Grafana Cloud k6 projects while maintaining a test repository or workflow.
- sources: <https://github.com/grafana/k6/releases/tag/v2.0.0>, <https://grafana.com/docs/k6/latest/reference/cloud-commands/>
- gotchas: "Version: v2.0.0"; "--json: Output the project list as a JSON array; without it, output is a human-readable table."; "Prerequisite: Every `k6 cloud` subcommand requires an API token and a configured stack. Authenticate with `k6 cloud login`, or set `K6_CLOUD_TOKEN` and `K6_CLOUD_STACK_ID`."; "The output supports human-readable table and JSON formats."; "Docs conflict: Card and release note say `--format=json`; official documentation says the flag is `--json`. The documentation’s newer version label is v2.3.x."

### k6 HTTP API server requires an explicit address (2026-05-11)
- slug: k6-http-api-server-requires-an-explicit-address-1ddbf7bc577c
- score: 0.96

How to use it:

Starting with k6 v2.0.0, the REST API server is off by default. When a local workflow needs it, start k6 with `--address` set to the listener address.

Examples:

```
k6 run --address=localhost:6565 <script.js>
```

- why_it_matters: Update a local workflow that uses the k6 REST API server.
- before: In earlier k6 versions the server started by default and listened on localhost:6565 unless opted out.
- sources: <https://github.com/grafana/k6/releases/tag/v2.0.0>, <https://grafana.com/docs/k6/latest/reference/k6-rest-api/>, <https://grafana.com/docs/k6/latest/using-k6/k6-options/reference/>
- gotchas: "Version: v2.0.0"; "--address (alias: -a) (required): Address where the REST API server listens; required to enable the server in v2.0.0. `K6_ADDRESS` is the equivalent environment variable."; "The server starts only when an address is explicitly provided via `--address` or `K6_ADDRESS`."

### k6 automatically resolves missing subcommand extensions (2026-03-25)
- slug: k6-automatically-resolves-missing-subcommand-extensions-65168ef8914e
- score: 0.95

How to use it:

If the subcommand extension is missing from the current k6 binary and is registered in the extension catalog, run `k6 x httpbin`; k6 provisions the extension and executes it. For community extensions, set `K6_ENABLE_COMMUNITY_EXTENSIONS=true`.

Examples:

```
k6 x httpbin
```

```
K6_ENABLE_COMMUNITY_EXTENSIONS=true k6 x httpbin
```

- why_it_matters: Run a subcommand extension that is not included in the current k6 binary.
- before: Previously, using extension subcommands required manually building a custom k6 binary with xk6.
- sources: <https://github.com/grafana/k6/releases/tag/v1.7.0>, <https://grafana.com/docs/k6/latest/extensions/create/subcommand-extensions/>
- gotchas: "Version: v1.7.0"; "x httpbin (required): Invokes the registered `httpbin` subcommand extension in the `k6 x` namespace."; "K6_ENABLE_COMMUNITY_EXTENSIONS: Set to `true` to use community extensions."; "Prerequisite: Use k6 v1.7.0 or later for automatic resolution of subcommand extensions."; "Prerequisite: The extension must be registered in the k6 extension catalog. Community extensions require `K6_ENABLE_COMMUNITY_EXTENSIONS=true`."; "Automatic resolution applies when the subcommand extension is not included in the current binary."

### k6/browser adds frameLocator() (2026-02-10)
- slug: k6-browser-adds-framelocator-bd6e7eef3129
- score: 0.98

How to use it:

When a k6 browser test needs to interact with iframe content, call `frameLocator(selector)` with a selector that resolves to the iframe. Chain another `frameLocator()` for nested frames, then use `locator()` to target and interact with elements inside.

Examples:

```
import { browser } from 'k6/browser';

export const options = {
  scenarios: {
    browser: {
      executor: 'shared-iterations',
      options: { browser: { type: 'chromium' } },
    },
  },
};

export default async function () {
  const page = await browser.newPage();
  try {
    await page.goto('<URL>');
    const frame = page.frameLocator('<iframe-selector>');
    await frame.locator('<element-selector>').click();
    const nested = page.frameLocator('<outer-iframe-selector>')
      .frameLocator('<inner-iframe-selector>');
    await nested.locator('<nested-element-selector>').click();
  } finally {
    await page.close();
  }
}
```

- why_it_matters: Interact with elements inside an iframe while testing a web application with k6 browser.
- sources: <https://github.com/grafana/k6/releases/tag/v1.6.0>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/locator/framelocator/>
- gotchas: "Version: v1.6.0"; "selector (required): String selector that resolves to an iframe element; used by `frameLocator(selector)` to return a FrameLocator for that iframe."; "Prerequisite: Configure a browser scenario with a browser type such as `chromium` and import `browser` from `k6/browser`."

### k6/browser adds requestfinished and requestfailed event handlers (2026-02-10)
- slug: k6-browser-adds-requestfinished-and-requestfailed-event-handlers-40d1758c06bc
- score: 0.93

How to use it:

When debugging a k6 browser test, register `requestfailed` and `requestfinished` listeners on the page before navigation to observe failed and completed network requests.

Examples:

```
import { browser } from 'k6/browser';

export const options = {
  scenarios: {
    ui: {
      executor: 'shared-iterations',
      options: { browser: { type: 'chromium' } },
    },
  },
};

export default async function () {
  const page = await browser.newPage();
  page.on('requestfailed', (request) => console.log(`Request failed: ${request.url()}`));
  page.on('requestfinished', (request) => console.log(`Request finished: ${request.url()}`));
  await page.goto('<URL>');
  await page.close();
}
```

- why_it_matters: Monitor successful and failed network requests while debugging a k6 browser test.
- sources: <https://github.com/grafana/k6/releases/tag/v1.6.0>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/page/on/>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/request/>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/>
- gotchas: "Version: v1.6.0"; "event (required): Event name: `requestfailed` for requests that fail to reach the server; `requestfinished` for requests that successfully complete."; "handler (required): Callback invoked when the event is emitted; receives the corresponding Request object."; "request.url(): Returns the request URL; usable in the event handler for logging."; "Prerequisite: Use a current k6 version to work with the browser module."; "`requestfailed` fires for request failures such as network errors or aborts; `requestfinished` fires when a request completes successfully."

### k6/browser Page adds goBack() and goForward() (2026-02-10)
- slug: k6-browser-page-adds-goback-and-goforward-8323f0867bd6
- score: 0.96

How to use it:

When a k6 browser script needs to test session history, use `page.goBack()` or `page.goForward()` after navigation; await the call and pass optional `{ timeout, waitUntil }` settings as needed.

Examples:

```
import { browser } from 'k6/browser';

export const options = {
  scenarios: { ui: { executor: 'shared-iterations', options: { browser: { type: 'chromium' } } } },
};

export default async function () {
  const page = await browser.newPage();
  try {
    await page.goto('<first-url>');
    await page.goto('<second-url>');
    await page.goBack({ timeout: 30000, waitUntil: 'load' });
    await page.goForward();
  } finally {
    await page.close();
  }
}
```

- why_it_matters: Test browser history navigation in a k6 browser script.
- sources: <https://github.com/grafana/k6/releases/tag/v1.6.0>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/page/goback/>, <https://grafana.com/docs/k6/latest/using-k6-browser/running-browser-tests/>, <https://grafana.com/docs/k6/latest/using-k6-browser/>
- gotchas: "Version: v1.6.0"; "options: Options object for the history navigation call; defaults to null."; "options.timeout: Maximum operation time in milliseconds; defaults to 30000. Set to 0 to disable the timeout."; "options.waitUntil: Navigation success event; defaults to `load`. Allowed values: `domcontentloaded`, `load`, `networkidle`. Docs caution that `networkidle` may never fire on busy sites."; "Prerequisite: A browser scenario must specify an executor and set `options.browser.type` to `chromium`."; "Prerequisite: Install k6 and a Chromium-based browser, or use a Docker image with Chromium built in."; "The methods support optional timeout and `waitUntil` parameters."

### k6 Cloud commands support a configurable default stack (2026-02-10)
- slug: k6-cloud-commands-support-a-configurable-default-stack-f75ad1d847d4
- score: 0.97

How to use it:

When running a Grafana Cloud test, log in with a stack to save it as the default, or set a stack for that run with `K6_CLOUD_STACK_ID` or `options.cloud.stackID`.

Examples:

```
k6 cloud login
```

```
k6 cloud login --token <YOUR_API_TOKEN> --stack <YOUR_STACK_URL_OR_SLUG>
```

```
K6_CLOUD_STACK_ID=<YOUR_STACK_ID> k6 cloud run <SCRIPT.js>
```

- why_it_matters: Run a test in Grafana Cloud using the configured default stack or a stack selected for that run.
- before: Users had to specify the project ID for every test run.
- sources: <https://github.com/grafana/k6/releases/tag/v1.6.0>, <https://grafana.com/docs/k6/latest/reference/cloud-commands/>, <https://grafana.com/docs/grafana-cloud/observe-and-act/testing/k6/author-run/tokens-and-cli-authentication/?mdm=referral&plcmt=footer&src=joyk.com>, <https://github.com/grafana/k6/blob/v1.6.0/cloudapi/config.go>
- gotchas: "Version: v1.6.0"; "--token <YOUR_API_TOKEN>: API token for authentication; used with `--stack` for non-interactive login."; "--stack <YOUR_STACK_URL_OR_SLUG>: Stack URL or slug where cloud commands run by default."; "K6_CLOUD_STACK_ID=<YOUR_STACK_ID>: Environment variable selecting the stack by ID for cloud commands."; "options.cloud.stackID: Stack ID selected for the run; available in k6 v1.6.0 and later."; "options.cloud.projectID: Project ID for the cloud run."; "Prerequisite: Authenticate with a Grafana Cloud k6 API token and configure a stack to run cloud commands."; "A stack slug or stack id is used to determine which default project to use when one is not explicitly provided."; "If `projectID` does not belong to the configured stack, the run throws an error."; "Stack information will become mandatory to run a test in k6 v2."; "Docs conflict: Current k6 documentation says every cloud subcommand requires a configured stack; current release notes state stack is mandatory in k6 v2. The official v1.6.0 source documents stackID and projectID fields, but current documentation may describe newer behavior."

### k6 deps analyzes script and archive dependencies (2026-02-10)
- slug: k6-deps-analyzes-script-and-archive-dependencies-175f158dbc81
- score: 0.97

How to use it:

When you need to identify script or archive dependencies for an auto-resolved build, run `k6 deps <script-or-archive>`; add `--json` for programmatic output. The command reports dependencies found through imports and “use” directives, but does not follow dynamic `require()` calls.

Examples:

```
k6 deps <script.js>
```

```
k6 deps --json <script.js>
```

```
k6 deps <archive.tar>
```

- why_it_matters: Inspect a script or archive to identify extension dependencies needed to build a binary with auto extension resolution.
- sources: <https://github.com/grafana/k6/releases/tag/v1.6.0>, <https://grafana.com/docs/k6/latest/release-notes/v1.6.0/>, <https://grafana.com/docs/k6/latest/using-k6/k6-deps-command/>
- gotchas: "Version: v1.6.0"; "<script> (required): Script or archive to analyze."; "--json: Output dependency information in JSON; default output is human-readable."; "Dependency analysis accounts for imports, not dynamic `require()` calls."

### k6 run supports a dependency manifest for default version constraints (2026-02-10)
- slug: k6-run-supports-a-dependency-manifest-for-default-version-constraints-1acb14c9aea2
- score: 0.94

How to use it:

When an imported dependency has no version constraint in the script, set `K6_DEPENDENCIES_MANIFEST` to a JSON map of dependency names to constraints and run the script. The manifest supplies a default only for imported dependencies without an explicit version or `use k6 with` directive.

Examples:

```
K6_DEPENDENCIES_MANIFEST='{"k6/x/faker": ">=v0.4.4"}' k6 run <script.js>
```

- why_it_matters: Run a script with imported dependencies that lack explicit version constraints and need manifest-specified constraints.
- before: An imported dependency without an explicit version defaults to `"*"`.
- sources: <https://github.com/grafana/k6/releases/tag/v1.6.0>
- gotchas: "Version: v1.6.0"; "K6_DEPENDENCIES_MANIFEST: Environment variable containing a JSON object whose keys are dependency names and whose values are version constraints; it replaces the default `*` constraint when the imported dependency has no version defined in script pragmas."; "dependency name (JSON key) (required): Name of a dependency imported by the script, such as `k6/x/faker`; entries do not affect dependencies the script does not import."; "constraint (JSON value) (required): Version constraint to apply to that imported dependency when the script does not define its version using pragmas."; "k6 run <script.js> (required): Runs the script with the manifest environment variable set in the invocation."; "The manifest does not change anything for a dependency that is not imported by the script."; "The manifest supplies defaults when a dependency has no version defined in the script using pragmas."

### k6 adds an opt-in machine-readable summary (2026-01-05)
- slug: k6-adds-an-opt-in-machine-readable-summary-7b0b5264d322
- score: 0.98

How to use it:

When exporting a k6 end-of-test summary in structured form, enable the machine-readable format and write it with `--summary-export` or `handleSummary()`.

Examples:

```
k6 run script.js --new-machine-readable-summary --summary-export=summary.json
```

```
K6_NEW_MACHINE_READABLE_SUMMARY=true k6 run --summary-export summary.json script.js
```

```
export function handleSummary(data) { return { 'summary.json': JSON.stringify(data) }; }
```

- why_it_matters: Export a k6 test run summary in a structured format for a CI pipeline or custom analysis script.
- sources: <https://github.com/grafana/k6/releases/tag/v1.5.0>, <https://github.com/grafana/k6/blob/v1.5.0/internal/cmd/runtime_options.go>, <https://grafana.com/docs/k6/latest/results-output/end-of-test/custom-summary/>, <https://grafana.com/docs/k6/latest/using-k6/k6-options/reference/>
- gotchas: "Version: v1.5.0"; "Availability: Currently opt-in; the format will become the default in k6 v2."; "--new-machine-readable-summary: Enables the new machine-readable summary format; used for `--summary-export` and as the `handleSummary()` argument."; "K6_NEW_MACHINE_READABLE_SUMMARY: Environment variable that enables the machine-readable format; set to a boolean value such as `true`."; "--summary-export <filename>: For `k6 run`, saves the end-of-test summary report to a JSON file; `<filename>` is the output path."; "handleSummary(data): End-of-test callback receiving the aggregated summary object; return a map whose string keys are `stdout`, `stderr`, or file paths and whose values are strings or `ArrayBuffer`."; "Prerequisite: The documented `--summary-export` command is available with `k6 run`."; "Prerequisite: The machine-readable format was introduced in k6 v1.5.0; the v1.5.0 release note says it is opt-in."; "The format is currently opt-in."; "Docs conflict: Current options documentation discourages `--summary-export` and recommends `handleSummary()` for flexible exports; it still documents the flag and its JSON output. This guidance is from newer documentation than v1.5.0. https://grafana.com/docs/k6/latest/using-k6/k6-options/reference/"

### k6/browser locator.pressSequentially() types with keyboard events (2026-01-05)
- slug: k6-browser-locator-presssequentially-types-with-keyboard-events-038fcfc1c573
- score: 0.98

How to use it:

When testing input behavior that responds to individual keystrokes, use `locator.pressSequentially()` to type characters and fire keyboard events. Set `delay` in milliseconds to test handlers that depend on time between keystrokes.

Examples:

```
import { browser } from 'k6/browser';

export const options = {
  scenarios: {
    browser: {
      executor: 'shared-iterations',
      options: { browser: { type: 'chromium' } },
    },
  },
};

export default async function () {
  const page = await browser.newPage();
  try {
    await page.goto('<URL>');
    await page.locator('<input selector>').pressSequentially('<text>', { delay: 100 });
  } finally {
    await page.close();
  }
}
```

- why_it_matters: Test a browser input that reacts to each keystroke, such as autocomplete or per-character validation.
- before: Use `locator.type()` for gradual typing without keyboard events, or `locator.fill()` for simple form filling.
- sources: <https://github.com/grafana/k6/releases/tag/v1.5.0>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/locator/presssequentially/>
- gotchas: "Version: v1.5.0"; "text (required): String to type into the focused element character by character."; "options.delay: Milliseconds to wait between key presses; defaults to 0."; "options.noWaitAfter: If true, do not wait for navigation caused by the action to complete; defaults to false."; "options.timeout: Maximum time in milliseconds; defaults to 30000, or the BrowserContext/Page default timeout. Use 0 to disable."; "A configurable delay between keystrokes is supported."; "Docs conflict: The latest documentation shows k6 v2.3.x, newer than the card's v1.5.0; version-specific differences were not established."

### k6/browser page.waitForEvent() synchronizes on events (2026-01-05)
- slug: k6-browser-page-waitforevent-synchronizes-on-events-a05900ed5e02
- score: 0.99

How to use it:

When a browser test must wait for a console, request, or response event, call `page.waitForEvent(event[, optionsOrPredicate])` before triggering the event and await its promise before continuing.

Examples:

```
const msgPromise = page.waitForEvent('console', msg => msg.text().includes('hello'));
await page.evaluate(() => console.log('hello world'));
const msg = await msgPromise;
```

```
const resPromise = page.waitForEvent('response', {
  predicate: res => res.url().includes('/api/data'),
  timeout: 5000,
});
await page.click('button#fetch-data');
const res = await resPromise;
```

- why_it_matters: Write a browser test that proceeds after a specific console message or matching response is observed.
- sources: <https://github.com/grafana/k6/releases/tag/v1.5.0>, <https://github.com/grafana/k6/blob/v1.5.0/release%20notes/v1.5.0.md>, <https://grafana.com/docs/k6/latest/javascript-api/k6-browser/page/waitforevent/>
- gotchas: "Version: v1.5.0"; "event (required): Event name; supported values are `console`, `request`, and `response."; "optionsOrPredicate: A predicate function or options object; the two forms are alternatives."; "options.predicate: Function receiving the event object; return true when it is the expected event."; "options.timeout: Maximum wait in milliseconds; default 30000, or 0 to disable. BrowserContext or Page `setDefaultTimeout` can override the default."; "The method blocks the caller until the specified event is captured; with a predicate, it waits for an event satisfying that predicate."
