The DevTools Map
DevTools is a set of windows onto the engine, and each window faces one subsystem. This part is the map from subsystem to panel, how the whole thing works over a JSON protocol that scripts can speak too, the seven kinds of breakpoint and what each one answers, the console as an instrument, the panels most people have not opened, the chrome:// pages underneath, and a triage procedure from symptom to the panel that explains it.
The map: which panel watches which subsystem
"I know what DevTools is. I do not know, for a given symptom, which panel to open first."
DevTools is a set of windows onto the pipeline from part 0. Each panel attaches to one or two stages. Knowing the attachment is what makes the first panel the right one. This part is the map; the DevTools course goes panel by panel in depth with a lab app built for it.
| Subsystem | Panel or pane | What it exposes | Open it for |
|---|---|---|---|
| Network service | Network | Requests, priority, timing, headers, initiator chain, cache and SW hits, throttling | Slow TTFB, wrong priority, blocked requests, CORS, cookies not sent |
| HTML parser | Performance (Parse HTML), Network initiator | Parse tasks, what the preload scanner started | Render-blocking discovery, late resources |
| DOM | Elements; Console ($0, $$); DOM breakpoints | The live tree, who changes it | Markup not as expected, mutation origin |
| Style engine | Styles, Computed, Performance (Recalculate Style with selector stats) | Cascade order, overridden rules, resolved values, selector cost | Why this value, slow recalc |
| Layout | Layout pane, Elements overlays, Performance (Layout, forced reflow) | Grid and flex geometry, box model, layout thrash with stacks | Why is it here, why is layout slow |
| Paint and compositor | Rendering tab, Layers, Performance (Paint, Composite, Frames) | What repainted, layer tree and reasons, dropped frames | Jank, layer explosion, scroll stutter |
| Event loop and V8 | Performance (Main lane, Bottom-Up), Sources, Console | Tasks, long tasks, functions by cost, breakpoints | Slow interactions, blocked input, bugs |
| Memory | Memory, Performance monitor | Heap snapshots, retainers, allocation timeline, live counts | Leaks, GC pauses |
| Workers and SW | Sources (Threads), Application (Service Workers), Network (SW column) | Worker debugging, SW lifecycle, SW-answered requests | Worker bugs, stale cache, update stuck |
| Storage | Application | Every storage API, quota, clear and simulate | Data not persisting, quota, partition confusion |
| Security | Security, Issues, Network headers, Application → Frames | Certificates, mixed content, CSP and CORS violations, isolation state | Padlock broken, blocked script, SAB unavailable |
| Navigation and lifecycle | Application (bfcache, Speculative loads), Network (Preserve log), Event listener breakpoints | bfcache blockers, prerender state, lifecycle events | Back is slow, prerender not firing |
| Accessibility | Elements → Accessibility; full a11y tree; Lighthouse | Roles, names, the tree AT reads | Unnamed controls, wrong roles |
| Media | Media panel | Decoder, buffered ranges, dropped frames, events | Stutter, no hardware decode |
| Everything in time | Performance | Every thread, every event, with vitals and interactions | Any "why was that slow" |
How DevTools works: the protocol
DevTools is a web application that asks the browser questions over a JSON protocol. Understanding that removes the mystery, explains what the panels can and cannot show, and opens the same door to scripts: Puppeteer, Playwright, Lighthouse and remote debugging all speak the Chrome DevTools Protocol.
- Front end. TypeScript, in the Chromium repository under
devtools-frontend. It renders in its own process (docked or undocked, it is a separate renderer). It is served from the browser's resources; you can also point Chrome at a custom build. - Protocol. Domains (DOM, CSS, Network, Page, Runtime, Debugger, Profiler, HeapProfiler, Target, Emulation, Overlay, Storage, ServiceWorker, Tracing, and more). Each has commands (request and reply with an id) and events. The schema is published and versioned; the browser also exposes it at
/json/protocolon a debugging port. - Back end. In the browser process, agents for Network, Target, Browser. In each renderer,
InspectorDOMAgent,InspectorCSSAgent,InspectorNetworkAgentand others in Blink, and V8's own inspector for Runtime, Debugger, Profiler and HeapProfiler. These hook directly into the engine: the Styles pane's "matched rules" is the style engine's own matching, run again for one element. - Transport. An internal pipe when DevTools is attached in-process; a WebSocket when remote (
--remote-debugging-port, or--remote-debugging-pipefor automation).
- Everything DevTools shows is scriptable. Puppeteer's
page.evaluateis Runtime.evaluate;page.screenshotis Page.captureScreenshot; Lighthouse's traces are Tracing.start and the trace events. - Some things DevTools shows are not free. Enabling the Network domain makes the browser record bodies; enabling Debugger changes V8's compilation (no lazy parsing in some cases); paint instrumentation slows rendering. An open DevTools is a different browser; close it when measuring.
- Remote debugging is the same protocol over USB: chrome://inspect for Android Chrome and WebViews; Safari's Web Inspector for iOS. The phone is where most performance bugs live; this is how you see them.
- The Protocol Monitor (Settings → Experiments) shows every message. Watch what the Styles pane asks when you select an element; then ask it yourself from a script.
- Other engines: Firefox DevTools uses the Remote Debugging Protocol; Safari uses the Web Inspector protocol; WebDriver BiDi is the cross-browser standard being built from both CDP and WebDriver.
The debugger: seven kinds of breakpoint
Most people use line breakpoints and console.log. The debugger has six other ways to stop, each of which answers a "who did this" question that a line breakpoint cannot, because you do not know which line yet.
- Line. Click the gutter. Pause before the statement.
- Conditional. Right-click the gutter, add a condition. Pause when true. For the 400th iteration or the one with the bad id.
- Logpoint. Same menu; prints an expression without pausing. A console.log you do not have to rebuild for, and that does not alter timing much.
- DOM. Elements → right-click → Break on: subtree modifications, attribute modifications, node removal. The debugger stops inside whatever code changed the node, through any framework.
- Event listener. Sources → Event Listener Breakpoints: categories of events (Mouse, Keyboard, Timer, Load, XHR, Animation, Control, Clipboard, DOM Mutation, Media, Pointer, Touch, Worker). Pause in the first handler for the ticked event. Who handles this click; who set this timer; who added an unload listener.
- XHR / fetch. Sources → XHR/fetch Breakpoints: URL substring. Pause where the request was issued, with the stack. Who hits this endpoint; why twice.
- Exception. The pause icon: uncaught, and optionally caught. Stops at the throw site with the live state. For "an error happens somewhere in the promise chain": tick caught exceptions and let it find the origin.
- Async stacks. The Call Stack includes the await, the setTimeout, the click that led here, as grey "async" frames. The answer to "how did we get into this callback".
- Scope and hover. Every variable in Local, Closure, Global; hover an identifier in the source for its value; edit a value in the console and continue.
- Restart frame. Rerun the current function from the top. Fix-and-retry without a reload.
- Ignore list. Mark node_modules and framework files as ignored; stepping skips them; stacks collapse them. The difference between stepping through your code and stepping through React.
- Live edit and Overrides. Edit a source file in Sources and save: V8 hot-swaps the function if its shape allows. Overrides: map a remote file to a local copy that persists across reloads; patch a third-party script or a production bundle to test a fix.
- Source maps. Served or inline; DevTools shows original source, breakpoints map both ways, stacks are symbolicated. Production builds should ship source maps to a restricted location (or upload to the error tracker) rather than none.
The Console beyond log
- Context selector. The dropdown at the top: run in the top frame, any iframe, any worker, the service worker, or an extension. Most "undefined is not a function" confusions in multi-frame pages are the wrong context.
- Utilities.
$0through$4(the selected elements, most recent first),$(sel)and$$(sel),$x(xpath),inspect(obj),copy(obj),keys,values,monitor(fn)(log every call with args),monitorEvents(el, 'click'),getEventListeners(el),queryObjects(Ctor)(every live instance of a class: a leak probe),debug(fn)(break on entry). - Formatting.
console.tablefor arrays of objects;console.groupandgroupCollapsed;console.dirfor a DOM node's properties rather than its markup;%o %s %d %cformat specifiers;console.time/timeEnd;console.count;console.tracefor a stack where you are;console.assert. - Live expressions. The eye icon: an expression re-evaluated continuously.
document.activeElementwhile tabbing;performance.memory.usedJSHeapSizewhile clicking. - Filtering. By level, by text, by regex, by
-url:negation; hide network messages; group similar; preserve log across navigations. - Issues. The Issues panel is the structured version of console warnings: each with a description, the affected resources, and the fix. Cookies, CORS, CSP, mixed content, deprecations, accessibility.
- console.log of an object keeps a reference until the console is cleared: a leak detector that leaks.
- Logging in a hot path (scroll, rAF, mousemove) is itself a long task. Use a logpoint or a counter.
- Objects are shown live: the expanded view reflects the object's state when you expand it, not when it was logged.
structuredCloneorJSON.stringifyfor a snapshot.
The panels most people have not opened
| Panel | Where | What it does | When it is the answer |
|---|---|---|---|
| Rendering | More tools | Paint flashing, layout shift regions, layer borders, FPS meter, scrolling performance issues, emulate media (prefers-color-scheme, reduced-motion, print), vision deficiencies, disable local fonts, emulate focused page | Jank, layer debugging, dark mode and print without changing OS settings, "does this work for deuteranopia" |
| Layers | More tools | The compositor layer tree, 3D, with each layer's size, memory, and compositing reason | Layer explosion; GPU memory; "why does this element have its own layer" |
| Performance monitor | More tools | Live CPU, JS heap, DOM nodes, listeners, layouts and recalcs per second | Leak confirmation; "is layout happening on every scroll" |
| Coverage | More tools | Per file, bytes of JS and CSS used versus unused on this load | Finding dead code to split or drop; critical CSS extraction |
| Network conditions | More tools | User agent override, Accept-Language, throttling profiles, disable cache | Testing a UA-sniffed path; a language-negotiated page |
| Sensors | More tools | Geolocation override, orientation, idle state, touch emulation | Location-dependent features; device orientation |
| CSS Overview | More tools | Colours, fonts, unused declarations, contrast issues, media queries across the page | A design-system audit in one click |
| Animations | More tools | Captures animations and transitions, scrubs, slows, shows easing curves | Tuning a transition; seeing what animated when |
| Changes | More tools | A diff of every style edit you made in DevTools | Copying a prototyped fix back into the codebase |
| Recorder | More tools | Record a user flow, replay it, export as Puppeteer or Playwright, measure with Performance | Reproducing an interaction consistently for tracing |
| WebAudio / WebAuthn / Media | More tools | Audio graph inspector; virtual authenticators; media element internals | Each one's domain |
| Device mode | Toolbar toggle | Viewport, DPR, touch, UA, throttling presets; device frames; media query bar | Responsive checks; but not a substitute for a real phone for performance |
| Lighthouse | Tab | Lab audit with scores and pointers; also via CLI and CI | A first pass; a checklist; a regression gate |
chrome:// pages: the engine's own instruments
- chrome://process-internals: which sites are in which process; site isolation mode; frame trees. The proof of parts 0 and 9.
- chrome://tracing and chrome://tracing with ui.perfetto.dev: the full tracing system DevTools' Performance panel is a view of. Record categories DevTools does not show (GPU, IPC, memory-infra, V8 internals, blink.user_timing, disabled-by-default-*). For a question the Performance panel cannot answer, this can.
- chrome://gpu: hardware acceleration status per feature (canvas, compositing, raster, video decode, WebGL, WebGPU), the GPU and driver, problems detected, and why a feature is software-only. The first stop for "video is using 60% CPU" and "canvas is slow on this machine".
- chrome://net-export: a full network log (NetLog) including DNS, sockets, TLS, HTTP/2 and QUIC frames, cache decisions. Load it in netlog-viewer. The Network panel's Timing tab is a summary of this.
- chrome://discards: tab lifecycle states; freeze and discard tabs on demand to test part 10's handling.
- chrome://serviceworker-internals: every registration, its version, running state, with Start, Stop, Unregister, and the console log of each worker.
- chrome://indexeddb-internals, chrome://quota-internals: per-origin storage sizes, open connections, and the quota calculation.
- chrome://histograms: Chrome's own UMA histograms, searchable, for the instance: e.g.
PageLoad.PaintTiming.NavigationToLargestContentfulPaint2. The field metrics, locally. - chrome://flags: experimental features; chrome://version: the command line it was launched with (check your flags took); chrome://memory-internals and the Task Manager (Shift+Esc): memory per process, per site, with GPU memory.
- about:blank? no; but view-source: and chrome://inspect/#devices for remote targets.
A triage procedure: symptom to panel
- "The page is slow to appear." Network: document row Timing (TTFB?). Then Performance: Timings lane for FCP and LCP; the LCP phases; render-blocking requests in Insights.
- "It is visible but I cannot click anything." Performance: Main lane between FCP and the first interaction; long tasks; TBT. Usually script execution or hydration.
- "Clicking is laggy." Performance: Interactions lane; the phases; the handler in the Main lane. Then Bottom-Up by function.
- "Scrolling stutters." Rendering: Scrolling performance issues overlay (non-passive listeners); paint flashing (repaint on scroll); Performance: Frames lane and whether Main is busy during scroll; Layers for layer count.
- "An animation is janky." Rendering: paint flashing (should be none for a compositor animation); Performance: purple and green per frame means layout or paint is animating; Animations panel for the curve.
- "Things jump around while loading." Performance: Layout Shifts lane; click each; Rendering: Layout Shift Regions.
- "Memory grows." Performance monitor to confirm; Memory: three snapshots, compare, Detached filter, Retainers.
- "The style is wrong." Elements: Styles (crossed-out means overridden; the winner is uppermost), Computed with the "show all" and filter; Layout pane for grid and flex.
- "The request did not happen / was blocked / returned the wrong thing." Network: Preserve log on; the row's Headers, its Initiator, its Cookies tab; Console and Issues for CORS and CSP; Application → Service Workers for a stale SW; Network conditions to disable cache.
- "It works on desktop, not on the phone." Remote debug the phone (chrome://inspect); record a Performance trace there; check chrome://gpu on the device for acceleration.
- "It works for me, not for the user." Field data (CrUX, RUM) by device and connection; reproduce the condition with throttling and the user's state; then the above.
- "Who changed this / called this / set this." DOM breakpoint; XHR breakpoint; event listener breakpoint;
monitor(fn);getEventListeners.
The DevTools course's lab app has a route for every row above, each with the pathology planted and the panel that reveals it. This part was the map; that course is the territory.