Chrome DevTools Cheatsheet - Front-end Debugging Reference

Console.log poking is a poor substitute for stepping through a live page. This reference covers Elements and DOM breakpoints, console tricks, Network waterfall and request replay, Performance flame charts, and Application storage. Use it when a page works on your laptop but misbehaves in production — isolate a layout bug, find a slow request, or trace a storage leak. After reading you inspect, measure and fix frontend problems from inside the browser instead of guessing.

Dev Tools·54 commands·Last updated 2026-07-21
chromedevtoolsDebugging

Typical Use Case

For web developers and testers who need to pin down front-end problems precisely. Six panels form one investigation path: Console for logging, timing, counting and interactive element picking with $0; Elements for editing HTML, forcing pseudo-states, and breaking on DOM changes to find who changed a style; Network for filtering, throttling, replaying requests and copying a failed call as cURL; Performance for locating jank in the main thread and flame chart; Application for local storage, cookies, IndexedDB and service workers. The two highest-value habits are Ctrl+Shift+C followed by $0 to verify a change live, and turning a failed request into a cURL command you can rerun in a terminal.

Shortcuts 8

F12 or Cmd+Option+I
Open DevTools (macOS)
F12 or Ctrl+Shift+I
Open DevTools (Win/Linux)
Cmd+Option+J
Open Console (macOS)
Cmd+Option+E
Open Elements (macOS)
Cmd+Shift+C
Select-element mode
Cmd+Shift+P
Open the command menu
Cmd+P
Quick open file
Cmd+Shift+M
Toggle device emulation

Console Commands 12

console.log("message")
Log a message
console.table(array)
Print as a table
console.time("label") / console.timeEnd("label")
Timing
console.count("label")
Count
console.group("group") / console.groupEnd()
Group
console.assert(condition, "error")
Assert
console.dir(element)
Print a DOM object
copy(document.title)
Copy to clipboard
$0
Currently selected DOM element
$("selector")
Query selector (like querySelector)
$$("selector")
Query all matching elements
monitorEvents(element, "click")
Monitor events

Elements Debugging 9

Edit as HTML
Edit element HTML
Toggle Edit as HTML
Toggle edit-as-HTML mode
Force Element State (:hover, :active)
Force element state (:hover, :active)
Break on: subtree modifications
Break on: subtree modifications
Break on: attribute modifications
Break on: attribute modifications
Store as global variable
Store as global variable
Copy selector
Copy CSS selector
Copy XPath
Copy XPath
Delete node
Delete node

Network Analysis 10

Disable cache
Disable cache
Throttling: Slow 3G
Network throttling
Filter: Doc, JS, CSS, Img, XHR
Filter by type
Filter: -domain:example.com
Exclude a domain
Filter: status-code:404
Filter by status code
Filter: is:from-cache
Cache requests
Replay XHR
Replay XHR
Copy as cURL
Copy as cURL
Save as...
Save as...
Block request URL
Block request URL

Performance 7

Record
Record performance data
Screenshots
Screenshots
Memory
Memory analysis
Main thread
Main thread analysis
Flame Chart
Flame Chart
Bottom-Up / Call Tree
Bottom-Up / Call Tree
Summary
Summary

Application Storage 8

Local Storage
Local Storage
Session Storage
Session Storage
Cookies
Cookie management
IndexedDB
IndexedDB viewer
Cache Storage
Service Worker cache
Clear site data
Clear site data
Service Workers
Service Worker management
Manifest
PWA Manifest

Parameter matrix

ParameterEffectExample
F12 / Cmd+Option+IRender an array of objects as an aligned table instead of a collapsed tree.F12
F12 / Ctrl+Shift+IReference the element currently selected in the Elements panel without querying for it again.Ctrl + Shift + I
Cmd+Option+JQuery a single element or every matching element, returning real DOM nodes rather than a static list.Cmd + Option + J
Cmd+Option+ELog every event of a type that an object receives, including the ones fired before you attached the listener.Cmd + Option + E
Cmd+Shift+CTurn a captured request into a runnable curl command so you can reproduce it outside the browser.Cmd + Shift + C
Cmd+Shift+PNegative-filter the request list so third-party traffic stops hiding the requests you care about.Cmd + Shift + P
Cmd+PRe-issue a captured XHR/fetch request against the running server to see whether a bug is client-side or server-side.Cmd + P
Cmd+Shift+MBypass the HTTP cache for every subsequent request so a stale bundle cannot mask your changes.Cmd + Shift + M
console.log("message")Pause execution whenever the DOM under the selected node changes, which catches code rewriting markup indirectly.console.log("message")
console.table(array)Produce a selector for the inspected element, which you can paste into a test or a query.console.table(rows)
console.time("label") / console.timeEnd("label")Capture a trace of the main thread and the compositor, from which the flame chart and layout-shift metrics are derived.console.time("render"); console.timeEnd("render");
console.count("label")Pin an inspected element or object to a global name so it survives across console evaluations.console.count("render")
console.group("group") / console.groupEnd()成组输出日志console.group("init"); console.groupEnd();
console.assert(condition, "error")条件不成立时输出断言信息console.assert(el, "error")
console.dir(element)展开打印 DOM 对象console.dir($0)
copy(document.title)把结果复制到剪贴板copy(document.title)
$0引用当前选中的 DOM 元素$0.style.color = "red";
$("selector")查询单个元素(类似 querySelector)$(".card")
$$("selector")查询所有匹配元素$$("li")
monitorEvents(element, "click")监控目标元素上的事件触发monitorEvents($0, "click")
Edit as HTML直接编辑元素 HTML在 Elements 中右键 → Edit as HTML
Force Element State (:hover, :active)强制元素状态以便调试交互样式右键节点 → Force Element State → :hover
Break on: subtree modificationsDOM 子树变化时断下右键节点 → Break on → subtree modifications
Break on: attribute modifications属性变化时断下右键节点 → Break on → attribute modifications
Store as global variable把节点存为全局变量供 Console 使用右键节点 → Store as global variable
Copy selector / Copy XPath复制选择器或 XPath 路径右键节点 → Copy selector
Delete node删除该 DOM 节点右键节点 → Delete node
Disable cache禁用缓存,确保每次都是新资源Network 面板勾选 Disable cache
Throttling: Slow 3G网络限速模拟弱网Throttling 选 Slow 3G
Filter: Doc, JS, CSS, Img, XHR按资源类型过滤请求Filter 输入 XHR
Filter: -domain:example.com按域名排除请求Filter 输入 -domain:example.com
Filter: status-code:404按状态码过滤Filter 输入 status-code:404
Filter: is:from-cache只看缓存命中的请求Filter 输入 is:from-cache
Replay XHR重放选中的请求右键请求 → Replay XHR
Copy as cURL复制为 cURL 命令到终端重放右键请求 → Copy as cURL
Save as...把响应体保存到本地右键请求 → Save as...
Block request URL拦截匹配 URL 的请求右键请求 → Block request URL
Record录制性能数据Performance 面板 → Record
Screenshots录制期间逐帧截图Performance 面板 → Screenshots
Memory内存分析视图Performance 面板 → Memory
Main thread主线程任务与耗时分析查看 Main thread 轨道
Flame Chart火焰图定位耗时函数查看 Flame Chart
Bottom-Up / Call Tree自底向上 / 调用树视角查看 Call Tree
Summary时间分布汇总查看 Summary
Local Storage / Session Storage查看本地/会话存储Application → Local Storage
CookiesCookie 管理Application → Cookies
IndexedDB查看 IndexedDB 数据Application → IndexedDB
Cache Storage查看 Service Worker 缓存Application → Cache Storage
Clear site data清除该站点的所有本地数据Application → Clear site data
Service WorkersService Worker 注册与状态Application → Service Workers
Manifest查看 PWA ManifestApplication → Manifest

Common pitfalls

SymptomA local edit never reaches the browser and the old code keeps running.

CauseDevTools is open with Disable cache enabled but the page was loaded from the HTTP cache, or a service worker is serving a stale precached bundle.

FixHard-reload with Ctrl+Shift+R, then check Application > Service Workers for an active worker and unregister it if it owns the scope.

SymptomLocal file edits made in DevTools disappear on reload.

CauseEdit as HTML only patches the live DOM; it never writes to disk.

FixUse it to find the right markup, then reproduce the change in your source file and let Live Reload push it back.

SymptomA breakpoint never hits even though the code obviously runs.

CauseThe bound file is a different copy of the source than the one running — a source map points at the original file, or a bundled/minified build is loaded instead.

FixSet the breakpoint in the file the Sources panel shows, and verify the mapping under DevTools > Settings > Debugger > Source Maps.

SymptomBreakpoints pause in a loop inside library code instead of in application code.

CauseBlackboxing is off, so the debugger enters node_modules or framework internals that also match your XHR/fetch break conditions.

FixRight-click the frame you do not care about and choose Blackbox script content, or use a conditional breakpoint on your own function.

SymptomThe Network panel shows nothing even though requests are clearly being made.

CauseRecording was off, or the requests are issued inside a Web Worker / Service Worker whose own network traffic is filtered out.

FixTurn recording on and reload; enable the service worker frames filter in the panel options, or check the worker console separately.

SymptomEditing Local Storage does not survive a page reload.

CauseThe page writes the same key back into Local Storage on every load, overwriting the value you just set.

FixSet a breakpoint on the assignment, or change the value while a debugger pause holds the write path, then resume.

SymptomA throttled CPU profile shows 100% busy while the page feels perfectly responsive.

CauseCPU throttling simulates a slow device for the tab being profiled; a long task inside a worker or a synchronous timer can still keep the main thread at 100%.

FixRead the flame chart by "Main thread" and the Bottom-Up tab to find the self-time hot spots instead of trusting the busy percentage alone.

Symptom改 Local Storage 或 Cookie 后页面行为没变化,像是没保存上

Cause存储面板显示的是当前文档状态的快照;写入需要通过页面自身代码或手动编辑触发,部分站点还有同源与服务端状态校验。

Fix手动改值后回车写回并刷新页面确认;若仍无效,用 Console 执行一次写入再读取校验,区分是存储没写成功还是逻辑不读该键。

Troubleshooting

  1. 1Start from the console, where the error names the line

    Cmd+Shift+C 选中元素 → 右键 → Break on → attribute modifications → 重新触发

    Anything the page did to the DOM can be checked here; if it returns null, the selector or the render is the problem, not your code.

  2. 2Reproduce a request as a shell command

    $0.style.color = "red"; $$(".card").length; copy($0.outerHTML)

    Copy as cURL from the Network panel gives you the exact headers and body, so you can tell a server bug from a client bug.

  3. 3Find the handler that owns a click

    console.time("render"); /* 可疑操作 */ console.timeEnd("render");

    Attach this to the selected element to see the event and which listeners Chrome has bound to it.

  4. 4Test the DOM for stale mutations

    Filter 输入 status-code:404 → 右键请求 → Copy as cURL → 终端执行

    Dumping the markup shows whether a framework actually rendered what you expected or the node is still empty.

  5. 5Break on the moment the value changes

    勾选 Disable cache → Throttling 选 Slow 3G → 刷新页面

    Chrome exposes bound listeners on the element, which tells you whether the click handler was ever attached.

  6. 6录制并分析一次真实卡顿

    Performance → Record → 触发操作 → Stop → 查看 Main thread / Flame Chart / Call Tree

    录制时不要切换标签页以免噪声。Flame Chart 里找最宽的调用块确定耗时函数,Call Tree 从上往下确认调用路径,Summary 给出整体时间分布,三视图合看能快速锁定瓶颈。

  7. 7排查本地状态与缓存残留

    Application → Local Storage / Cookies / Cache Storage / Service Workers → Clear site data → 刷新

    先分别检查四个存储位置有无陈旧数据,再统一清除站点数据并刷新。若清除后行为恢复正常,说明问题出在本地状态或 Service Worker 缓存而非代码本身。

Command Examples

Grab a direct reference to the selected element

Cmd+Shift+C $0 $$("table tbody tr") console.table($$("table tbody tr").map(r => r.cells[0].textContent))

$0 is whichever node is currently highlighted in the Elements panel — use it as your entry point in the console. $$ returns an array, and pairing it with console.table flattens table data at once instead of expanding nodes one by one.

Copy as cURL to reproduce a request

Network 面板 → 右键请求 → Copy as cURL

When a request fails intermittently, turn it into a command line: replay it outside the page, and drop one header at a time to find the culprit. Strip Cookie and Authorization before pasting anywhere.

Filter by status code to isolate failures

Filter: status-code:404 Filter: -domain:example.com

A slow page is usually the sum of dozens of requests. Filtering by status code shows what is genuinely failing, and excluding third-party domains strips analytics and font noise so you see only your own traffic.

Time a block of code to find the synchronous block

console.time("parse"); // 待测代码 console.timeEnd("parse");

Console timing is lighter than the Performance panel and suits bisecting: wrap chunks of a long routine and time each one — the offender is whichever blows past the others. Use the Performance panel only when you need flame charts and call trees.

Output

parse: 312.7ms

Catch third-party DOM mutations with a subtree breakpoint

Break on: subtree modifications

When a node vanishes for no visible reason, the Elements panel will not tell you who removed it. A subtree breakpoint pauses the moment a script mutates the structure, and the call stack names the script.

Common Pitfalls

  • Leaving "Disable cache" checked makes you debug stale assets and chase a bug that no longer exists in your code.
  • "Copy as cURL" embeds Cookie, Authorization, and CSRF tokens — pasting that into an issue, a chat, or a public repo hands over a live session.
  • A throttling preset can outlive the DevTools window in some versions, so every later test runs slow for reasons unrelated to the code.
  • "Edit as HTML" changes are temporary and vanish on reload. Never treat them as a fix — the real change belongs in the source file.
  • "Clear site data" wipes local and session storage, cookies, and caches. Running it mid-investigation destroys the login state and the localStorage fixtures you were reproducing against.
  • Force Element State (:hover/:active) is a visual simulation that fires no real JS events, so it cannot tell you whether click logic actually works.

Tips

  • $0 in Console is the currently selected DOM element, directly operable.
  • Right-click in the Network panel and Copy as cURL to replay a request in the terminal.
  • When recording in the Performance panel, avoid other tabs open, which hurts accuracy.

FAQ

What are $0, $(...) and $$(...) in the Console, and how do they pair with Elements?

Once you select a node in the Elements panel, $0 refers to that element and you can operate on it directly: $0.style.color = "red" or $0.remove(). $("selector") is querySelector and returns one match; $$("selector") is querySelectorAll and returns a NodeList you can then .forEach over. To get a complicated selected element out of the panel, use Store as global variable to keep it as a global, or console.dir(element) to print the DOM object's properties — console.log alone only gives you an "[object HTMLDivElement]" summary.

How do I use Console timing to find out which part of a piece of code is slow?

Pair console.time("label") with console.timeEnd("label") using the same label; repeating a start warns and a missing end prints nothing. Wrap each suspicious stage — console.time("parse") around parsing, console.time("render") around rendering — and compare the two numbers in the Console, then subdivide whichever is larger. Alongside it, console.count("label") counts invocations and exposes redundant calls inside a loop, console.group / console.groupEnd collapse noisy output, and console.assert(condition, "error") checks an invariant.

How do I filter the Network panel down to the requests that actually misbehave?

The filter box combines conditions: narrow by type — Doc, JS, CSS, Img, XHR — to drop static-asset noise; -domain:example.com excludes a domain; status-code:404 pins every 404; is:from-cache surfaces cache hits. Pair it with Disable cache and reload to check whether caching is masking the problem, Throttling: Slow 3G to reproduce weak-network behaviour, and Block request URL to deliberately break a request and verify your fallback. Once you have the request, right-click Copy as cURL and replay it in the terminal.

How do I set things up to reproduce a bug that only shows on mobile?

Cmd + Shift + M toggles device emulation; once a device is selected you can edit the HTML directly in Elements, and Force Element State pins :hover / :active so interactive styles become inspectable. Cmd+Shift+C puts you in the element picker for clicking straight on the real page. When the bug involves storage, move to the Application panel to inspect Local Storage, Session Storage, Cookies, IndexedDB and Cache Storage, and use Clear site data to wipe state before reproducing so leftovers do not confuse you; Service Workers and Manifest panels cover PWA issues.

How do I read the flame chart produced by the Performance panel?

Hit Record to capture (and avoid touching other tabs while recording, or you pollute the data), then use Screenshots to grab the frame where the jank is visible. Bottom-Up sorts by Self Time, telling you directly which functions burn the most CPU; Call Tree expands the stack so you can find who called the slow code. Summary shows how time is distributed across phases, and the Memory panel alongside it reveals whether the JS heap keeps growing during the capture. The workflow is: locate the longest slice in Summary, then identify the culprit in Bottom-Up.

Official References

Each command links to its official documentation below, so you can verify the latest usage and read deeper.

Maintained by LaoHand

Publicly updated on Jul 21, 2026, continuously proofread against official docs.

Contact Us

Wrong command or description? Send us corrections, business inquiries or product feedback by email.

Contact Us