<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Chromium on Grafana Labs</title><link>https://grafana.com/docs/k6/v2.3.x/javascript-api/k6-browser/chromium/</link><description>Recent content in Chromium on Grafana Labs</description><generator>Hugo -- gohugo.io</generator><language>en</language><atom:link href="/docs/k6/v2.3.x/javascript-api/k6-browser/chromium/index.xml" rel="self" type="application/rss+xml"/><item><title>connectOverCDP(wsEndpoint)</title><link>https://grafana.com/docs/k6/v2.3.x/javascript-api/k6-browser/chromium/connectovercdp/</link><pubDate>Mon, 21 Sep 2026 15:16:28 +0000</pubDate><guid>https://grafana.com/docs/k6/v2.3.x/javascript-api/k6-browser/chromium/connectovercdp/</guid><content><![CDATA[&lt;h1 id=&#34;connectovercdpwsendpoint&#34;&gt;connectOverCDP(wsEndpoint)&lt;/h1&gt;
&lt;p&gt;Attaches k6 to an existing Chromium-based browser over the &lt;a href=&#34;https://chromedevtools.github.io/devtools-protocol/&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Chrome DevTools Protocol&lt;/a&gt; (CDP), and returns a 
    &lt;a href=&#34;/docs/k6/v2.3.x/javascript-api/k6-browser/&#34;&gt;Browser&lt;/a&gt; you can use exactly like a k6-managed one.&lt;/p&gt;
&lt;p&gt;Because you connect from inside the iteration, you can compute the WebSocket endpoint at runtime. For instance, you can request a browser session from your provider&amp;rsquo;s API in 
    &lt;a href=&#34;/docs/k6/v2.3.x/using-k6/test-lifecycle/&#34;&gt;&lt;code&gt;setup()&lt;/code&gt;&lt;/a&gt; and pass the endpoint to your iterations.&lt;/p&gt;


&lt;div class=&#34;admonition admonition-note&#34;&gt;&lt;blockquote&gt;&lt;p class=&#34;title text-uppercase&#34;&gt;Note&lt;/p&gt;&lt;p&gt;&lt;code&gt;connectOverCDP&lt;/code&gt; doesn&amp;rsquo;t need the &lt;code&gt;browser&lt;/code&gt; 
    &lt;a href=&#34;/docs/k6/v2.3.x/using-k6-browser/running-browser-tests/&#34;&gt;scenario option&lt;/a&gt;. k6 doesn&amp;rsquo;t launch a browser, so there&amp;rsquo;s no browser type for it to resolve. The 
    &lt;a href=&#34;/docs/k6/v2.3.x/using-k6-browser/options/&#34;&gt;browser module options&lt;/a&gt; that apply to an existing browser, such as &lt;code&gt;K6_BROWSER_TIMEOUT&lt;/code&gt; and &lt;code&gt;K6_BROWSER_DEBUG&lt;/code&gt;, are still honored.&lt;/p&gt;&lt;/blockquote&gt;&lt;/div&gt;

&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Parameter&lt;/th&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Default&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;wsEndpoint&lt;/td&gt;
              &lt;td&gt;string&lt;/td&gt;
              &lt;td&gt;-&lt;/td&gt;
              &lt;td&gt;Required. The WebSocket endpoint of the browser&amp;rsquo;s CDP interface, for example &lt;code&gt;ws://localhost:9222/devtools/browser/&amp;lt;BROWSER_ID&amp;gt;&lt;/code&gt;. Must use the &lt;code&gt;ws&lt;/code&gt; or &lt;code&gt;wss&lt;/code&gt; scheme.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h3 id=&#34;returns&#34;&gt;Returns&lt;/h3&gt;
&lt;section class=&#34;expand-table-wrapper&#34;&gt;&lt;div class=&#34;button-div&#34;&gt;
      &lt;button class=&#34;expand-table-btn&#34;&gt;Expand table&lt;/button&gt;
    &lt;/div&gt;&lt;div class=&#34;responsive-table-wrapper&#34;&gt;
    &lt;table&gt;
      &lt;thead&gt;
          &lt;tr&gt;
              &lt;th&gt;Type&lt;/th&gt;
              &lt;th&gt;Description&lt;/th&gt;
          &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
          &lt;tr&gt;
              &lt;td&gt;&lt;code&gt;Promise&amp;lt;Browser&amp;gt;&lt;/code&gt;&lt;/td&gt;
              &lt;td&gt;A Promise that fulfills with a 
    &lt;a href=&#34;/docs/k6/v2.3.x/javascript-api/k6-browser/&#34;&gt;Browser&lt;/a&gt; object. Unlike the k6-managed &lt;code&gt;browser&lt;/code&gt;, it also exposes 
    &lt;a href=&#34;/docs/k6/v2.3.x/javascript-api/k6-browser/close/&#34;&gt;&lt;code&gt;close()&lt;/code&gt;&lt;/a&gt;.&lt;/td&gt;
          &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/div&gt;
&lt;/section&gt;&lt;h3 id=&#34;connection-lifecycle&#34;&gt;Connection lifecycle&lt;/h3&gt;
&lt;p&gt;k6 manages the connection for you and closes it at the end of the iteration, the same way it does for a browser it launched itself. Call 
    &lt;a href=&#34;/docs/k6/v2.3.x/javascript-api/k6-browser/close/&#34;&gt;&lt;code&gt;browser.close()&lt;/code&gt;&lt;/a&gt; when you want to release it earlier.&lt;/p&gt;
&lt;p&gt;Closing the connection doesn&amp;rsquo;t stop the browser itself. You own its lifecycle, so it keeps running.&lt;/p&gt;
&lt;h3 id=&#34;examples&#34;&gt;Examples&lt;/h3&gt;
&lt;h4 id=&#34;connect-to-a-local-browser&#34;&gt;Connect to a local browser&lt;/h4&gt;
&lt;p&gt;Start Chrome with the &lt;code&gt;--remote-debugging-port&lt;/code&gt; flag, then read its WebSocket endpoint from &lt;code&gt;http://localhost:9222/json/version&lt;/code&gt; (the &lt;code&gt;webSocketDebuggerUrl&lt;/code&gt; field) and pass it to k6 as an environment variable:&lt;/p&gt;
&lt;!-- md-k6:skip --&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JavaScript&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-javascript&#34;&gt;import { chromium } from &amp;#39;k6/browser&amp;#39;;

export default async function () {
  const browser = await chromium.connectOverCDP(__ENV.CDP_WS_URL);
  const page = await browser.newPage();

  try {
    await page.goto(&amp;#39;https://quickpizza.grafana.com/&amp;#39;);
    console.log(`title: ${await page.title()}`);
  } finally {
    await page.close();
    await browser.close();
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Then, run the test with this command:&lt;/p&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;Bash&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-bash&#34;&gt;CDP_WS_URL=ws://localhost:9222/devtools/browser/&amp;lt;BROWSER_ID&amp;gt; k6 run script.js&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h4 id=&#34;connect-to-a-browser-provider&#34;&gt;Connect to a browser provider&lt;/h4&gt;
&lt;p&gt;When a third-party provider creates the browser session, request the endpoint once in &lt;code&gt;setup()&lt;/code&gt; and share it with every iteration:&lt;/p&gt;
&lt;!-- md-k6:skip --&gt;

&lt;div class=&#34;code-snippet &#34;&gt;&lt;div class=&#34;lang-toolbar&#34;&gt;
    &lt;span class=&#34;lang-toolbar__item lang-toolbar__item-active&#34;&gt;JavaScript&lt;/span&gt;
    &lt;span class=&#34;code-clipboard&#34;&gt;
      &lt;button x-data=&#34;app_code_snippet()&#34; x-init=&#34;init()&#34; @click=&#34;copy()&#34;&gt;
        &lt;img class=&#34;code-clipboard__icon&#34; src=&#34;/media/images/icons/icon-copy-small-2.svg&#34; alt=&#34;Copy code to clipboard&#34; width=&#34;14&#34; height=&#34;13&#34;&gt;
        &lt;span&gt;Copy&lt;/span&gt;
      &lt;/button&gt;
    &lt;/span&gt;
    &lt;div class=&#34;lang-toolbar__border&#34;&gt;&lt;/div&gt;
  &lt;/div&gt;&lt;div class=&#34;code-snippet &#34;&gt;
    &lt;pre data-expanded=&#34;false&#34;&gt;&lt;code class=&#34;language-javascript&#34;&gt;import http from &amp;#39;k6/http&amp;#39;;
import { chromium } from &amp;#39;k6/browser&amp;#39;;

export function setup() {
  const res = http.post(&amp;#39;https://provider.example/v1/sessions&amp;#39;);
  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(&amp;#39;https://quickpizza.grafana.com/&amp;#39;);
  } finally {
    await page.close();
    await browser.close();
  }
}&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;h3 id=&#34;related&#34;&gt;Related&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/k6/v2.3.x/javascript-api/k6-browser/#browser-module-api&#34;&gt;browser module API&lt;/a&gt; - The API a connected browser exposes&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/k6/v2.3.x/javascript-api/k6-browser/close/&#34;&gt;browser.close()&lt;/a&gt; - Release the connection before the iteration ends&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/k6/v2.3.x/javascript-api/k6-browser/isconnected/&#34;&gt;browser.isConnected&lt;/a&gt; - Check whether the CDP connection is still active&lt;/li&gt;
&lt;li&gt;
    &lt;a href=&#34;/docs/k6/v2.3.x/using-k6-browser/running-browser-tests/&#34;&gt;Running browser tests&lt;/a&gt; - Run tests with a browser that k6 launches&lt;/li&gt;
&lt;/ul&gt;
]]></content><description>&lt;h1 id="connectovercdpwsendpoint">connectOverCDP(wsEndpoint)&lt;/h1>
&lt;p>Attaches k6 to an existing Chromium-based browser over the &lt;a href="https://chromedevtools.github.io/devtools-protocol/" target="_blank" rel="noopener noreferrer">Chrome DevTools Protocol&lt;/a> (CDP), and returns a
&lt;a href="/docs/k6/v2.3.x/javascript-api/k6-browser/">Browser&lt;/a> you can use exactly like a k6-managed one.&lt;/p></description></item></channel></rss>