Most developers are comfortable using the standard Network and Elements tabs, but there comes a point in every complex project where the built-in tools aren’t enough. Whether you’re managing a complex state machine or debugging a proprietary protocol, knowing how to create a Chrome DevTools extension allows you to bring your internal application data directly into the browser’s native debugging environment.

In my experience building internal tooling for large-scale React apps, I’ve found that custom panels reduce debugging time by 30-40% because they eliminate the need to constantly console.log large objects. Instead of guessing, you can visualize your data in real-time.

The Challenge: The DevTools Architecture Gap

Creating a DevTools extension is fundamentally different from creating a standard Chrome extension. While a typical extension might use a popup or an options page, a DevTools extension operates across three distinct layers: the Extension Background, the DevTools Page, and the DevTools Panel.

The main challenge is that the DevTools panel lives in an isolated environment. It cannot directly access the DOM of the page you are inspecting. To bridge this gap, you must implement a messaging system that routes data from the inspected page, through the DevTools page, and finally into your custom UI panel.

Solution Overview: The Communication Pipeline

To successfully implement this, we use a ‘bridge’ pattern. Here is the high-level flow:

If you’re coming from a background of using other tools, you might find this similar to how the React Developer Tools extension guide describes the bridge between the React internals and the browser UI.

Implementation: Building Your First Panel

Step 1: The Manifest File

Your manifest.json must explicitly define the devtools_page. This is the entry point that Chrome looks for when the DevTools window opens.


{
  "manifest_version": 3,
  "name": "Custom Debugger",
  "version": "1.0",
  "devtools_page": "devtools.html",
  "permissions": ["tabs", "storage"]
}

Step 2: The DevTools Coordinator

The devtools.html file is not a visible page; it’s a script loader. It should simply link to a JavaScript file that creates the panel.

// devtools.js
chrome.devtools.panels.create(
  "My Debugger", // Panel title
  "icon.png",     // Panel icon
  "panel.html",   // The HTML file for the panel UI
  function(panel) {
    console.log("Custom panel created!");
  }
);

Step 3: The Panel UI and Data Fetching

In your panel.html and associated JS, you can now use the chrome.devtools.inspectedWindow API. This is the secret sauce for interacting with the page being debugged.

// panel.js
async function getAppData() {
  // This executes code directly in the context of the inspected page
  const result = await chrome.devtools.inspectedWindow.eval("window.myAppState");
  document.getElementById('output').innerText = JSON.stringify(result, null, 2);
}

setInterval(getAppData, 1000); // Poll for state changes
Screenshot of Chrome DevTools showing a custom 'My Debugger' panel alongside the Elements tab
Screenshot of Chrome DevTools showing a custom ‘My Debugger’ panel alongside the Elements tab

As shown in the diagram above, this eval call bypasses the standard content script limitations, allowing you to pull variables directly from the page’s global window object.

Case Study: Debugging a WebSocket State Machine

I recently used this approach to debug a real-time trading dashboard. The app had a complex internal state for WebSocket connections that was invisible to the Network tab. By creating a custom DevTools panel, I was able to:

  1. Visualize the current connection state (Connecting, Open, Closing).
  2. Trigger manual ‘reconnect’ events via inspectedWindow.eval().
  3. Log incoming binary packets into a human-readable table.

This was significantly faster than adding a hidden HTML overlay to the app itself, as it kept the production UI clean while providing deep technical insights.

Common Pitfalls and Pitfalls

During my testing, I encountered a few recurring issues that you should watch out for:

For those looking to improve their general debugging workflow before diving into custom extensions, I recommend checking out my list of the best devtools extensions for debugging JavaScript to see what patterns already exist.

Summary: When to Build Your Own

Building a custom extension is a high-effort, high-reward task. If you only need to see a few variables, stick to console.log or the standard Sources tab. However, if you are building a framework, a complex library, or a highly state-dependent application, a custom DevTools panel is the gold standard for developer experience (DX).