<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Parth V Square </title>
    <description>The latest articles on DEV Community by Parth V Square  (@parthvsquare).</description>
    <link>https://dev.to/parthvsquare</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4198027%2F6ad1246f-62cd-46c7-96d9-d74dd0092b1b.png</url>
      <title>DEV Community: Parth V Square </title>
      <link>https://dev.to/parthvsquare</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/parthvsquare"/>
    <language>en</language>
    <item>
      <title>Chrome DevTools MCP in Claude Code (setup, attach mode, vs Playwright MCP)</title>
      <dc:creator>Parth V Square </dc:creator>
      <pubDate>Sun, 25 Oct 2026 08:55:21 +0000</pubDate>
      <link>https://dev.to/branch42-labs/chrome-devtools-mcp-in-claude-code-setup-attach-mode-vs-playwright-mcp-36o9</link>
      <guid>https://dev.to/branch42-labs/chrome-devtools-mcp-in-claude-code-setup-attach-mode-vs-playwright-mcp-36o9</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Chrome DevTools MCP is the Chrome DevTools team's open-source MCP server. It lets Claude Code, Cursor, Codex or Gemini CLI drive a real Chrome and use DevTools features: network requests, console, screenshots, performance traces, Lighthouse and heap snapshots. Install it with &lt;code&gt;claude mcp add chrome-devtools --scope user -- npx chrome-devtools-mcp@latest&lt;/code&gt;. Add &lt;code&gt;--autoConnect&lt;/code&gt; (Chrome 144+) to let it attach to the Chrome you're already signed in to. It's great for debugging the page in front of it. It's a poor fit for "map this app's whole API".&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I wanted it
&lt;/h2&gt;

&lt;p&gt;My agent kept writing frontend fixes it couldn't check. With a browser MCP server it opens the page, reads the console, looks at the failing request and tells me what broke. The Chrome team shipped this as a public preview in &lt;a href="https://developer.chrome.com/blog/chrome-devtools-mcp" rel="noopener noreferrer"&gt;September 2025&lt;/a&gt;, and it now has around 60 tools (some behind opt-in flags).&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;You need Node.js LTS and current stable Chrome.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add chrome-devtools &lt;span class="nt"&gt;--scope&lt;/span&gt; user &lt;span class="nt"&gt;--&lt;/span&gt; npx chrome-devtools-mcp@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or the plugin, which also installs skills for a11y, cookies, LCP and memory leaks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/plugin marketplace add ChromeDevTools/chrome-devtools-mcp
/plugin &lt;span class="nb"&gt;install &lt;/span&gt;chrome-devtools-mcp@chrome-devtools-plugins
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cursor&lt;/strong&gt; (Settings → MCP → New MCP Server) and most other clients:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"chrome-devtools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chrome-devtools-mcp@latest"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Codex / Gemini CLI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codex mcp add chrome-devtools &lt;span class="nt"&gt;--&lt;/span&gt; npx chrome-devtools-mcp@latest
gemini mcp add chrome-devtools npx chrome-devtools-mcp@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First prompt to try: &lt;code&gt;Check the performance of https://developer.chrome.com&lt;/code&gt;. You'll see a Chrome window open and a trace get recorded.&lt;/p&gt;

&lt;h2&gt;
  
  
  The network tools
&lt;/h2&gt;

&lt;p&gt;There are two:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;list_network_requests&lt;/code&gt;: requests for a page since the last navigation. Filter by &lt;code&gt;resourceTypes&lt;/code&gt;, paginate with &lt;code&gt;pageSize&lt;/code&gt;/&lt;code&gt;pageIdx&lt;/code&gt;, and set &lt;code&gt;includePreservedRequests&lt;/code&gt; to reach back 3 navigations.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;get_network_request&lt;/code&gt;: one request with headers (including &lt;code&gt;Cookie&lt;/code&gt; and &lt;code&gt;Set-Cookie&lt;/code&gt;) and bodies. &lt;code&gt;responseFilePath&lt;/code&gt; writes a big body to disk instead of into the context window.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The trick I like most: call &lt;code&gt;get_network_request&lt;/code&gt; with no &lt;code&gt;reqid&lt;/code&gt; and it returns whatever request you have &lt;strong&gt;selected in the DevTools Network panel&lt;/strong&gt;. I click the broken call, then type "why did this 403?".&lt;/p&gt;

&lt;p&gt;If headers carry tokens you'd rather not send to a model, start the server with &lt;code&gt;--redactNetworkHeaders&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attach mode (your signed-in browser)
&lt;/h2&gt;

&lt;p&gt;By default the server launches Chrome with its own profile in &lt;code&gt;~/.cache/chrome-devtools-mcp/chrome-profile&lt;/code&gt;. &lt;code&gt;--isolated&lt;/code&gt; uses a throwaway profile instead. To debug something behind your real login:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;code&gt;chrome://inspect/#remote-debugging&lt;/code&gt; in Chrome 144+ and allow incoming connections.&lt;/li&gt;
&lt;li&gt;Add the flag:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chrome-devtools-mcp@latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--autoConnect"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Approve the permission dialog Chrome shows each time the server connects. A "Chrome is being controlled by automated test software" banner stays up while it's attached.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No &lt;code&gt;--autoConnect&lt;/code&gt; (sandboxes, older Chrome)? Start Chrome yourself and point the server at it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/Applications/Google&lt;span class="se"&gt;\ &lt;/span&gt;Chrome.app/Contents/MacOS/Google&lt;span class="se"&gt;\ &lt;/span&gt;Chrome &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--remote-debugging-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;9222 &lt;span class="nt"&gt;--user-data-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/chrome-profile-stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"chrome-devtools-mcp@latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--browser-url=http://127.0.0.1:9222"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Heads up: attach mode gives the agent your cookies and signed-in accounts. Google's own docs say to only use it with agents you trust. Also, usage statistics are on by default (&lt;code&gt;--no-usage-statistics&lt;/code&gt;), and performance tools can send trace URLs to CrUX (&lt;code&gt;--no-performance-crux&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Chrome DevTools MCP vs Playwright MCP
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/microsoft/playwright-mcp" rel="noopener noreferrer"&gt;Playwright MCP&lt;/a&gt; (&lt;code&gt;claude mcp add playwright npx @playwright/mcp@latest&lt;/code&gt;) overlaps a lot. How I pick:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Chrome DevTools MCP&lt;/th&gt;
&lt;th&gt;Playwright MCP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Browsers&lt;/td&gt;
&lt;td&gt;Chrome, Chrome for Testing&lt;/td&gt;
&lt;td&gt;Chrome, Firefox, WebKit, Edge&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Page model&lt;/td&gt;
&lt;td&gt;screenshots + text snapshot&lt;/td&gt;
&lt;td&gt;accessibility tree, no vision needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perf insights / Lighthouse / heap&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;Playwright traces via &lt;code&gt;--caps=devtools&lt;/code&gt;, no Lighthouse or heap tools listed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Network&lt;/td&gt;
&lt;td&gt;list + get (headers, bodies)&lt;/td&gt;
&lt;td&gt;list (URL regex) + get, mocking via &lt;code&gt;--caps=network&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Existing browser&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;--autoConnect&lt;/code&gt;, &lt;code&gt;--browser-url&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;--extension&lt;/code&gt;, &lt;code&gt;--cdp-endpoint&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;User flows and cross-browser checks: Playwright. "Why is this page slow or erroring in Chrome": DevTools MCP. Playwright's README also notes that coding agents may get on better with its CLI + skills, since those calls cost fewer tokens than MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it stops for API work
&lt;/h2&gt;

&lt;p&gt;Both servers only see what the browser loads while the agent is connected. When I want the agent to understand the whole API of an app, that hurts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The request list resets per navigation (3 back at most), so the agent has to click through every screen.&lt;/li&gt;
&lt;li&gt;Each screen costs tool calls and context.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/orders/1042&lt;/code&gt; and &lt;code&gt;/orders/1043&lt;/code&gt; come back as separate URLs, so the agent has to figure out they're one endpoint.&lt;/li&gt;
&lt;li&gt;Real logged-in traffic means attach mode and handing over my session.&lt;/li&gt;
&lt;li&gt;Close the browser and the traffic is gone.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For that job I use &lt;a href="https://netraptor.dev" rel="noopener noreferrer"&gt;Netraptor&lt;/a&gt;, a Chrome extension I work on. It records the app's fetch/XHR calls while I browse normally (or crawls same-site pages), groups them into endpoints like &lt;code&gt;/orders/{id}&lt;/code&gt;, and its Pro plan has a local, read-only MCP server so the agent can ask "what does &lt;code&gt;GET /orders/{id}&lt;/code&gt; return?" from real recorded responses. It has its own gap: it records from inside the page, so browser-added headers like &lt;code&gt;Cookie&lt;/code&gt; aren't in its copy. DevTools MCP shows those. So I run both: Netraptor for "what does the API look like", DevTools MCP for "go reproduce this".&lt;/p&gt;

&lt;p&gt;The full guide, with links to every doc above, is at &lt;a href="https://netraptor.dev/guides/chrome-devtools-mcp" rel="noopener noreferrer"&gt;netraptor.dev/guides/chrome-devtools-mcp&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>ai</category>
      <category>chrome</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Chrome won't let you paste into the console? Type "allow pasting" (no quotes)</title>
      <dc:creator>Parth V Square </dc:creator>
      <pubDate>Sun, 25 Oct 2026 08:55:06 +0000</pubDate>
      <link>https://dev.to/branch42-labs/chrome-wont-let-you-paste-into-the-console-type-allow-pasting-no-quotes-3fjh</link>
      <guid>https://dev.to/branch42-labs/chrome-wont-let-you-paste-into-the-console-type-allow-pasting-no-quotes-3fjh</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Paste once so the warning shows up. Then type &lt;code&gt;allow pasting&lt;/code&gt; in the Console prompt, without quotes, and press Enter. Paste again. Chrome remembers the choice for that profile.&lt;/p&gt;

&lt;p&gt;I set up a fresh Chrome profile last week, pasted a snippet into the Console, and got this instead of my code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Warning: Don't paste code into the DevTools Console that you don't understand or haven't reviewed yourself. This could allow attackers to steal your identity or take control of your computer. Type "allow pasting" below and press Enter to allow pasting.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you landed here from Google with that exact text in the search box, here is the short version and the parts that trip people up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the Console (&lt;code&gt;Ctrl+Shift+J&lt;/code&gt;, or &lt;code&gt;Cmd+Option+J&lt;/code&gt; on a Mac).&lt;/li&gt;
&lt;li&gt;Paste your code. Chrome blocks it and logs the warning.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;allow pasting&lt;/code&gt; and press Enter.&lt;/li&gt;
&lt;li&gt;Paste again. It lands in the prompt this time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the Sources panel (for example a snippet under Sources &amp;gt; Snippets) you get a dialog with a text field instead of a Console message. Type the same phrase there and confirm.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "allow pasting" sometimes doesn't work
&lt;/h2&gt;

&lt;p&gt;I looked at the DevTools source to see what it checks. It compares the prompt text against the phrase exactly, and only while the warning is active. So:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Paste first.&lt;/strong&gt; Typing the phrase before the warning appears does nothing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No double quotes.&lt;/strong&gt; The warning shows the phrase in double quotes, but &lt;code&gt;"allow pasting"&lt;/code&gt; is just a JS string. The Console echoes it and you are still blocked. Plain &lt;code&gt;allow pasting&lt;/code&gt; works, and so does &lt;code&gt;'allow pasting'&lt;/code&gt; with single quotes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No extra spaces or capitals.&lt;/strong&gt; Watch for autocomplete adding things.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-English DevTools&lt;/strong&gt; uses a translated phrase. Type the one in your warning.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why you don't see it on your main profile
&lt;/h2&gt;

&lt;p&gt;Chrome only shows the warning to profiles that look new to DevTools. If your Console history has at least 5 entries, it skips the warning entirely. The Chrome team wrote this up in &lt;a href="https://developer.chrome.com/blog/self-xss" rel="noopener noreferrer"&gt;How Chrome DevTools helps to defend against self-XSS attacks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It comes back when the stored setting is gone:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a new Chrome profile or a fresh install&lt;/li&gt;
&lt;li&gt;Settings &amp;gt; Preferences &amp;gt; &lt;strong&gt;Restore defaults and reload&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;a rare bug mentioned in the Chrome post, where a new profile is the suggested fix&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For CI and automation, launch Chrome with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--unsafely-disable-devtools-self-xss-warnings&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://developer.chrome.com/docs/automation-and-testing/chrome-for-testing" rel="noopener noreferrer"&gt;Chrome for Testing&lt;/a&gt; already has the warnings off. Edge is Chromium, so it behaves the same and takes the same flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reason it exists: self-XSS
&lt;/h2&gt;

&lt;p&gt;Self-XSS is the "paste this in your console to get free credits" scam. Whatever you paste runs as you on that site. It can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;read &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;sessionStorage&lt;/code&gt; and any cookie that isn't &lt;code&gt;HttpOnly&lt;/code&gt;, which is where a lot of apps keep tokens&lt;/li&gt;
&lt;li&gt;call the site's API with your session&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fetch&lt;/code&gt; all of it off to someone else's server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For us the phrase is a one-time speed bump. The habit worth keeping is reading every paste before you hit Enter.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safer habits for code you copied
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use a Snippet for anything you run twice.&lt;/strong&gt; Sources &amp;gt; Snippets &amp;gt; New snippet, paste, save, then &lt;code&gt;Ctrl+Enter&lt;/code&gt; / &lt;code&gt;Cmd+Enter&lt;/code&gt;. You can also run it from the Command Menu (&lt;code&gt;Ctrl+Shift+P&lt;/code&gt;, delete the &lt;code&gt;&amp;gt;&lt;/code&gt;, type &lt;code&gt;!snippet-name&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Read a copied fetch before running it.&lt;/strong&gt; Check that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the URL is the host you expect&lt;/li&gt;
&lt;li&gt;the method is what you want (&lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt; change data)&lt;/li&gt;
&lt;li&gt;the body is readable JSON or form data&lt;/li&gt;
&lt;li&gt;nothing extra wraps the call, like &lt;code&gt;eval&lt;/code&gt;, &lt;code&gt;atob&lt;/code&gt;, or a second &lt;code&gt;fetch&lt;/code&gt; that ships &lt;code&gt;document.cookie&lt;/code&gt; somewhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prefer cURL in a terminal if you only need the response.&lt;/strong&gt; It runs outside the page, so it can't touch page storage. It still carries your cookies and auth headers, so don't drop it into Slack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skipping the paste entirely
&lt;/h2&gt;

&lt;p&gt;Half the time I'm pasting because I copied a request as fetch and want to replay it with a tweak. I use &lt;a href="https://netraptor.dev" rel="noopener noreferrer"&gt;Netraptor&lt;/a&gt; for that now (disclosure: it's ours). It's a DevTools panel where you right-click a request and pick &lt;strong&gt;Resend&lt;/strong&gt;, or &lt;strong&gt;Edit and resend as fetch&lt;/strong&gt; to change the method, URL, headers or body first. It runs the request with &lt;code&gt;fetch&lt;/code&gt; inside the inspected page using the page's cookies, and the result shows up tagged &lt;code&gt;Resent&lt;/code&gt;. The same menu copies as cURL (bash/cmd), PowerShell, fetch or Node.js fetch. It only works on live traffic, since it needs the page you're inspecting.&lt;/p&gt;

&lt;p&gt;Full guide, with the Sources dialog and FAQ: &lt;a href="https://netraptor.dev/guides/allow-pasting-chrome-console" rel="noopener noreferrer"&gt;Allow pasting in the Chrome console&lt;/a&gt;&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>devtools</category>
      <category>javascript</category>
      <category>security</category>
    </item>
    <item>
      <title>How to create a HAR file in Chrome without leaking your tokens</title>
      <dc:creator>Parth V Square </dc:creator>
      <pubDate>Sun, 25 Oct 2026 08:54:55 +0000</pubDate>
      <link>https://dev.to/branch42-labs/how-to-create-a-har-file-in-chrome-without-leaking-your-tokens-3n68</link>
      <guid>https://dev.to/branch42-labs/how-to-create-a-har-file-in-chrome-without-leaking-your-tokens-3n68</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Open DevTools &amp;gt; Network, check &lt;strong&gt;Preserve log&lt;/strong&gt; and &lt;strong&gt;Disable cache&lt;/strong&gt;, clear, reload, reproduce the bug, then click &lt;strong&gt;Export HAR (sanitized)...&lt;/strong&gt;. Since Chrome 130 that export drops &lt;code&gt;Cookie&lt;/code&gt;, &lt;code&gt;Set-Cookie&lt;/code&gt; and &lt;code&gt;Authorization&lt;/code&gt;. Tokens in URLs, custom headers like &lt;code&gt;X-Api-Key&lt;/code&gt;, and request and response bodies are still in the file. Run a &lt;code&gt;grep&lt;/code&gt; over it before you attach it to a ticket.&lt;/p&gt;

&lt;p&gt;Every support team eventually asks for "a HAR file". Most of the bad ones I've seen came from the same three mistakes: DevTools opened too late, Preserve log off, or a filter left on. Here's the version that works on the first try.&lt;/p&gt;

&lt;h2&gt;
  
  
  The steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to the page with the problem and open DevTools (&lt;code&gt;F12&lt;/code&gt;, &lt;code&gt;Ctrl+Shift+I&lt;/code&gt;, or &lt;code&gt;Cmd+Option+I&lt;/code&gt; on macOS). Click &lt;strong&gt;Network&lt;/strong&gt;. Do this &lt;em&gt;before&lt;/em&gt; you reproduce anything, because Chrome only logs requests while DevTools is open.&lt;/li&gt;
&lt;li&gt;Check &lt;strong&gt;Preserve log&lt;/strong&gt; (so redirects and logins don't wipe the list) and &lt;strong&gt;Disable cache&lt;/strong&gt; (so you see what a first-time visitor sees).&lt;/li&gt;
&lt;li&gt;Click the clear button, then reload. Now the log starts from a clean page load.&lt;/li&gt;
&lt;li&gt;Reproduce the bug. Keep DevTools open until it has happened.&lt;/li&gt;
&lt;li&gt;Clear the Filter box and select &lt;strong&gt;All&lt;/strong&gt;. A leftover &lt;code&gt;Fetch/XHR&lt;/code&gt; chip is an easy way to ship half a file.&lt;/li&gt;
&lt;li&gt;Click the download icon, &lt;strong&gt;Export HAR (sanitized)...&lt;/strong&gt;, and save. Right-clicking any request gives you &lt;strong&gt;Save all as HAR (sanitized)&lt;/strong&gt; too.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the flow opens a popup or a new tab (hello, SSO), those requests land in &lt;em&gt;that&lt;/em&gt; tab's DevTools. Turn on &lt;strong&gt;Auto-open DevTools for popups&lt;/strong&gt; in DevTools settings first.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Sanitized" covers three headers
&lt;/h2&gt;

&lt;p&gt;Chrome 130 changed the default export (&lt;a href="https://developer.chrome.com/blog/new-in-devtools-130" rel="noopener noreferrer"&gt;release notes&lt;/a&gt;). The sanitized file leaves out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Cookie&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Set-Cookie&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Authorization&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the whole list. If you actually need those headers, say to debug your own auth flow, go to DevTools &lt;strong&gt;Settings &amp;gt; Preferences &amp;gt; Network&lt;/strong&gt;, check &lt;strong&gt;Allow to generate HAR with sensitive data&lt;/strong&gt;, then long-click the Export button and pick &lt;strong&gt;Export HAR (with sensitive data)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Edge behaves the same since it's the same DevTools. Firefox (Network Monitor gear menu &amp;gt; &lt;strong&gt;Persist Logs&lt;/strong&gt;, then &lt;strong&gt;Save All As HAR&lt;/strong&gt;) and Safari (Web Inspector &amp;gt; Network &amp;gt; &lt;strong&gt;Preserve Log&lt;/strong&gt;, then &lt;strong&gt;Export&lt;/strong&gt;) put cookies and auth headers in the file along with everything else.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's still in a sanitized HAR
&lt;/h2&gt;

&lt;p&gt;Things I've found in "sanitized" HAR files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;X-Api-Key&lt;/code&gt;, &lt;code&gt;X-CSRF-Token&lt;/code&gt;, &lt;code&gt;X-Auth-Token&lt;/code&gt; headers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;?access_token=...&lt;/code&gt; and &lt;code&gt;?api_key=...&lt;/code&gt; in URLs, including inside &lt;code&gt;Referer&lt;/code&gt; and &lt;code&gt;Location&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;OAuth &lt;code&gt;?code=&lt;/code&gt; values on the login redirect&lt;/li&gt;
&lt;li&gt;The password in a login request body, in plain text&lt;/li&gt;
&lt;li&gt;Refresh tokens in token-exchange calls and fresh access tokens in login responses&lt;/li&gt;
&lt;li&gt;Names, emails and addresses in ordinary API responses&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Scrubbing it
&lt;/h2&gt;

&lt;p&gt;First, record less. Log in, clear the log, then reproduce only the failing steps.&lt;/p&gt;

&lt;p&gt;Then strip the headers you know about. With &lt;code&gt;jq&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jq &lt;span class="s1"&gt;'.log.entries[] |= (
  .request.headers |= map(select(.name | test("^(cookie|authorization|x-api-key)$"; "i") | not))
  | .response.headers |= map(select(.name | test("^set-cookie$"; "i") | not))
  | .request.cookies = []
  | .response.cookies = []
)'&lt;/span&gt; session.har &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; session.scrubbed.har
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Headers are the easy part. Now look for everything else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s1"&gt;'token|secret|password|api[_-]?key|bearer|eyJ'&lt;/span&gt; session.scrubbed.har
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;eyJ&lt;/code&gt; catches JWTs, because &lt;code&gt;{"&lt;/code&gt; base64-encodes to &lt;code&gt;eyJ&lt;/code&gt;. Every hit is a value to replace by hand or a step to leave out of the recording. Google's &lt;a href="https://toolbox.googleapps.com/apps/har_analyzer/" rel="noopener noreferrer"&gt;HAR Analyzer&lt;/a&gt; can also download a redacted copy. Whatever you couldn't remove, log out or rotate the key once the ticket is closed.&lt;/p&gt;

&lt;h2&gt;
  
  
  A sanitizer that also reads URLs and bodies
&lt;/h2&gt;

&lt;p&gt;I work on &lt;a href="https://netraptor.dev" rel="noopener noreferrer"&gt;Netraptor&lt;/a&gt;, a Chrome extension that adds its own Network panel to DevTools, and its &lt;strong&gt;Save all as HAR (sanitized)&lt;/strong&gt; goes further than Chrome's. It drops any header with a credential-like name (token, secret, password, session, auth, csrf, jwt, key, and so on), sets matching query and fragment params plus OAuth &lt;code&gt;code&lt;/code&gt; to &lt;code&gt;[redacted]&lt;/code&gt;, redacts matching keys at any depth in JSON and form bodies, and removes bodies it can't parse (HTML, text, binary) with a comment saying so. It saves only the rows you have filtered to, so you can export just the failing calls. It matches on field names, so an email under &lt;code&gt;email&lt;/code&gt; or a token in a URL path still gets through. Run the &lt;code&gt;grep&lt;/code&gt; anyway.&lt;/p&gt;

&lt;p&gt;The full guide, with FAQ and a section on why HAR files come out empty, is here: &lt;a href="https://netraptor.dev/guides/create-har-file-in-chrome" rel="noopener noreferrer"&gt;How to create a HAR file in Chrome&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>devtools</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Chrome's Network tab keeps clearing on reload. Here's how to stop it</title>
      <dc:creator>Parth V Square </dc:creator>
      <pubDate>Sun, 25 Oct 2026 08:54:33 +0000</pubDate>
      <link>https://dev.to/branch42-labs/chromes-network-tab-keeps-clearing-on-reload-heres-how-to-stop-it-1f30</link>
      <guid>https://dev.to/branch42-labs/chromes-network-tab-keeps-clearing-on-reload-heres-how-to-stop-it-1f30</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; In Chrome DevTools, open the Network panel and tick &lt;strong&gt;Preserve log&lt;/strong&gt;. Requests then survive reloads and redirects. They still vanish when you close DevTools, anything before DevTools opened is missing, and every page load lands in one unlabelled list. In Firefox the option is &lt;strong&gt;Persist Logs&lt;/strong&gt;, under the gear icon in the Network Monitor.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;You're debugging a login. The form posts, the server redirects, and the request you needed is gone. Chrome's Network panel clears its list every time the main frame loads a new document. That covers reloads, links, form posts and server redirects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Turn on Preserve log
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open DevTools &lt;strong&gt;before&lt;/strong&gt; loading the page (&lt;code&gt;F12&lt;/code&gt;, or &lt;code&gt;Cmd+Option+I&lt;/code&gt; on macOS). Chrome only records requests while DevTools is open.&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;Network&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;Tick &lt;strong&gt;Preserve log&lt;/strong&gt; in the action bar at the top.&lt;/li&gt;
&lt;li&gt;Reproduce the reload or redirect. The old requests stay put and new ones are added below them.&lt;/li&gt;
&lt;li&gt;Before you close DevTools, export a HAR (download icon in the action bar) if you want to keep any of it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Console has its own Preserve log in its settings. Turn that on too if you want console messages to survive the reload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it falls short
&lt;/h2&gt;

&lt;p&gt;I hit these regularly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Closing DevTools wipes it.&lt;/strong&gt; The preserved log lives in the DevTools window. Close it and the log is gone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The first load is often missing.&lt;/strong&gt; If the page loaded before you opened DevTools, those requests were never recorded. Reload with DevTools open. For popups, start Chrome with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  google-chrome &lt;span class="nt"&gt;--auto-open-devtools-for-tabs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you need a capture that doesn't depend on DevTools at all, &lt;code&gt;chrome://net-export&lt;/code&gt; writes a browser-level NetLog.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One flat list.&lt;/strong&gt; After five reloads you have five copies of &lt;code&gt;/api/me&lt;/code&gt; and nothing telling you which load each one belongs to. You end up reading the order of the document requests and the waterfall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SPAs never clear anyway.&lt;/strong&gt; A &lt;code&gt;history.pushState&lt;/code&gt; route change isn't a document load, so the log never clears. With or without Preserve log, every route's API calls pile into the same list with no marker between them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Disable cache is a different job
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Disable cache&lt;/strong&gt; sits right next to it. Preserve log decides whether the list survives a reload. Disable cache decides whether the requests in it hit the network or come from the HTTP cache (only while DevTools is open). If a request seems missing after a reload, check whether it came from the memory or disk cache before you assume it never ran.&lt;/p&gt;

&lt;h2&gt;
  
  
  Firefox: Persist Logs
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open the Network Monitor (&lt;code&gt;Ctrl+Shift+E&lt;/code&gt;, or &lt;code&gt;Cmd+Option+E&lt;/code&gt; on macOS).&lt;/li&gt;
&lt;li&gt;Click the gear icon at the right end of the Network toolbar.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Persist Logs&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Web Console has its own Persist Logs setting too. The limits are the same as Chrome's.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I use when the flat list gets in the way
&lt;/h2&gt;

&lt;p&gt;I work on &lt;a href="https://netraptor.dev" rel="noopener noreferrer"&gt;Netraptor&lt;/a&gt;, a Chrome extension with its own DevTools panel, and this was one of the gaps we wanted to close. When you open the panel it pulls in what DevTools already logged for the page. After that, each reload, navigation or SPA route change (&lt;code&gt;pushState&lt;/code&gt;, &lt;code&gt;replaceState&lt;/code&gt;, back/forward) starts a group labelled "Reloaded" or "Navigated to" with the path, time and request count. Earlier loads fold away rather than being deleted. If you turn on "Keep history for this site", it saves that site's fetch/XHR calls to IndexedDB, so they're still there after you close DevTools.&lt;/p&gt;

&lt;p&gt;The full guide, with steps and FAQ, is here: &lt;a href="https://netraptor.dev/guides/preserve-network-log-chrome" rel="noopener noreferrer"&gt;Preserve log in Chrome: keep network requests after a page reload&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>chrome</category>
      <category>devtools</category>
      <category>debugging</category>
    </item>
    <item>
      <title>What is a HAR file, and how to get one from Chrome</title>
      <dc:creator>Parth V Square </dc:creator>
      <pubDate>Fri, 23 Oct 2026 19:04:44 +0000</pubDate>
      <link>https://dev.to/branch42-labs/what-is-a-har-file-and-how-to-get-one-from-chrome-1olo</link>
      <guid>https://dev.to/branch42-labs/what-is-a-har-file-and-how-to-get-one-from-chrome-1olo</guid>
      <description>&lt;p&gt;A HAR file (HTTP Archive) is a JSON file that records every network request a browser made while a page was open, including URLs, headers, request bodies, responses and timings. Support teams ask for one because it shows exactly what your browser sent and received when something broke. You can generate a HAR file in Chrome from the Network panel in DevTools in under a minute.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I build &lt;a href="https://netraptor.dev?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=launch_oct26_organic&amp;amp;utm_content=what-is-a-har-file" rel="noopener noreferrer"&gt;Netraptor&lt;/a&gt;, which this guide mentions as one option. The steps work with plain Chrome and free tools.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open the Network panel.&lt;/strong&gt; Go to the page with the problem and open DevTools with F12, &lt;code&gt;Ctrl+Shift+I&lt;/code&gt; on Windows and Linux, or &lt;code&gt;Cmd+Option+I&lt;/code&gt; on macOS. Click the Network tab.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn on Preserve log.&lt;/strong&gt; Check Preserve log so requests are kept across page loads and redirects. Check Disable cache too if the problem only shows up on a fresh load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproduce the problem.&lt;/strong&gt; Reload the page and repeat the exact steps that cause the issue. DevTools only records while it is open, so keep it open the whole time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export the HAR file.&lt;/strong&gt; Click the download icon, Export HAR (sanitized)..., in the action bar at the top of the Network panel, and choose where to save the file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Check the file before sharing.&lt;/strong&gt; Open the &lt;code&gt;.har&lt;/code&gt; file in a text editor and search for tokens, emails or other secrets before you send it to anyone.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is a HAR file?
&lt;/h2&gt;

&lt;p&gt;HAR stands for HTTP Archive. A HAR file is plain JSON with a &lt;code&gt;.har&lt;/code&gt; extension that describes a browser's network activity: one entry per request, grouped under the pages that triggered them. Chrome, Edge, Firefox and Safari can all export it, and most debugging tools can read it.&lt;/p&gt;

&lt;p&gt;The format was drafted as HAR 1.2 for the W3C Web Performance Working Group. That draft was never published as a standard and is now marked as abandoned, but browsers still write files that follow it. A trimmed HAR file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"log"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"creator"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WebInspector"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"537.36"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"pages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"page_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://app.example.com/"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"entries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"pageref"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"page_1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"startedDateTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-10-16T09:12:03.120Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;184.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://app.example.com/api/orders"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"statusText"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"timings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"blocked"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"dns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"connect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"send"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"wait"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;176.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"receive"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What's inside a HAR file
&lt;/h2&gt;

&lt;p&gt;Each entry in &lt;code&gt;log.entries&lt;/code&gt; captures one request and its response. The fields you will look at most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;request&lt;/code&gt;: method, full URL, query string, headers, cookies and the request body (&lt;code&gt;postData&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;response&lt;/code&gt;: status code, headers, cookies, MIME type and usually the response body in &lt;code&gt;content.text&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;timings&lt;/code&gt;: how long the request spent blocked, on DNS, connecting, sending, waiting for the server (&lt;code&gt;wait&lt;/code&gt;) and downloading (&lt;code&gt;receive&lt;/code&gt;), in milliseconds.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;startedDateTime&lt;/code&gt; and &lt;code&gt;time&lt;/code&gt;: when the request began and how long it took in total.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pages&lt;/code&gt;: the page loads the requests belong to, so you can tell which navigation triggered what.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because it holds full headers and bodies, a HAR file is often the fastest way for someone else to see a failed API call, a slow request or a bad redirect without access to your account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Export HAR (sanitized) vs. with sensitive data
&lt;/h2&gt;

&lt;p&gt;Since Chrome 130, the default HAR export is sanitized: it leaves out the &lt;code&gt;Cookie&lt;/code&gt;, &lt;code&gt;Set-Cookie&lt;/code&gt; and &lt;code&gt;Authorization&lt;/code&gt; headers. This change was made to cut down on accidental leaks of login sessions when people attach HAR files to support tickets.&lt;/p&gt;

&lt;p&gt;If you need those headers, for example to debug your own auth flow, open DevTools Settings &amp;gt; Preferences &amp;gt; Network and turn on Allow to generate HAR with sensitive data. The Export HAR button then offers both a sanitized and a sensitive-data option. See the &lt;a href="https://developer.chrome.com/docs/devtools/network/reference" rel="noopener noreferrer"&gt;Network features reference&lt;/a&gt; for the current labels.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Sanitized only removes those three headers. Tokens in URLs, request bodies, custom headers like &lt;code&gt;X-Api-Key&lt;/code&gt; and response bodies are still in the file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How to get a HAR file in Edge, Firefox and Safari
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Microsoft Edge uses the same DevTools as Chrome. Follow the steps above.&lt;/li&gt;
&lt;li&gt;Firefox: open the Network Monitor (&lt;code&gt;Ctrl+Shift+E&lt;/code&gt; or &lt;code&gt;Cmd+Option+E&lt;/code&gt;), reproduce the issue, then right-click any request and choose Save All As HAR.&lt;/li&gt;
&lt;li&gt;Safari: enable the Develop menu in Safari settings, open Web Inspector, go to the Network tab, reproduce the issue and click Export.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whichever browser you use, start recording before you reproduce the problem. A HAR file only contains requests made while the network tools were open.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it safe to share a HAR file?
&lt;/h2&gt;

&lt;p&gt;Treat a HAR file like a password. A file exported with sensitive data contains session cookies and bearer tokens, and anyone who has it can often act as you until those expire. Even a sanitized file can include personal data from API responses, IDs in URLs and API keys in custom headers.&lt;/p&gt;

&lt;p&gt;Before you share one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the sanitized export unless the recipient specifically needs auth headers.&lt;/li&gt;
&lt;li&gt;Record in a fresh tab with only the steps needed to reproduce the issue, so unrelated traffic stays out of the file.&lt;/li&gt;
&lt;li&gt;Search the file for &lt;code&gt;token&lt;/code&gt;, &lt;code&gt;key&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;secret&lt;/code&gt; and your email address.&lt;/li&gt;
&lt;li&gt;Log out after sending a file that included cookies. That invalidates the session on most sites.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Google's &lt;a href="https://toolbox.googleapps.com/apps/har_analyzer/" rel="noopener noreferrer"&gt;HAR Analyzer&lt;/a&gt; also has a redaction button that downloads a copy with sensitive values removed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Doing this with Netraptor
&lt;/h2&gt;

&lt;p&gt;Chrome's Network panel records everything, but only while DevTools is open, and you have to remember to turn on Preserve log first. If you capture the same app often, &lt;a href="https://netraptor.dev/" rel="noopener noreferrer"&gt;Netraptor&lt;/a&gt; can record it in the background instead.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In the Netraptor toolbar popup, turn on Record this site. It records the fetch and XHR API traffic for that domain and its subdomains across page loads, with or without DevTools open.&lt;/li&gt;
&lt;li&gt;Open the Netraptor panel in DevTools to browse the recorded requests in a Chrome-style Requests table, or group them by endpoint in API Map.&lt;/li&gt;
&lt;li&gt;On the Export tab, export a HAR file. Strip auth headers and cookies is on by default, so the file is safer to share.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;HAR export is part of the Free plan, along with Postman and curl exports. Everything stays in your browser and no account is needed. Netraptor records API calls only, so if you need images, scripts and the full page-load waterfall in the file, use Chrome's own export.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to do with a HAR file next
&lt;/h2&gt;

&lt;p&gt;Once you have the file, you can load it back into Chrome DevTools, open it in an online viewer or query it with &lt;code&gt;jq&lt;/code&gt;. See &lt;a href="https://netraptor.dev/guides/how-to-open-a-har-file" rel="noopener noreferrer"&gt;how to open and analyze a HAR file&lt;/a&gt;. If you want to replay the requests you captured, turn them into a &lt;a href="https://netraptor.dev/guides/create-postman-collection-from-browser" rel="noopener noreferrer"&gt;Postman collection&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What does HAR stand for?
&lt;/h3&gt;

&lt;p&gt;HAR stands for HTTP Archive. It is a JSON-based format for logging a browser's network requests and responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is my HAR file empty?
&lt;/h3&gt;

&lt;p&gt;DevTools only records network traffic while it is open. Open the Network panel first, check Preserve log, then reload the page and reproduce the problem before exporting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I open a HAR file in Notepad?
&lt;/h3&gt;

&lt;p&gt;Yes. A HAR file is plain JSON text, so any text editor can open it. For a readable request list, import it into the Chrome DevTools Network panel or a HAR viewer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a HAR file contain my password?
&lt;/h3&gt;

&lt;p&gt;It can. If you log in while recording, the login request body may include your password in plain text. Record after logging in, or check the file before sharing it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why are cookies missing from my HAR file?
&lt;/h3&gt;

&lt;p&gt;Chrome exports sanitized HAR files by default and strips the Cookie, Set-Cookie and Authorization headers. Turn on Allow to generate HAR with sensitive data in DevTools settings if you need them.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://netraptor.dev/guides/what-is-a-har-file?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=launch_oct26_organic&amp;amp;utm_content=what-is-a-har-file" rel="noopener noreferrer"&gt;netraptor.dev/guides/what-is-a-har-file&lt;/a&gt;. More guides: &lt;a href="https://netraptor.dev/guides?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=launch_oct26_organic&amp;amp;utm_content=what-is-a-har-file" rel="noopener noreferrer"&gt;netraptor.dev/guides&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>devtools</category>
      <category>chrome</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What is an OpenAPI spec, and how to generate one from your web app's traffic</title>
      <dc:creator>Parth V Square </dc:creator>
      <pubDate>Fri, 23 Oct 2026 19:04:12 +0000</pubDate>
      <link>https://dev.to/branch42-labs/what-is-an-openapi-spec-and-how-to-generate-one-from-your-web-apps-traffic-24oh</link>
      <guid>https://dev.to/branch42-labs/what-is-an-openapi-spec-and-how-to-generate-one-from-your-web-apps-traffic-24oh</guid>
      <description>&lt;p&gt;An OpenAPI spec is a JSON or YAML document that describes an HTTP API in a standard, language-agnostic format, listing its paths, methods, parameters, request bodies and responses. If your API has no spec yet, you can generate a first draft from real traffic by recording the requests your web app makes in Chrome, exporting them as a HAR file, and converting that file with an open-source tool such as mitmproxy2swagger. You then review the draft by hand, because traffic only shows what was actually called.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: I build &lt;a href="https://netraptor.dev?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=launch_oct26_organic&amp;amp;utm_content=generate-openapi-spec-from-traffic" rel="noopener noreferrer"&gt;Netraptor&lt;/a&gt;, which this guide mentions as one option. The steps work with plain Chrome and free tools.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Steps
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Record the app's API calls in Chrome.&lt;/strong&gt; Open DevTools (F12, or Cmd+Option+I on a Mac), go to the Network panel, check Preserve log, click the Fetch/XHR filter and reload the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use every feature you want in the spec.&lt;/strong&gt; Sign in with a test account and walk through each screen. Create, edit and delete test records so every endpoint and HTTP method shows up at least once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export a HAR file.&lt;/strong&gt; Click Export HAR (sanitized) in the Network panel toolbar and save the file as &lt;code&gt;app.har&lt;/code&gt;. The sanitized export leaves out &lt;code&gt;Cookie&lt;/code&gt;, &lt;code&gt;Set-Cookie&lt;/code&gt; and &lt;code&gt;Authorization&lt;/code&gt; headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run a first pass with mitmproxy2swagger.&lt;/strong&gt; Install it with &lt;code&gt;pip install mitmproxy2swagger&lt;/code&gt;, then run &lt;code&gt;mitmproxy2swagger -i app.har -o openapi.yaml -p https://api.example.com&lt;/code&gt;. The output lists every discovered path under &lt;code&gt;x-path-templates&lt;/code&gt;, each prefixed with &lt;code&gt;ignore:&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick the paths and run it again.&lt;/strong&gt; Remove the &lt;code&gt;ignore:&lt;/code&gt; prefix from the paths you want, fix templates such as &lt;code&gt;/users/{id}&lt;/code&gt;, and run the same command again. The second pass writes the operations into &lt;code&gt;paths&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validate and edit the result.&lt;/strong&gt; Paste the file into &lt;a href="https://editor.swagger.io/" rel="noopener noreferrer"&gt;Swagger Editor&lt;/a&gt; or run &lt;code&gt;openapi-generator-cli validate -i openapi.yaml&lt;/code&gt;. Then add descriptions, required fields, error responses and auth by hand.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What is OpenAPI?
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://spec.openapis.org/oas/latest.html" rel="noopener noreferrer"&gt;OpenAPI Specification&lt;/a&gt; (OAS) defines a standard, programming-language-agnostic way to describe HTTP APIs. A tool or a person can read an OpenAPI document and learn which endpoints exist, what each one accepts and what it returns, without reading the server code.&lt;/p&gt;

&lt;p&gt;OpenAPI started as the Swagger Specification. SmartBear donated it to the OpenAPI Initiative under the Linux Foundation in late 2015, and it was renamed in early 2016. Today "OpenAPI" is the name of the format, and "Swagger" usually refers to SmartBear's tools such as Swagger UI and Swagger Editor.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://spec.openapis.org/oas/" rel="noopener noreferrer"&gt;published versions&lt;/a&gt; are 2.0, the 3.0.x line, the 3.1.x line and the 3.2.x line, with 3.2.1 the newest. Version 3.1 aligned its Schema Object with JSON Schema draft 2020-12, and most current tools read 3.0 and 3.1. If a tool you rely on rejects a newer version, check its docs before choosing.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does an OpenAPI spec look like? (JSON and YAML)
&lt;/h2&gt;

&lt;p&gt;An OpenAPI document is one JSON or YAML file, conventionally named &lt;code&gt;openapi.json&lt;/code&gt; or &lt;code&gt;openapi.yaml&lt;/code&gt;. It must have an &lt;code&gt;openapi&lt;/code&gt; version field and an &lt;code&gt;info&lt;/code&gt; object, plus at least one of &lt;code&gt;paths&lt;/code&gt;, &lt;code&gt;components&lt;/code&gt; or &lt;code&gt;webhooks&lt;/code&gt;. Path parameters are written in curly braces, and every placeholder must match a parameter definition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;openapi&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3.1.0&lt;/span&gt;
&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Example app API&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1.0.0&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="s"&gt;/users/{id}&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Get a user&lt;/span&gt;
      &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;id&lt;/span&gt;
          &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;path&lt;/span&gt;
          &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;200"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;The user&lt;/span&gt;
          &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;application/json&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;object&lt;/span&gt;
                &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
                  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;string&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON form holds the same structure with braces and quotes. YAML is easier to edit by hand, JSON is easier to generate and parse, and most tools accept either.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a spec generated from traffic will miss
&lt;/h2&gt;

&lt;p&gt;Recorded traffic shows real requests and responses, which makes it a good starting point. It also has gaps you need to fill before anyone treats the file as documentation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Endpoints you never triggered are missing. Admin screens, error paths and rarely used features only appear if you exercise them.&lt;/li&gt;
&lt;li&gt;Schemas are inferred from examples. A field that was &lt;code&gt;null&lt;/code&gt; in every response, or an optional field you never sent, will be typed loosely or left out.&lt;/li&gt;
&lt;li&gt;Path parameters need checking. Generators guess which segments are IDs, so &lt;code&gt;/users/42&lt;/code&gt; and &lt;code&gt;/users/me&lt;/code&gt; can end up merged or split the wrong way.&lt;/li&gt;
&lt;li&gt;Auth is usually missing. Add a &lt;code&gt;securitySchemes&lt;/code&gt; entry under &lt;code&gt;components&lt;/code&gt; (for example a bearer token) and a &lt;code&gt;security&lt;/code&gt; requirement yourself.&lt;/li&gt;
&lt;li&gt;Enums, formats, limits and descriptions come from you, not the traffic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treat the generated file as a draft. One careful review pass usually turns it into something your team can rely on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it safe to generate a spec from production traffic?
&lt;/h2&gt;

&lt;p&gt;Be careful with what goes into the HAR file and the spec. Chrome's sanitized HAR export removes &lt;code&gt;Cookie&lt;/code&gt;, &lt;code&gt;Set-Cookie&lt;/code&gt; and &lt;code&gt;Authorization&lt;/code&gt; headers, but request and response bodies stay in the file, and so do tokens passed in URLs or custom headers.&lt;/p&gt;

&lt;p&gt;mitmproxy2swagger adds example data only when you pass &lt;code&gt;--examples&lt;/code&gt; (and headers with &lt;code&gt;--headers&lt;/code&gt;). Its README warns that this can include sensitive data. If you want examples in the spec, record against a test account with fake data, then read the examples before you commit or share the file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Record traffic only from apps you build, test or are authorised to test, and prefer a staging environment over production.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What to do with an OpenAPI spec once you have one
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Publish docs. Swagger UI and similar tools render the file as browsable reference pages.&lt;/li&gt;
&lt;li&gt;Generate clients and server stubs. &lt;a href="https://openapi-generator.tech/docs/usage" rel="noopener noreferrer"&gt;OpenAPI Generator&lt;/a&gt; takes &lt;code&gt;-i&lt;/code&gt; (the spec), &lt;code&gt;-g&lt;/code&gt; (a generator such as &lt;code&gt;typescript-fetch&lt;/code&gt;) and &lt;code&gt;-o&lt;/code&gt; (an output folder).&lt;/li&gt;
&lt;li&gt;Test against it. The spec becomes a contract you can check the real API against in CI.&lt;/li&gt;
&lt;li&gt;Import it into Postman. Postman imports OpenAPI 3.0 and 3.1 as a collection. See &lt;a href="https://netraptor.dev/guides/create-postman-collection-from-browser" rel="noopener noreferrer"&gt;Create a Postman collection from a website's requests&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you only need the list of endpoints and not a full spec, &lt;a href="https://netraptor.dev/guides/find-api-endpoints-of-a-web-app" rel="noopener noreferrer"&gt;Find every API endpoint your web app calls&lt;/a&gt; covers the DevTools side in more detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Faster: generate the spec with Netraptor
&lt;/h2&gt;

&lt;p&gt;Netraptor is a Chrome extension with its own DevTools panel. It shortens the record, convert and template steps above, and everything stays local in your browser.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Turn on "Record this site" in the toolbar popup. Netraptor records fetch/XHR API traffic for that domain and its subdomains across page loads, even with DevTools closed.&lt;/li&gt;
&lt;li&gt;Optionally run "Crawl this site" to visit same-origin links in your logged-in tab. It skips logout and delete-looking links. Free crawls cover 25 pages, Pro up to 1000.&lt;/li&gt;
&lt;li&gt;Check the API Map tab. Endpoints are grouped and IDs are already parameterized, for example &lt;code&gt;/users/{id}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the Export tab, export OpenAPI 3.1 as YAML or JSON, with optional response samples. "Strip auth headers and cookies" is on by default.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OpenAPI export is part of Pro ($29.99 one-time, no subscription). The Free plan exports HAR, Postman Collection v2.1 and curl, so you can export a HAR from Netraptor and run it through mitmproxy2swagger instead. You still review the generated spec by hand either way.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is OpenAPI the same as Swagger?
&lt;/h3&gt;

&lt;p&gt;OpenAPI is the specification, and it was called the Swagger Specification until 2016. Swagger now refers to SmartBear's tools, such as Swagger UI and Swagger Editor, that work with OpenAPI files.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use OpenAPI 3.0, 3.1 or 3.2?
&lt;/h3&gt;

&lt;p&gt;Use 3.1 unless a tool in your pipeline only supports 3.0. Version 3.1 matches JSON Schema 2020-12, and 3.2 is newer, so check tool support before adopting it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is OpenAPI Generator?
&lt;/h3&gt;

&lt;p&gt;OpenAPI Generator is an open-source CLI that turns an OpenAPI document into client SDKs, server stubs and docs for many languages. It also has a &lt;code&gt;validate&lt;/code&gt; command for checking a spec.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I generate an OpenAPI spec from code instead of traffic?
&lt;/h3&gt;

&lt;p&gt;Yes, if you own the backend. Many frameworks, FastAPI for example, produce a spec from route definitions, and that is usually more complete than one inferred from traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between openapi.json and openapi.yaml?
&lt;/h3&gt;

&lt;p&gt;They hold the same document in two syntaxes. The spec allows both, and most tools accept either.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://netraptor.dev/guides/generate-openapi-spec-from-traffic?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=launch_oct26_organic&amp;amp;utm_content=generate-openapi-spec-from-traffic" rel="noopener noreferrer"&gt;netraptor.dev/guides/generate-openapi-spec-from-traffic&lt;/a&gt;. More guides: &lt;a href="https://netraptor.dev/guides?utm_source=devto&amp;amp;utm_medium=community&amp;amp;utm_campaign=launch_oct26_organic&amp;amp;utm_content=generate-openapi-spec-from-traffic" rel="noopener noreferrer"&gt;netraptor.dev/guides&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>openapi</category>
      <category>api</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
