<h2 dir="auto">Proposed functionality</h2>
<p dir="auto">A new <code class="notranslate">setStorageState()</code> API on the <code class="notranslate">context</code> object that applies any given storage state to the current page.</p>
<div class="highlight highlight-source-ts notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="context.setStorageState({ path: '/storage.json' })
context.setStorageState({
  cookies: [...],
  origins: [...]
})"><pre class="notranslate"><span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-en">setStorageState</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">path</span>: <span class="pl-s">'/storage.json'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span>
<span class="pl-s1">context</span><span class="pl-kos">.</span><span class="pl-en">setStorageState</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">cookies</span>: <span class="pl-kos">[</span>...<span class="pl-kos">]</span><span class="pl-kos">,</span>
  <span class="pl-c1">origins</span>: <span class="pl-kos">[</span>...<span class="pl-kos">]</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span></pre></div>
<p dir="auto">This API is opposite in its functionality to the existing <code class="notranslate">context.storageState()</code> that flushes the storage state to the disk.</p>
<h2 dir="auto">Use case</h2>
<p dir="auto">The <a href="https://playwright.dev/docs/test-auth#reuse-signed-in-state" rel="nofollow">Authentication</a> docs showcase a great example of creating a browser context, performing sign-in, and storing that session in a JSON file. However, to <em>use</em> that session file you need to create a new browsing context. This is not suitable when using <code class="notranslate">@playwright/test</code> and wanting to control auth state per test.</p>
<p dir="auto">The recommended example shows that we can create separate contexts with a different session, and that works great, but you lose the ability to use the already existing <code class="notranslate">context</code> that gets created by the Playwright test runner. You also lose any custom fixtures as they are attached to that default context.</p>
<p dir="auto">In general, I see no reason not to have the "read" functionality for the session state.</p>
<h2 dir="auto">Implementation</h2>
<p dir="auto">You're already using this logic in Playwright, it's just internal:</p>
<p dir="auto"></p><div class="Box Box--condensed my-2">
  <div class="Box-header f6">
    <p class="mb-0 text-bold">
      <a href="https://github.com/microsoft/playwright/blob/1303e3e355fcdfd4e7f66650dbd9fca6645db5e3/packages/playwright-core/src/server/browserContext.ts#L512-L537">playwright/packages/playwright-core/src/server/browserContext.ts</a>
    </p>
    <p class="mb-0 color-fg-muted">
        Lines 512 to 537
      in
      <a data-pjax="true" class="commit-tease-sha" href="/microsoft/playwright/commit/1303e3e355fcdfd4e7f66650dbd9fca6645db5e3">1303e3e</a>
    </p>
  </div>
  <div itemprop="text" class="Box-body p-0 blob-wrapper blob-wrapper-embedded data">
    <table class="highlight tab-size mb-0 js-file-line-container" data-tab-size="8" data-paste-markdown-skip="">

        <tbody><tr class="border-0">
          <td id="L512" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="512"></td>
          <td id="LC512" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-k">async</span> <span class="pl-en">setStorageState</span><span class="pl-kos">(</span><span class="pl-s1">metadata</span>: <span class="pl-smi">CallMetadata</span><span class="pl-kos">,</span> <span class="pl-s1">state</span>: <span class="pl-smi">NonNullable</span><span class="pl-kos">&lt;</span><span class="pl-s1">channels</span><span class="pl-kos">.</span><span class="pl-smi">BrowserNewContextParams</span><span class="pl-kos">[</span><span class="pl-s">'storageState'</span><span class="pl-kos">]</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L513" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="513"></td>
          <td id="LC513" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">_settingStorageState</span> <span class="pl-c1">=</span> <span class="pl-c1">true</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L514" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="514"></td>
          <td id="LC514" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-k">try</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L515" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="515"></td>
          <td id="LC515" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">       <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">state</span><span class="pl-kos">.</span><span class="pl-c1">cookies</span><span class="pl-kos">)</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L516" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="516"></td>
          <td id="LC516" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-k">await</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">addCookies</span><span class="pl-kos">(</span><span class="pl-s1">state</span><span class="pl-kos">.</span><span class="pl-c1">cookies</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L517" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="517"></td>
          <td id="LC517" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">       <span class="pl-k">if</span> <span class="pl-kos">(</span><span class="pl-s1">state</span><span class="pl-kos">.</span><span class="pl-c1">origins</span> <span class="pl-c1">&amp;&amp;</span> <span class="pl-s1">state</span><span class="pl-kos">.</span><span class="pl-c1">origins</span><span class="pl-kos">.</span><span class="pl-c1">length</span><span class="pl-kos">)</span>  <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L518" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="518"></td>
          <td id="LC518" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-k">const</span> <span class="pl-s1">internalMetadata</span> <span class="pl-c1">=</span> <span class="pl-en">serverSideCallMetadata</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L519" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="519"></td>
          <td id="LC519" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-k">const</span> <span class="pl-s1">page</span> <span class="pl-c1">=</span> <span class="pl-k">await</span> <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-en">newPage</span><span class="pl-kos">(</span><span class="pl-s1">internalMetadata</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L520" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="520"></td>
          <td id="LC520" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">_setServerRequestInterceptor</span><span class="pl-kos">(</span><span class="pl-s1">handler</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L521" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="521"></td>
          <td id="LC521" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">           <span class="pl-s1">handler</span><span class="pl-kos">.</span><span class="pl-en">fulfill</span><span class="pl-kos">(</span><span class="pl-kos">{</span> <span class="pl-c1">body</span>: <span class="pl-s">'&lt;html&gt;&lt;/html&gt;'</span> <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">catch</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span><span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L522" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="522"></td>
          <td id="LC522" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L523" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="523"></td>
          <td id="LC523" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-k">for</span> <span class="pl-kos">(</span><span class="pl-k">const</span> <span class="pl-s1">originState</span> <span class="pl-k">of</span> <span class="pl-s1">state</span><span class="pl-kos">.</span><span class="pl-c1">origins</span><span class="pl-kos">)</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L524" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="524"></td>
          <td id="LC524" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">           <span class="pl-k">const</span> <span class="pl-s1">frame</span> <span class="pl-c1">=</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">mainFrame</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L525" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="525"></td>
          <td id="LC525" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">           <span class="pl-k">await</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">goto</span><span class="pl-kos">(</span><span class="pl-s1">metadata</span><span class="pl-kos">,</span> <span class="pl-s1">originState</span><span class="pl-kos">.</span><span class="pl-c1">origin</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L526" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="526"></td>
          <td id="LC526" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">           <span class="pl-k">await</span> <span class="pl-s1">frame</span><span class="pl-kos">.</span><span class="pl-en">evaluateExpression</span><span class="pl-kos">(</span><span class="pl-s">`</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L527" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="527"></td>
          <td id="LC527" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-s">            originState =&gt; {</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L528" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="528"></td>
          <td id="LC528" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-s">              for (const { name, value } of (originState.localStorage || []))</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L529" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="529"></td>
          <td id="LC529" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-s">                localStorage.setItem(name, value);</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L530" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="530"></td>
          <td id="LC530" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line"> <span class="pl-s">            }`</span><span class="pl-kos">,</span> <span class="pl-c1">true</span><span class="pl-kos">,</span> <span class="pl-s1">originState</span><span class="pl-kos">,</span> <span class="pl-s">'utility'</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L531" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="531"></td>
          <td id="LC531" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-kos">}</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L532" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="532"></td>
          <td id="LC532" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">         <span class="pl-k">await</span> <span class="pl-s1">page</span><span class="pl-kos">.</span><span class="pl-en">close</span><span class="pl-kos">(</span><span class="pl-s1">internalMetadata</span><span class="pl-kos">)</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L533" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="533"></td>
          <td id="LC533" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">       <span class="pl-kos">}</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L534" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="534"></td>
          <td id="LC534" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-kos">}</span> <span class="pl-k">finally</span> <span class="pl-kos">{</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L535" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="535"></td>
          <td id="LC535" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">       <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">_settingStorageState</span> <span class="pl-c1">=</span> <span class="pl-c1">false</span><span class="pl-kos">;</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L536" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="536"></td>
          <td id="LC536" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">     <span class="pl-kos">}</span> </td>
        </tr>

        <tr class="border-0">
          <td id="L537" class="blob-num border-0 px-3 py-0 color-bg-default" data-line-number="537"></td>
          <td id="LC537" class="blob-code border-0 px-3 py-0 color-bg-default blob-code-inner js-file-line">   <span class="pl-kos">}</span> </td>
        </tr>
    </tbody></table>
  </div>
</div>
<p></p>
<p dir="auto">I propose to abstract it into a general function, dropping internals like <code class="notranslate">this. _settingStorageState</code>, and reuse it in the new <code class="notranslate">page.setStorageState()</code> API.</p>
<p dir="auto">We have the ability to sniff websockets and use events on messages bi directionally, which is great, but can we also modify those messages? Either change them if they are fired, or send them directly to the websocket? It seems like following the "Route.ContinueAsync" flow works well, but it'd be even better if we can create a request since we already have the "WebSocket" class within the event handler.</p>
<p dir="auto">Note: also created on the C# implementation repo since that's what I'm using, but figured I'd put it here too since this appears to be the main repo. We can close whichever is more appropriate:<br>
<a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="904255351" data-permission-text="Title is private" data-url="https://github.com/microsoft/playwright-dotnet/issues/1450" data-hovercard-type="issue" data-hovercard-url="/microsoft/playwright-dotnet/issues/1450/hovercard" href="https://github.com/microsoft/playwright-dotnet/issues/1450">microsoft/playwright-dotnet#1450</a></p>